强大的CSS: 让编写更高效的选择器

高效的CSS已经不是一个新的话题了,也不是我一个非得重拾的话题,但它却是我在工作之时,所感兴趣的,关注已久的话题。

有很多人都忘记了,或在简单的说没有意识到,CSS在我们手中,既能很高效,也可以变得很低能。这很容易被忘记,尤其是当你意识到你会的太少,CSS代码效率很低的时候。

下面的规则只真正被应用到那些速度要求很高,有成百上千的DOM元素被绘制在页面上的大型网站。但是,实践出真理,多知道一点总是好的。

CSS 选择器

对我们大多数人来说,CSS选择器并不陌生。最基本的选择器是元素选择器(比如div),ID选择器(比如#header)还有类选择器(比如.tweet)。

一些的不常见的选择器包括伪类选择器(:hover),很多复杂的CSS3和正则选择器,比如:first-child,class ^= “grid-”。

CSS选择器具有高效的继承性, CSS选择器效率从高到低的排序如下:

  1. ID选择器 比如#header
  2. 类选择器 比如.promo
  3. 元素选择器 比如 div
  4. 兄弟选择器 比如 h2 + p
  5. 子选择器 比如 ul > li
  6. 后代选择器 比如 ul a
  7. 通用选择器 比如 *
  8. 属性选择器 比如 type = “text”
  9. 伪类/伪元素选择器 比如 a:hover

我们不得不提的是,纵使ID选择器很快、高效,但是它也仅仅如此。从CSS Test我们可以看出ID选择器和类选择器在速度上的差异很小很小。

在Windows系统上的Firefox 6上,我测得了一个简单类选择器的(reflow figure)重绘速度为10.9ms,而ID选择器为12.5ms,所以事实上ID比类选择器重绘要慢一点点。

ID选择器和类选择器在速度上的差异基本上没有关系。

在一个标签选择器(a)的测试上显示,它比类或ID选择器的速度慢了很多。在一个嵌套很深的后代选择器的测试上,显示数据为440左右!从这里我们可以看出ID/类选择器 和 元素/后代选择器中间的差异较大,但是相互之间的差异较小。

组合选择器

你可以有一个标准的选择器比如 #nav,来选择任何带有ID为”nav”的元素,或在你可以有一个组合选择器比如#nav a,来选择任何在ID为’nav’的元素里面的链接元素

此刻,我们读这些是从左到右的方式。我们是先找到#nav,然后从它的里面找其他元素。但是浏览器解析这些不是这样的:浏览器解析选择器是从右到左的方式。

在我们看来,#nav里面带了一个a,浏览器却是看到的a在#nav里面。这些细微的差异对选择器的效率有很大的影响,同时学这些差异也是很有价值的。

浏览器从最右边的元素开始(它想要渲染的元素),然后用它的方式回溯DOM树比从DOM树的最高层开始选择向下寻找。

这些对CSS选择器的效率有很大的影响。

关键选择器

关键选择器,正如前面讨论的一样,是一个复杂的CSS选择器中最右边部分。它是浏览器最先寻找的。

现在我们回到讨论开始的地方,哪类选择器是最高效的?哪个是会影响选择器效率的关键选择器;写CSS代码的时候,关键选择器是能否高效的决定因素。 一个关键CSS选择器像这样:

#content?.intro?{}

是不是高效选择器比如类选择器天生就高效?浏览器会寻找.intro的实例(可能会很多),然后沿着DOM树向上查找,确定刚才找到的实例是否在一个带有ID为”content”的容器里面。

但是,下面的选择器就表现的不是那么好了:

#content?* {}

这个选择器所做的是选择所有在页面上的单个元素(是每个单个的元素),然后去看看它们是否有一个 #content 的父元素。这是一个非常不高效选择器因为它的关键选择器执行开销太大了。

运用这些知识我们就可以在分类和选择元素的时候做出更好的选择。

假设你有一个复杂的页面,它相当巨大并且在你的一个很大很大的站点上。在那个页面上有成百上千甚至上万的 a 标签。它还有一个小的社交链接区域放在一个ID为#social的Ul里面。我们假设它们是Twitter,Facebook,Dribbble还有 Google+的链接吧。在这个页面上我们有四个社交链接和成百上千的其他链接。 下面的这个选择器就自然的不是那么高效和合理了:

#social a {}

这里发生的情况是浏览器会在定位到#social区域下的四个链接之前得到页面上所有成千上万的链接。我们的关键选择器匹配了太多我们不感兴趣的其他元素。

为了补救我们可以给每个在社交链接区域的 a 增加一个更特殊、明确的选择器 .social-link , 但是这好像有点违背我们的认知:当我们能用组合选择器的时候就不要放不必要的类标示在元素上。

这就是为什么我对选择器的性能如此感兴趣的原因了:必须在web 标准最佳实践和速度之间的保持平衡。

通常我们有:

<ul id="social">
    <li><a href="#" class="twitter">Twitter</a></li>
    <li><a href="#" class="facebook">Facebook</a></li>
    <li><a href="#" class="dribble">Dribbble</a></li>
    <li><a href="#" class="gplus">Google+</a></li>
</ul>

CSS:

#social a {}

我们现在最好有:

<ul id="social">
    <li><a href="#" class="social-link twitter">Twitter</a></li>
    <li><a href="#" class="social-link facebook">Facebook</a></li>
    <li><a href="#" class="social-link dribble">Dribbble</a></li>
    <li><a href="#" class="social-link gplus">Google+</a></li>
</ul>

加上CSS:

#social?.social-link?{}

这个新的关键选择器将会匹配更少的元素,这意味着浏览器能够很快的找到它们并渲染特定的样式,然后专注于下一件事。

另外,事实上我们可以用.social-link{}更清晰的选择,而不是过分限制它。阅读下一部分你会知道原因…

简单的重述一次,你的关键选择器会决定浏览器的工作量,因此,我们应该重视一下关键选择器。

过度限制选择器

现在我们知道了什么是关键选择器,还有它工作的原理,但是我们可以更乐观一点。拥有一个明确的关键选择器最大的好处就是你可以避免使用过度限制选择器。一个过度限制选择器可能像:

html?body .wrapper?#content a {}

这里的写的太多了,至少3个选择器是完全不需要的。它可以最多像这个样子:

#content a {}

这会发生什么呢? 首先第一个意味着浏览器不得不寻找所有的 a 元素,然后检查他们是否在一个ID为”content”的元素中,然后如此循环直到HTML标签。这样造成了太多的我们不太想要的花费。了解了这个,我们得到一些更现实的例子:

#nav li a {}

变成这个:

#nav a {}

我们知道如果a在li里面,它也必定在#nav里面,所以我们可以马上把li从选择器组中拿掉。然后,既然我们知道在页面中只有一个ID为nav的元素,那么它依附的元素就是完全没有关系得了,我们也可以拿掉ul。

过度限制选择器使浏览器工作比它实际需要的更繁重,花费的时间更多。我们可以删掉不必需的限制,来使我们的选择器更简单和高效。

这些真的需要吗?

最短的答案是:或许不是。

最长的答案是:它取决于你正在搭建的站点。如果你正在为你的晋升而努力,那么就好好写出简单、高效的CSS代码吧,因为你可能不会感觉到它给你带来的改变。 如果你正在搭建下一个每个页面都以毫秒计算的网站,这样有时速度会很快,但有时可能不是。

浏览器将会在解析CSS的速度上变得更好,甚至在手机端。在一个网站上,你不太可能会觉察到一个低效的CSS选择器,但是….

但是

它确实发生了,浏览器还是不得不去做我们讨论的所有工作,无论它们变得多快。即使你不需要或者甚至不想实践任何一个,但是它都是我们值得学习的知识。请记住选择器可能会让你付出很大代价,你应该避免盯着一个看。这意味着如果你发现你自己在写像这样的:

div:nth-of-type(3)?ul:last-child?li:nth-of-type(odd)?* {?font-weight:bold }

这时,你可能就做错了。

自己是一个五年的前端工程师,希望本文对你有帮助!

这里推荐一下我的前端学习交流扣qun:731771211 ,里面都是学习前端的,如果你想制作酷炫的网页,想学习编程。自己整理了一份2019最全面前端学习资料,从最基础的HTML+CSS+JS【炫酷特效,游戏,插件封装,设计模式】到移动端HTML5的项目实战的学习资料都有整理,送给每一位前端小伙伴,每天分享技术

点击:加入

原文地址:https://blog.51cto.com/14284898/2395240

时间: 2024-10-30 06:54:38

强大的CSS: 让编写更高效的选择器的相关文章

编写更好的CSS

编写好的CSS代码能提升页面的渲染速度.本质上,一条规则都没有引擎解析的最快.MDN上将CSS选择符归拆分成四个主要类别,如下所示,性能依次降低. ID 规则 Class 规则 标签规则 通用规则 对效率普遍认识是从Steve Souders在2009年出版的<高性能网站建设进阶指南>开始的,虽然Souders的书中罗列的非常详细,你可以在这里查看完整列表引用.你也可以在谷歌的高效的CSS选择器的最佳实践中查看更多的细节. 本文我想分享一些我在编写高性能CSS中用到的简单的例子和指导方针.受M

DIV+CSS:如何编写代码才能更有效率

如何编写CSS代码才能更有效率?这是许多网页制作者与开发者都关心的问题.大概没有什么魔法,可以保证一下就把你的样式表缩小到百分之多少,但合理的 CSS 编码与组织技巧,的确能够帮助你的更有效率地写出更清晰高效的代码,自然,样式表大小的缩减还能减少下载的时间. 一.排版: 1.关键词和操作符之间加适当的空格. 2.相对独立的程序块与块之间加空行 3.较长的语句.表达式等要分成多行书写. 4.划分出的新行要进行适应的缩进,使排版整齐,语句可读. 5.长表达式要在低优先级操作符处划分新行,操作符放在新

【转】编写更好的CSS代码

原文转自:http://blog.jobbole.com/55067/ 编写好的CSS代码,有助提升页面的渲染速度.本质上,引擎需要解析的CSS规则越少,性能越好.MDN上将CSS选择符归类成四个主要类别,如下所示,性能依次降低. ID 规则 Class 规则 标签规则 通用规则 对效率的普遍认识是从Steve Souders在2009年出版的<高性能网站建设进阶指南>开始,虽然该书中罗列的更加详细,但你也可以在这里查看完整的引用列表,也可以在谷歌的<高效CSS选择器的最佳实践>中

编写更好的jQuery代码(转)

这是一篇关于jQuery的文章,写到这里给初学者一些建议. 原文地址:http://flippinawesome.org/2013/11/25/writing-better-jquery-code/ 现在已经有很多文章讨论jQuery和JavaScript的性能问题,然而,在这篇文章中我计划总结一些提升速度的技巧和一些我自己的建议来改善你的jQuery和JavaScript代码.更好的代码意味着更快的应用程序,快速渲染和反应性意味着一个更好的用户体验. 首先,我们要记住最重要的一点是:jQuer

编写更好的jQuery代码的建议

编写更好的jQuery代码的建议 2013/12/05 | 分类: WEB前端, 开发 | 15 条评论 | 标签: JQUERY 分享到:125 本文由 伯乐在线 - yanhaijing 翻译自 Mathew Carella.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 讨论jQuery和javascript性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的jQuery和javascript代码.好的代码会带来速度的提升.快速渲染和响应意味着更好的

用python编写一个高效搜索代码工具

用python编写一个高效搜索代码工具大多码农在linux环境下使用grep+关键词的命令搜索自己想要的代码或者log文件.今天介绍用python如何编写一个更强大的搜索工具,windows下也适用.我们的需求:1, 可以同时指定多个关键词.比如某个文件某一行中有"error: aa bb cc",如果检索关键词error和cc则可以显示该行,避免单一关键词冗余信息太多2, 可以排除某些关键词.对于"error: aa bb cc" ,如果设定排除bb,则不予显示该

这些小工具让你的Android 开发更高效

在做Android 开发过程中,会遇到一些小的问题,虽然自己动手也能解决,但是有了一些小工具,解决这些问题就得心应手了,今天就为大家推荐一下Android 开发遇到的小工具,来让你的开发更高效. Vysor Vysor 是一个可以将手机的屏幕投影到电脑上,当然也可以操作,当我们做分享或者演示的时候,这个工具起到了作用. Vector Asset Android Studio 在1.4 支持了VectorAsset,所谓VectorAsset:它可以帮助你在Android 项目中添加Materia

利用代码契约编写更好的代码

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:要编写更好代码的途径有很多,其中一种方式就是给代码加上契约.今天推荐的文章就是介绍微软研究院推出的开源Code Contract工具库的使用. 所谓代码契约就是让你用额外的代码来表达应用程序中对业务代码的假设情况,一般可以执行预先条件判断.过后条件判断和对象不可变判断.而微软研究院为.NET提供了这样的工具,即VS的扩展工具Code Contracts for .NET(现在仅支持到2013版

如何使程序更高效的执行?

在codewars网站做题,做到一下一道题. var add = function (a, b) { return a + b; }; var lazy_sum = make_lazy(add, 2, 3); Test.expect(lazy_sum() === 5, 'Evaluates the expression when required');//这个是codewars网站特有的测试代码,自己运行要另行写 var double = function (n) { return n * 2;