CSS之面试题(二)
一、计算属性calc()的使用
1. 定义及用法
calc() 函数用于动态计算长度值。 语法:calc(expression)
.ele{ width:calc(100% - 20px); }
2. 注意事项
- 需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px)。
- 任何长度值都可以使用calc()函数进行计算。
- calc()函数支持 "+", "-", "*", "/" 运算。
- calc()函数使用标准的数学运算优先级规则。
二、--CSS变量
1. 概念
var() 函数用于插入 CSS 变量的值。CSS 变量可以访问 DOM,这意味着您可以创建具有局部或全局范围的变量,使用 JavaScript 来修改变量,以及基于媒体查询来修改变量。
使用 CSS 变量的一种好方法涉及设计的颜色。您可以将它们放在变量中,而不必一遍又一遍地复制和粘贴相同的颜色。
2. 语法
var() 函数的语法如下:var(name, value)
- name必需,变量名(以两条破折号开头)。
- value可选。回退值(在未找到变量时使用)。
- -- 前缀通常被用在类中,是CSS中对变量声明的前缀。
:root { --blue: #1e90ff; --white: #ffffff; } .container { color: var(--blue); background-color: var(--white); padding: 15px; }
三、伪类和伪元素
使用伪元素的时候,总是感觉和伪类很相似,但又不能详细的说出两者的区别和联系,那么两者到底有什么区别和联系呢?
1.伪元素/伪对象
不存在在DOM文档中,是虚拟的元素,是创建新元素。代表某个元素的子元素,这个子元素虽然在逻辑上存在,但却并不实际存在于DOM树中。
伪元素选择符是指为一个HTML元素的各种状态和部分内容定义样式的一种方式。
☘️ 1. 前端CSS中的伪元素选择符有以下几种:
- ::after:在元素的最后面添加一个伪元素,通常用于添加内容。
- ::before:在元素的最前面添加一个伪元素,通常用于添加内容。
- ::first-letter:用于选中元素中的第一个字母。
- ::first-line:用于选中元素中的第一行文字。
- ::selection:用于选中元素中被用户选中的文本部分。
- ::placeholder 用于设置输入框或文本域中placeholder属性设置的文字的样式。
☘️ 2. 伪元素使用时的注意事项
- 伪元素如果没有设置content属性,那么伪元素是无用的(可以将伪元素的内容设置为空)
- 插入的内容在页面的源码里是不可见的,只能在css里面可见。
- 插入的伪元素默认情况是内联元素,因此,为了给插入元素赋予高度,外边距、填充等等,必须显式定义它是一个块级元素。
- 典型的css继承规则适用于插入的伪元素,比如,插入的字体系列,然后伪元素会像其他元素一样继承这些字体系列,同样的,伪元素不会继承没有自然继承自父元素(如padding和margin)的样式。
- 使用伪元素插入非文本内容。
2. 伪类
存在DOM文档中,逻辑上存在但在文档树中却无须标识的“幽灵”分类,用来表示元素的一种状态。
☘️ 1.动态伪类选择器
- :link。元素被定义了超链接但并未被访问过
- :visited。元素被定义了超链接并已被访问过
- :active。元素被激活
- :hover。鼠标悬停
- :focus。元素获取焦点
a 标签的这四种伪类选择器的顺序为:a:link ,a:visited,a:hover ,a:active
。必须严格按照此规则来设置属性,否则无效。
☘️ 2. UI 元素状态伪类选择器
- :checked。选中的复选按钮或者单选按钮表单元素
- :enabled。所有启用的表单元素
- :disabled。所有禁用的表单元素
☘️ 3. 结构伪类选择器
first-child
: 元素得是其父元素的第一个子元素才匹配:last-child
: 元素得是其父元素的最后一个子元素才匹配:nth-child(n)
: 元素得是其父元素的第n个子元素才匹配:nth-last-child(n)
: 元素得是其父元素的倒数第n个子元素才匹配:only-child
: 元素得是其父元素的唯一一个子元素才匹配:first-of-type
: 元素得是其父元素的第一个该类元素才匹配:last-of-type
: 元素得是其父元素的最后一个该类元素才匹配:only-of-type
: 元素得是其父元素的唯一一个该类元素才匹配:nth-of-type(n)
: 元素得是其父元素的第n个该类元素才匹配:nth-last-of-type(n)
: 元素得是其父元素的倒数第n个子元素才匹配not
: 排除元素 例: li:not(:first-child): 元素不是其父元素的第一个子元素的li元素被匹配
3. 伪类与伪元素的区别与联系
- 在计算权重的时候 :伪类与类优先级相同 、伪元素与标签优先级相同
- 伪类与伪元素都是用于向选择器加特殊效果
- 伪类与伪元素的本质区别就是是否抽象创造了新元素
- 伪类只要不是互斥可以叠加使用
- 伪元素在一个选择器中只能出现一次,并且只能出现在末尾
- 伪类与伪元素优先级分别与类、标签优先级相同
四、什么是响应式?
跟随用户页面设备尺寸的变化,页面实现自动的适配
比如你逛掘金的商城页面,缩放页面的时候发现1000-1160宽是一个适配,1160以外又是一个适配
实现方案
☘️ 1. 弹性布局:适合做某个容器内的响应式,比如ul
的li
,但是不方便做整个页面的响应式
弹性容器默认就是让子元素在收缩放大时平均分配
☘️ 2. 百分比:常适用于页面外层大容器,同样不适合整个页面的响应式,一般适配都是pc端一个,平板一个,手机一个,百分比过于灵活不适合。
百分比继承父容器
☘️ 3. rem + 媒体查询 (可用于任何地方,一般pc端是rem + 媒体查询,移动端是rem + js)
rem是参照根字体大小,css有媒体查询的语法,写法参考如下,min-width
到max-width
就是区间
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } li{ list-style: none; width: 200px; height: 100px; } li:nth-child(1){ background-color: antiquewhite; } li:nth-child(2){ background-color: aqua; } li:nth-child(3){ background-color: aquamarine; } li:nth-child(4){ background-color: azure; } li:nth-child(5){ background-color: black; } li:nth-child(6){ background-color: blueviolet; } </style> <style> li { width: 10rem; /* pc端用媒体查询 移动端用js处理 */ } @media screen and (min-width: 1000px) { /* 大于1000时 变化 pc端 */ html{ font-size: 30px; } } @media screen and (min-width: 800px) and (max-width: 1000px) { /* 平板端 */ html{ font-size: 20px; } } @media screen and (max-width: 500px) { /* 手机端 */ html{ font-size: 14px; } } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> </body> </html>
☘️ 4. 直接媒体查询,不如第三个方法,这个代码量会很大
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } li{ list-style: none; width: 200px; height: 100px; } li:nth-child(1){ background-color: antiquewhite; } li:nth-child(2){ background-color: aqua; } li:nth-child(3){ background-color: aquamarine; } li:nth-child(4){ background-color: azure; } li:nth-child(5){ background-color: black; } li:nth-child(6){ background-color: blueviolet; } </style> <style> @media screen and (min-width: 1000px) { li{ width: 300px; } } @media screen and (min-width: 800px) and (max-width: 1000px) { li{ width: 200px; } } @media screen and (max-width: 500px) { li{ width: 100px; } } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> </body> </html>
5. vw
/vh
:相对于window大小
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } li{ list-style: none; width: 200px; height: 100px; } li:nth-child(1){ background-color: antiquewhite; } li:nth-child(2){ background-color: aqua; } li:nth-child(3){ background-color: aquamarine; } li:nth-child(4){ background-color: azure; } li:nth-child(5){ background-color: black; } li:nth-child(6){ background-color: blueviolet; } </style> <style> li{ width: 20vw; } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> </body> </html>
五、什么是重绘与回流?
1. 概念:
当renderTree发生因为元素的规模尺寸,布局,隐藏等改变而需要重建时,这就称为回流。每个页面在第一次加载时至少要经历一次回流。
当renderTree中的一些元素需要更新属性,但这些属性只会影响元素外观,风格,而不影响布局时,比如background-Color则叫重绘。
回流必将引起重绘,重绘不一定引起回流。
2. 引起回流的方式?
- 页面初始化时,DOM载入后的第一次回流,将会遍历所有frame。最消耗性能的一次回流;
- 删除或者添加可见的元素时;
- 元素的位置发生改变时;
- 元素的大小改变时(例如改变了元素的内外边距,宽高,边框大小);
- 元素的内容发生变化(字体、文字、图片更换);
- 改变浏览器窗口尺寸(例如 resize 事件发生时);
- 样式改变(StyleChange)。整个frame树都应得到遍历;
- Css伪类激活
- 设置 style 属性的值,因为通过设置 style 属性改变节点样式的话,每一次设置都会触发一次回流;
- 查询某些属性或调用某些计算方法:offsetWidth、offsetHeight 等,会触发回流,为了 “即时性” 和 “准确性” ;
- Dom操作。
3. 引起重绘的方式?
- 可见性(visibility)和透明度(opacity)的改变;2.
- 颜色的改变;
- 背景的改变;
- 阴影、轮廓的改变;
- 文本方向(text-decoration)的改变等。
4. 如何减少回流、重绘?
可以看到每次DOM元素的样式操作都会引发重绘,如果涉及布局还会引发回流。避免大量页面回流的手段也有很多,其本质都是尽量减少引起回流和重绘的DOM操作:
- 避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
- 避免循环操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。 3.避免循环读取offsetLeft等属性。在循环之前把它们存起来。 4.绝对定位具有复杂动画的元素。绝对定位使它脱离文档流,否则会引起父元素及后续元素大量的回流。
六、padding和margin设值为百分比时的依据是什么?
当一个div padding和margin设置为百分比时,实际上是根据这个div的最近的块级父元素width的值为基准值计算的,这一点一定要注意
css
.child-box { width: 100px; height: 100px; border: 1px solid #ccc; padding: 5%; background-color: blue; margin: 5%; } .parent-box { width: 200px; height: 200px; border: 1px #f00 solid; background-color: #f00; }
html
<div class="parent-box"> <div class="child-box"> </div> </div>
分析:
蓝色盒子的宽=100 + 5% * 200 *2 = 120px,即蓝色盒子的宽 = 自身width + 自身padding的5% * 红色父盒子的宽 * 2document.querySelector(".child-box").clientWidth //120
七、line-heigt和font-size的关系是什么?
line-heigt和font-size是经常用到的属性,但很少有人注意他们的关系
由上图的关系可以看出:
行高(line-heigt) = 字体大小(font-size) + 行距(即2 * 半行距)
八、line-height 如何继承?
⽗元素的 line-height 写了具体数值,⽐如 30px,则⼦元素 line-height 继承该值。
⽗元素的 line-height 写了⽐例,⽐如 1.5 或 2,则⼦元素 line-height 也是继承该⽐例。
⽗元素的 line-height 写了百分⽐,⽐如 200%,则⼦元素 line-height 继承的是⽗元素 font-size * 200% 计 算出来的值。
九、为什么要初始化 CSS 样式 ?
- 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。
- 当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。
最简单的初始化方法:*{padding:0;margin:0;}(强烈不建议)
淘宝的样式初始化代码:
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend ,button,input,textarea,th,td{margin:0;padding:0;} body,button,input,select,textarea{font:12px/1.5tahoma,arial,\5b8b\4f53;} h1,h2,h3,h4,h5,h6{font-size:100%;} address,cite,dfn,em,var{font-style:normal;} code,kbd,pre,samp{font-family:couriernew,courier,monospace;} small{font-size:12px;} ul,ol{list-style:none;} a{text-decoration:none;} a:hover{text-decoration:underline;} sup{vertical-align:text-top;} sub{vertical-align:text-bottom;} legend{color:#000;} fieldset,img{border:0;} button,input,select,textarea{font-size:100%;} table{border-collapse:collapse;border-spacing:0;}