来自《css选择器世界》
css选择器可以分为四类,即选择器,选择符,伪类和伪元素
选择符
/*后代关系*/
.container img { }
/*父子关系*/
ol > lin{ }
/* 相邻兄弟关系*/
button + button {}
/*兄弟关系*/
button ~ button{}
/*列*/
.col || td { }
css选择器优先级的计算规则
每一段css语句的选择器都可以对应一个具体的数值,数值越大优先级越高,其中的css语句将被优先渲染。其中,出现一个0级选择器,优先级数值加0;出现一个1级选择器,优先值数值加1;出现一个2级选择器,优先值数值加10;出现一个3级选择器,优先级数值加100。
选择器 | 计算值 | 计算细则 |
---|---|---|
*{} | 0 | 1个0级通配选择器,优先级数值为0 |
dialog {} | 1 | 1个1级标签选择器,优先级数值为1 |
ul > li {} | 2 | 2个1级标签选择器,1个0级选择符,优先级数值为2 |
li > ol +ol {} | 3 | 3个1级标签选择器,2个0级选择符,优先级数值为0 |
.foo {} | 10 | 1个2级类名选择器,优先级数值为10 |
a:not([rel=nofollow]) {} | 11 | 1个1级标签选择器,1个0级否定伪类,1个2级属性选择器,优先级数值为11 |
a:hover{} | 11 | 1个1级标签选择器,1个二级伪类,优先级数值为11 |
ol li.foo{} | 12 | 1个2级类名选择器,2个1级标签选择器,1个0级空格选择器,优先级数值为12 |
li.foo.bar{} | 21 | 1个2级类名选择器,2个1级标签选择器,优先级数值为21 |
#foo{} | 100 | 1个3级ID选择器,优先级数值为100 |
#foo .bar p {} | 111 | 1个3级ID选择器,1个2级类名选择器,1个1级标签选择器,优先级数值为111 |
不要使用ID选择器:
* 优先级太高。ID选择器的优先级实在是太高了,如果我们想要重置某些样式,必然还需要ID选择器进行覆盖,再多的类名都没有用,这会使得整个项目选择器的优先级变得非常混乱。如果非要使用元素的ID作为选择器标识,请使用属性选择器,如\[id="csId"]。 * 和JavaScript耦合。实际开发中,元素的ID主要用在JavaScript中,以方便DOM元素快速获取它。如果ID同时和样式关联,它的可维护性会大打折扣。一旦ID变化,必须同时修改CSS和JavaScript,然而实际上开发人员只会修改一处,这就是很多后期bug产生的原因
不要嵌套选择器
缺点:
- 渲染性能糟糕
- 优先级混乱
- 样式布局脆弱
渲染性能糟糕:
有两方面会对渲染性能造成影响,一是标签选择器,二是过深的嵌套
css选择器的性能排序如下:
- ID选择器。如#foo
- 类选择器。如.foo
- 标签选择器。如div
- 通配选择器。如*
- 属性选择器。如[href]
- 部分伪类,如
:check
其中,ID选择器的性能最好,类选择器处于同一级别,差异很小,比标签选择器具有更明显的性能优势。这样看似乎.box>div
也是一个不错的用法,.box
性能很高,选中后再匹配标签为div的子元素,性能还行吧。然而,很遗憾,css选择器是从右往左进行匹配渲染的,.box>div是先匹配页面所有的<div>
元素,在匹配.box类名元素。如果页面内容丰富,HTML页面复杂,<div>
元素多达上千个,同时这样低效的选择器又很多,则会带来明显可感知的渲染性能问题。
然而在大多数场景下,讨论css选择器的性能问题是个伪命题。首先,我们实际开发的页面都比较简单,选择器用的再不合理,性能差异也不会太大;其次,就算页面很复杂,300毫秒和30毫秒的性能差异也不会成为页面性能的瓶颈,你付出千万分的努力所带来的优化说不定还远不如优化一张广告图的尺寸来的大。