CSS 选择器
什么是 CSS 选择器?
CSS 选择器是选取需设置样式的元素的模式。
CSS有哪些选择器?
基本选择器:
- 通配符选择器
*
:选择所有元素 或 某个元素下的所有元素。 - 元素选择器:以文档的元素作为选择器(如
span
)。 - ID 选择器
#id-name
。 - Class 选择器
.class-name
。 - 后代选择器
E F
:用空格,在 E 的后代中选择所有和 F 匹配的元素,也比较常用。 - 相邻兄弟选择器
E + F
:选择紧接在 E 元素后且和 F 匹配的元素。 - 通用兄弟选择器
E ~ F
:在 E 后的所有兄弟元素中选择与 F 匹配的元素。
属性选择器: [attr="value"]
选择有某个属性其值为 value 的元素。
关于属性选择器的详情,请戳这里。
伪类选择器(如:hover
)也包括 CSS3 的 :nth 系列选择器。
关于伪类选择器的详情,请戳这里
Notice:
:not(*)
匹配任何非元素的元素,因此这个规则将永远不会被应用。
伪元素选择器:
因为 CSS 的伪类选择器是以单引号开头的,为了区分伪类和伪元素选择器,CSS3 将伪元素选择器前面的:
改为::
。支持 CSS3 的浏览器同时也支持 CSS2 中引入的:
写法,:
已过时,仅用来支持 IE8-。
-
::before (:before)
:在备选元素内容前插入内容。/* CSS2 语法 */ p:before { /* style properties */ } /* CSS3 语法 */ p::before { /* style properties */ }
-
::after (:after)
:在被选元素内容后插入内容,同::before
。 -
::section
:选择被用户选择的元素。
只有一小部分 CSS 属性可以用于这个选择器:color
、background-color
、cusor
、caret-color
、outline
、text-decoration
、text-emphasis-color
、text-shadow
。Notice:
background-image
会和其他属性一样被忽略。
CSS 样式优先级 & 计算规则
什么是CSS样式优先级?
浏览器通过优先级来判断哪些属性与一个元素最为相关,从而在该元素上应用这些属性。
大致的判断CSS优先级比较规则:
内联样式 > ID选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 元素选择器 = 伪元素选择器 > 通配符选择器 > 继承样式。
精确的优先级计算规则
我们把特殊性分为4个等级,权重从左右依次降低:
内联样式 | ID选择器 | 类选择器 伪类选择器 属性选择器 | 元素选择器 伪元素选择器 | |
---|---|---|---|---|
权重位 | X,0,0,0 | 0,X,0,0 | 0,0,X,0 | 0,0,0,X |
规则:
- 每个等级的初始值为 0。
- 每个等级的值为选择器出现的次数之和(包括选择器内嵌的选择器)。
- 等级与等级之间不可进位,每个等级计数之间没有关联。
- 权重判断从左向右,如果某一位数值相同,则切换至下一位。
- 若两个优先级相同,则最后出现的优先级高。
- 通配符选择器的优先级为:
0,0,0,0
。 - 继承样式优先级最低,通配符样式优先级高于继承样式。
来看一些示例:
#div1 .div2 {}
/* 0,1,0,0 + 0,0,1,0 => 0,1,1,0 */
div .div2 {}
/* 0,0,0,1 + 0,0,1,0 => 0,0,1,1 */
/* 由于0,1,1,0的第二位值大于0,0,1,1的第二位,所以优先级是上面的高 */
#div1 #div2 ul li.first a {}
/* ID选择器2个{0,2,0,0} 类选择器1个{0,0,1,0} 元素选择器3个{0,0,0,3} => {0,2,1,3} */
#div1 #div2 ui li:not(#first) a {}
/* ID选择器3个{0,3,0,0}(包括:(not)中的#first) 伪类选择器1个{0,0,1,0} 元素选择器3个{0,0,0,3} => {0,3,1,3} */
#div1 #div2 ui li:ntn-type-of(1) a {}
/* ID选择器2个{0,2,0,0} 伪类选择器1个{0,0,1,0} 元素选择器3个{0,0,0,3} => {0,3,1,3} */
选择器性能优化
浏览器读取选择器
浏览器读取选择器遵循的原则是从右到左读取。
div#div1 h1 span { /*...*/ }
/* 如上,浏览器读取选择器的顺序是:
* 1. 查找页面中所有span元素
* 2. 查找1结果的祖先元素中是否有h1元素
* 3. 查找2结果的祖先元素中是否有id=div1的div元素
*/
从右到左的好处:
- 尽早过滤无关样式规则;
- 尽快匹配到目标元素。
选择器的最右边部分(即最后一部分)被成为关键选择器,它决定着CSS选择器的效率。
性能优化
根据「CSS优先级比较规则」和「浏览器读取选择器原则」,我们可以注意一下几点来提升CSS选择器的性能:
-
避免使用通配符选择器。
h1 * { /* ... */ } /* 因为浏览器会先选中所有HTML中的元素,再在其中寻找外层有h1标签的元素 */
-
避免在编写 ID 规则时使用标签名或类名;
div#div1 { /* ... */ } /* 因为HTML中元素ID是唯一的,而ID规则再加标签名会使得浏览器继续验证选中的元素是否是div标签
避免在编写 class 规则时使用标签名。
-
把多层标签选择规则用 class 规则替换,减少CSS查找。
-
避免使用后代组合器。
后代组合器是最昂贵的选择器,特别是用在标签或通配符中The descendant selector is the most expensive selector in CSS. It is dreadfully expensive — especially if the selector is in the Tag or Universal Category. ——David Hyatt
h1 span {} /* 浏览器在找到HTML中所有的span元素后,再层层向外查找选中的span标签外层是否包有h1标签
网上中文文章好多说的是子选择器
>
最昂贵,应该是英文翻译过来的失误。注意!!!最消耗性能的选择器是后代选择器,而不是子选择器。 -
避免单规则和类正则的属性选择器。
-
依赖继承。
-
移除无匹配的样式。
总结:
- 优先考虑使用class选择器,ID选择器效率虽然高,但是要注意HTML标签ID唯一的这个特性。
- 避免使用通配符选择器和属性选择器以及后代选择器与元素选择器结合使用的情况。
- CSS3新出的选择器在锁定元素的精确性和标签干净和语义化的同时,消耗了更多浏览器的资源,所以如果你更考虑性能,应尽量避免使用。