当前位置: 首页 > Web前端 > HTML

CSS元素选择器是如何工作的

时间:2023-04-02 23:26:00 HTML

在前端工程师的日常工作中,经常会用到CSS元素选择器;不管你是写通用的CSS,还是编译SASS、SCSS、LESS等,最后都是编译成一行一行的CSS样式属性,最后交给浏览器去解析和应用。但是你有没有想过没有它这怎么可能?浏览器渲染先来看看浏览器的渲染步骤:CSS被浏览器加载后,会被解析成一棵CSSOM树,并会尝试与Dom叠加形成一棵渲染树,接下来就是计算等步骤位置和渲染。从这个角度来看,应用CSS属性的关键在于如何将CSS转化为一棵CSSOM树,以及如何将CSSOM应用到DOM中。CSSOM树当我们记下一组CSS样式时,例如:#id.classh4+p{...}当浏览器解析它时,你可能会认为CSS会按照从左到右的顺序找到它#id>.class>h4>p,最后应用,但实际上浏览器解析CSS的顺序是从右到左p>h4>.class>#id。很违反直觉,对吧?但是如果考虑到性能问题,从右到左的解析会比从左到右强很多。假设它有这样的HTML:...

...
...
...这里有五个CSS样式规则:#div1.c.d{}.f.c.d{}.a.c.e{}#div1.f{}.c.d{}让我们模拟一下,如果CSS从左到右解析,会生成一个像这样的CSSOM树:by,这样的CSSOM树在应用样式时,必须检查所有的样式规则,确认样式规则是否会影响,共有三种样式规则:#div1.c.d.f.c.d.c.d以此类推,DOM树必须促进所有的样式规则,才能获取个别样式,这会造成大量的冗余额外计算,进而严重影响性能。反之,如果前面的CSS是从右到左解析的,那么CSSOM树可能是这样的:和前面的例子一样,从中的.d来看,由于样式规则影响的目标元素都集中在第一层,所以不需要方便整个CSSOM树,甚至只需要检查下面的子属性变量是否存在。检索它,就可以完成样式规则对元素的.d应用。从右到左的解析顺序可以将所有共享规则路径聚集在一起。浏览器在进行属性比较时,不需要对整个CSSOM树进行便利,大大减少了无效的比较计算。你也可以换个角度想:在HTML的结构中,一个元素可以有无数个子元素,但它只能有一个父元素。从孩子到父母(从下到上)搜索肯定更快。应用样式解析CSSOM树后,CSSOM树能否与DOM结合?如果真的那么容易就好了。除了开发者定义的CSS文件外,还有几个地方可能会定义样式规则来影响屏幕的渲染:HTML的内联样式设置了浏览器的默认值(即什么CSSreset/normalize会覆盖)浏览器浏览器负责处理CSS的部分。它将前面所有的东西和CSS文件定义的样式规则组织成一个单独的样式规则组(CSS规则集),里面记录了样式规则、目标属性等信息。目标属性为了提高后期的计算效率,浏览器的CSS处理核心会按照样式规则组中各个规则的目标属性进行分组存储;分为以下四组:idRulesclassRulestagNameRulesuniversalRules这样访问的时候可以根据目标元素是否存在。快速筛选出可能应用的样式的属性。应用规则最后是应用规则。浏览器会按照以下顺序和样式规则权重来应用所有样式规则:浏览器默认值浏览器用户偏好设置开发者定义的CSS内联样式加上!important样式属性你可能会好奇:为什么inlineStyle和开发者定义的CSS会是分开处理?我们可以回顾一下浏览器渲染的步骤。由于内联样式存在于DOM元素中,只有在DOM上应用CSS时才能访问它,两者不能事先结合。CSS效率其实浏览器在这里已经完成了优化机制;浏览器将自动为具有一致状态的元素拍摄样式快照。一致状态是满足以下条件:没有IDtag和class必须完全一致没有设置style属性同级的各种选择器(如:~、+、:first-child等)不能在style规则中使用由于以上条件,以及前面讨论的CSS计算过程,在编写CSS时有几点可以注意:由于样式规则的目标属性是分组存储的,所以id选择器非常高效,所以它不能与其他条件混合。不要写太深的CSS样式规则。如果您不能使用内联样式,请不要使用它。除了难以维护之外,因为它存在于DOM树上,无法提前与其他样式组合,所以效率会大大降低。如果你能注意到这类典型的小细节,CSS效率自然能大大提高。扩展了你对CSS选择器的理解之后,你一定很好奇,JavaScript元素选择器呢?这个问题可以参考jQuery的源码。它是从左到右解析的。至于为什么不一样,文中有答案,留给大家自己去思考。