当前位置: 首页 > 科技观察

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

时间:2023-03-12 09:01:18 科技观察

在前端工程师的日常工作中,经常会用到CSS元素选择器;不管你写的是通用的CSS,还是需要编译的SASS、SCSS、LESS等,最终都会被逐行编译成CSS,Style属性最后交给浏览器去解析应用。但是你有没有想过这是如何实现的呢?浏览器渲染先来看看浏览器的渲染步骤: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树:思考通过中的.d,这样的CSSOM树必须检查所有样式规则,看是否样式规则将影响.d。最后,还有可能影响.d的三种样式规则:#div1.c.d.f.c.d.c。d以此类推,DOM树上的每个元素都必须促进所有的样式规则,才能获得个体样式,这样会造成大量的冗余计算,严重影响性能。反之,如果前面的CSS是从右到左解析的,那么CSSOM树可能是这样的:和前面的例子一样,从中的.d来看,由于样式规则影响的目标元素都集中在第一层,所以不需要方便整个CSSOM树,甚至只需要检查下面的子属性变量是否存在。检索它,就可以完成样式规则对元素的.d应用。从右到左的解析顺序可以将所有共享规则路径聚集在一起。浏览器在进行属性比较时,不需要对整个CSSOM树进行便利,大大减少了无效的比较计算。你也可以换个角度想:在HTML的结构中,一个元素可以有无数个子元素,但只有一个父元素。从孩子到父母(从下到上)搜索肯定更快。1.应用样式解析CSSOM树后,能否将CSSOM树与DOM结合?如果真的这么简单就好了。除了开发者定义的CSS文件外,还有几个地方可能会定义样式规则来影响屏幕的渲染:HTML的内联样式设置了浏览器的默认值(即什么CSS重置/规范化会覆盖)Browser浏览器负责处理CSS的部分。它将前面所有的东西和CSS文件定义的样式规则组织成一个单独的样式规则组(CSS规则集),里面记录了样式规则、目标属性等信息。2、目标属性为了提高后期的计算效率,浏览器的CSS处理核心会按照样式规则组中各个规则的目标属性进行分组存储;它分为以下四组:idRulesclassRulestagNameRulesuniversalRules。目标元素中是否存在该属性,快速筛选出可能应用的样式。应用规则最后是应用规则。浏览器将按照以下顺序和样式规则权重应用所有样式规则:浏览器默认值浏览器用户偏好设置Developer-definedCSSinlinestyleplus!importantstyleattribute你可能想知道:为什么将inlinestyle和developer-definedCSS分开处理?我们可以回顾一下浏览器渲染的步骤。由于内联样式存在于DOM元素中,因此只有将CSS应用于DOM时才能访问它。事先不可能将两者结合起来。合并。CSS效率其实浏览器在这里已经完成了优化机制;浏览器将自动为具有一致状态的元素拍摄样式快照。状态一致是指必须满足以下条件:没有id标签和class必须完全一致没有设置style属性style规则不能使用同级的各种选择器(如:~,+,:first-child等。)以上条件,以及上面讨论的CSS计算过程,在写CSS的时候有几个地方需要注意:由于样式规则的目标属性会分组存储,id选择器效率很高,所以它不能与其他条件混合。不要写太深的CSS样式规则。如果您不能使用内联样式,请不要使用它。除了难以维护之外,因为它存在于DOM树上,无法提前与其他样式组合,所以效率会大大降低。如果你能注意到这类典型的小细节,CSS效率自然能大大提高。