我承认自己并不经常考虑这个想法…… **我们编写的 CSS 在浏览器渲染速度方面有多高效?**
这绝对是浏览器供应商关注的事情(页面加载速度越快,使用他们产品的人就越高兴)。 Mozilla 有一篇文章 关于最佳实践。 Google 也一直在努力让网络更快。 他们也有一个 关于此的文章。
让我们介绍一下他们提出的几个主要想法,然后讨论其实际应用。
从右到左
要理解浏览器如何读取 CSS 选择器,一个重要的事情是,它们从 **右到左** 读取。 这意味着在选择器ul > li a[title="home"]中,第一个被解释的是a[title="home"]。 这部分也被称为“关键选择器”,因为它最终是要被选择的元素。
ID 最高效,通用选择器效率最低
有四种关键选择器:ID、类、标签和通用。 它们的效率顺序也与之相同。
#main-navigation { } /* ID (Fastest) */
body.home #page-wrap { } /* ID */
.main-navigation { } /* Class */
ul li a.current { } /* Class *
ul { } /* Tag */
ul li a { } /* Tag */
* { } /* Universal (Slowest) */
#content [title='home'] /* Universal */
当我们将这个从右到左的想法,以及关键选择器想法结合起来时,我们可以看到这个选择器效率并不高
#main-nav > li { } /* Slower than it might seem */
虽然这感觉很奇怪,与直觉相悖…… 由于 ID 效率很高,我们认为浏览器应该可以很快找到这个 ID,然后很快找到 li 子节点。 但实际上,相对较慢的 li 标签选择器首先被执行。
不要标签限定
永远不要这样做
ul#main-navigation { }
ID 是唯一的,因此它们不需要标签名称与其关联。 这样做会使选择器效率降低。
如果可以避免,也不要对类名进行标签限定。 类名不是唯一的,因此理论上你可以使用一个类名来做一些对多个不同元素都有用的事情。 如果你想根据元素的不同让样式不同,你可能需要标签限定(例如li.first),但这非常罕见,因此一般来说,不要这样做。
后代选择器效率最低
David Hyatt
后代选择器是 CSS 中效率最低的选择器。 它极其低效 - 尤其是如果选择器在标签或通用类别中。
换句话说,像这样的选择器是一个效率灾难
html body ul li a { }
失败的选择器比匹配相同选择器的效率更高
我不确定我们能从中学到什么,因为如果你在 CSS 中有很多不匹配任何东西的选择器,那,嗯,相当奇怪。 但是值得注意的是,在选择器的从右到左解释中,一旦它匹配失败,它就会停止尝试,因此消耗的能量比需要继续解释要少。
考虑为什么你要写这个选择器
考虑一下
#main-navigation li a { font-family: Georgia, Serif; }
字体系列是级联的,所以你可能不需要一开始就写一个非常具体的选择器(如果你只是更改字体)。 这可能同样有效,而且效率更高
#main-navigation { font-family: Georgia, Serif; }
CSS3 和效率
来自 David Hyatt 的有点令人沮丧的消息
CSS3 选择器的悲惨真相是,如果你关心页面性能,实际上根本不应该使用它们。
整个 评论 值得一读。
CSS3 选择器(例如 :nth-child)在帮助我们定位想要的目标元素,同时保持标记简洁和语义化的方面非常棒。 但事实是,这些花哨的选择器在使用上更占用浏览器资源。
所以问题是,我们真的不应该使用它们吗? 让我们来思考一下其实际应用……
实际应用
我上面链接到的那篇 Mozilla 文章? 已经 10 年了。 事实:10 年前的计算机速度慢得多。 我感觉这些东西在当时更加重要。 10 年前我刚满 21 岁,我甚至不知道 CSS 是什么,所以我不会对你老派…… 但我感觉我们不怎么讨论渲染效率,是因为这已经不是什么大问题了。
我的感觉是这样的:我们上面讨论的最佳实践无论如何都是有意义的。 你不妨遵循它们,因为它们也不会限制你在 CSS 中的能力。 但你也不必死板地遵守它们。 如果你碰巧需要从网站中榨取每一滴性能,并且以前从未考虑过这些东西,那么你可能需要重新检查你的样式表,看看有哪些地方可以做得更好。 如果你在网站中没有看到渲染速度变慢,那么就不用担心,只需了解一下,以备将来之需。
超高速,零实用性
所以我们知道 ID 是效率最高的选择器。 如果你想创建一个渲染效率最高的页面,你实际上需要给页面上的每一个元素都赋予一个唯一的 ID,然后使用单个 ID 选择器来应用样式。 这会非常快,也很荒谬。 这很可能非常不语义化,而且难以维护。 即使是在以性能为重的网站上,你也很难看到这种做法。 **我认为这里需要注意的是,不要为了高效的 CSS 而牺牲语义化或可维护性。**
感谢 Jason Beaudoin 给我发邮件谈论这个想法。 如果有谁对这些东西更了解,或者你还有其他类似的技巧,请告诉我!
顺便说一句,我还想提一下,由于 CSS 样式选择器也用于许多 JavaScript 库,因此这些相同的概念也适用。 ID 选择器将是最快的,而复杂的限定后代选择器等则会更慢。
这些都是经过充分研究的、可以提高浏览器渲染速度的要点。 您对通过缩小来压缩 css 的看法是什么?
压缩很棒,如果您可以将压缩作为工作流程的一部分,而不会变得繁琐,那么它将极大地为您在生产环境中带来好处。
这里需要注意的是,我们上面讨论的“效率”与压缩无关。 高效的选择器无论它们是从压缩的样式表中提供还是不是,都会非常高效。
已记录。
是的,我也正要问同样的问题。但克里斯指出了非常好的观点。我一直认为通过压缩 CSS 可以提高性能,但从未意识到它在很大程度上取决于我们选择的方式。如果样式表变得很长,这些因素还重要吗?
这很有趣,而且有点令人沮丧,得知后代选择器是“效率灾难”。我一直认为,给父元素分配一个类,然后使用后代选择器来设置其子元素的样式更好,例如:
ul.someclass li {...}
我还在那里使用标签限定符…… 唉。
我不会为此感到过于内疚…… 如果可以,你可以去掉标签限定符,但后代选择器是我们 CSS 开发人员很多时候不得不面对的一部分。
我正在尝试思考如何实际测试它。Firebug 中的网络面板会反映出差异吗?
导航菜单就让人想起这个。
为了“最佳实践”,我已经改变了编写 CSS 的方式,不再使用后代选择器。
所以我的导航会是
#nav { list-style: none; other styles… }
#nav li { }
#nav a { }
#nav span { }
等等。当然,我可以应用类名来提高效率,但这似乎有点 overkill,除非你有下拉菜单。
标签限定符很有趣。在开发中,我肯定会更多地考虑这一点。
但是,用更多 ID 和类来增加 HTML 的权重,换取更有效地渲染的 CSS,这算不算是一种糟糕的交易?难道创建轻量级的语义标记不应该比更快渲染的 CSS 文件更重要吗?我想,也许两者之间存在一种平衡点,但为了提高 CSS 渲染速度而开始添加更多特定的类和 ID,在我看来,似乎有点不对劲。
好吧,我忽略了加粗的文字……“我认为这里的教训是不要为了高效的 CSS 而牺牲语义或可维护性。”
总之,这是一篇很棒的文章。
可能不会。我不知道如何获得可靠的指标。如果有人拥有可以使用的工具,我将非常有兴趣知道。
我可以查看不同浏览器关于此方面的文档,并用 PHP 制作一个基准脚本,渲染两个或多个样式表的加载时间差异。
例如:您当前的样式表,以及根据您最佳知识进行优化的版本。我认为,一个 CSS 基准测试网站会很有吸引力。当然,如果它取得成功,我知道在哪里能找到优秀的网页设计师 ^^
我敢保证,Mozilla 有一种方法可以从他们的渲染引擎中提取关于此方面的指标…… 我不知道是什么,但他们对所有内容都进行回归测试,并进行测试以确保不会在这个领域降低性能。
此外,这些指标可能不适用于 Web 内容,而只适用于运行在 Chrome 特权下的内容…… 所以你可以制作一个插件来告诉你这方面的信息。
无论如何,除非您编写了非常糟糕的选择器,否则它们不应在合理的页面上造成性能问题(例如,在超大型页面上可能会出现问题…… 但无论如何,这些页面都会遇到性能问题)。
除了引用比尔·克林顿还在任总统时发表的文章之外,您还基于哪些信息来撰写这篇文章?
另外,像 HTML body ul li a { } 这样的后代选择器示例很荒谬,尽管并非闻所未闻。前三个元素是多余且不必要的。换句话说,li a {} 可以达到完全相同的目的。
我在文章中明确指出,Mozilla 的文章已经过时。但是,最近的一些文章仍然引用了它,例如来自 Even Faster Websites 的这段摘录。
您的第二个示例正是我想让人们更加清楚的类型。
您没有看到同一段中链接的 Google 页面 吗?
当然看到了。但是,到目前为止,我所读到的都是最佳实践,没有任何内容真正展示了 CSS 选择器的速度测试。
您是否曾经进行过 MySpace 自定义?那些后代选择器实在丑陋。
人们还在使用 MySpace 吗?哈哈
说真的。简直就是“td td td td td td td td td li a td….”,仅仅是为了自定义一个部分哈哈。
还有 @Stephen,真的,没有人使用它。:P 我的两个都只是在互联网上漂浮着,被遗弃了,孤零零的。
我认为,这是没有人再使用它的原因之一——它让你可以自定义,但自定义的方式非常愚蠢,让人感到沮丧,最后放弃。
=)…是的,他们使用 MySpace,而且仍然有网页“开发人员”使用表格设计来创建新的网站!
以下节日网站每年都会重新设计(去年他们换了另一位设计师)http://www.gurtenfestival.ch/ …… 看一下源代码,但不要哭出来 =P……
我认为“HTML body ul li a { }”只是一个虚拟的示例。它可能是“html#one body#article ul.items li#active a.tooltip”。是的,有时需要给 html 元素添加 ID。是的,
为什么“HTML body ul li a { }”会很荒谬?这东西叫做 CSS,意思是层叠样式表。为什么他们不把它叫做选择器样式表呢?
最后:HTML5 使层叠变得更糟糕:section#article section.chapter figure.photo figcaption.right。
那不是层叠,那只是后代选择器。
层叠是元素如何继承样式。
ul {
这里有样式
}
ul li {
这里的样式
}
这就是层叠
我从每条评论中学习,所以在这里贡献我的想法:层叠是关于由于选择器的特殊性和顺序而覆盖样式。
例如
ul{color:#fff}
ul{color:#f00}
#someParticularUl{color:#0f0}
#someOtherUl{color:#00f}
由于浏览器解释样式层叠的方式,第一个组将变成红色,第二个元素将变成绿色,第三个元素将变成蓝色。
前两个是多余的,但“ul”可能不是;“li”可以包含在“ol”中。
嘿,克里斯,感谢您撰写这篇文章,棒极了!
我很有兴趣找到一种适当的方法来命名 CSS 选择器(DIV)。
我写了一篇关于 给 DIV 命名 的文章,但目前它还没有结束,我感觉关于这个主题还有很多话要说。
你能在这方面帮助我们吗?
谢谢!
好文章,有一些关于 RTL 解析的观点我以前从未考虑过。不过,有时用元素名称限定您的类很有帮助,特别是为了克服特殊性问题。
添加标签会为特殊性添加 0,0,1,0,这非常低。我认为,一般来说,如果您想对抗特殊性问题,最好为其添加一个 ID,并根据该新 ID 进行定位。我明白您的意思,但现在知道标签限定符效率较低,最好避免使用。
是的,它很低,但有时这可能是您所需要的 :)
别误会,我绝对是干净的标记 & CSS 的拥护者,但你知道任何关于选择器吹毛求疵的影响的统计数据吗?很难想象现实世界中 CSS 的使用会对页面的绘制时间产生如此大的影响——即使http://sxsw.beercamp.com/ 渲染速度很快。
你说“永远不要这样做”
ul#main-navigation { }
然而,这样做有一个很好的理由(除了效率以外)……通过用元素限定 ID,可以更容易地查看 CSS 并知道该 ID 应用于无序列表。如果没有元素限定符,你就强迫那些编辑和使用你的 CSS 的人总是切换到标记来理解这个 ID 应用于哪个元素。
此外,你可能有一个“游动”的 ID。如果 ID 应用于 UL,那么该规则比仅使用 ID 选择器更具体。
如果标记限定对你的 CSS 可读性有很大帮助,那就去做吧。只是要知道它效率较低,而且没有必要。有些人不喜欢使用简写,因为他们认为列出单个属性更易读,但他们意识到这样做会增加 CSS 文件的大小。
ID 仅在单个页面的上下文中是唯一的。但是,将可跨页面共享的样式表串联起来是一种最佳实践——在这种情况下,可能需要对 ID 进行范围限定或限定。
人们标记限定是为了可读性(这也是非常重要的),我认为最重要的是要找到一个合适的平衡点。
/*ul*/#main-navigation { }
这应该有助于提高可读性,而不会降低效率。当然,你也可以在该行上面添加一个注释,标识 main-navigation 为无序列表。
这与自动缩小过程相结合,该过程会剥离注释,将是一个优化可读性和效率相当不错的解决方案。甚至可能还有其他地方可以使用它(例如,指示跳过的后代)。
/*ul*/#main-navigation /*li*/ a { }
哇,这是一个好主意。我一定会在我的样式表中实现它 :)
第二!
一些浏览器无法处理选择器中的注释,因此它可能会完全跳过该规则。此外,大量的注释会稍微降低速度。
@Timmy: 好吧,“这与自动缩小过程相结合,该过程会剥离注释”不会使其成为一个非问题吗?
没错!
你个白痴,为什么要这样做,并使你的样式表臃肿!
我同意 Shaun 的观点,但出于完全不同的原因。样式表不仅仅用于一个页面(除非你想要为每个页面加载不同的样式表,这与本文的效率主题并不一致),这意味着一个页面上的 ID 可能与另一个页面上的另一个元素相关联。因此,如果你只想定位具有“message”ID 的 span 元素,而不是另一个页面上具有相同 ID 的 textarea 元素,你必须使用 span#message。当然,出于效率原因,应该尽可能避免使用它,但不要说“永远不要”。
这确实是我唯一想到“哦,糟糕,这就是我所做的”的地方……我出于同样的原因这样做……可读性,因此我必须深入研究 CSS 缩小(我已经在 JS 中使用它了),但据我所知,我在缩小 CSS 时遇到了一些 IE 问题,所以我把它去掉了……
但是@Chris 的文章很棒
我想到的另一件事是:如果你真的关心网站的性能,我认为你需要对导致页面变慢的原因进行层次结构划分……我认为 CSS 对加载时间的影响非常小……我认为大部分加载时间来自内容/CSS 图片(当没有使用雪碧时),然后是 JS,然后是其他所有内容……因此,我首先会优化图片和 JS
但是,在创建新网站时,这种 CSS 性能方面的东西确实很有帮助……做到正确……正如其他人所说……基准在哪里?=)……
感谢 Chris,
这将实际上让我更多地思考如何编写我的标记,目前,如果我不确定是否会重复使用选择器,我就会在上面添加一个类,也许我应该开始考虑 ID。
谢谢
我认为这最重要的部分是了解代码的成本,并将其考虑在内。正如 Chris 所指出的,严格应用这些原则肯定会导致创建语义标记的一些退化。感谢 Chris 的文章!
很有趣。我以前从未想过 CSS 的效率问题。我很少将元素附加到我的 ID 和类,但是如果我用不到,我就会确保将其排除在外。
感谢 Chris 发表的另一篇很棒的文章。我经常使用 html & body 后代选择器,所以现在可能是时候改变我的方式了。
为什么浏览器从右到左解析 CSS?这听起来像是效率问题……
更合理的是在逻辑上位于堆栈较低位置的选择器之前读取限制选择器。
我想这就是原因:http://en.wikipedia.org/wiki/Bottom-up_parsing
我敢肯定地说它是为了性能。我不确定是否能解释确切的原因。
基本上,如果你有一个像这样的树
div ul li
它必须匹配每个 div,然后遍历并检查每个元素是否为 ul,如果它是 ul,则检查每个元素并查看它是否为 li。为了做到这一点,它必须遍历 DOM 树。
反过来,它可以构建页面上每个 li 元素的查找表。(我不确定它是否是实际的实现方式,但它的功能是相同的)。然后它只需要检查其祖先,看看它是否在任何地方都有一个 ul,然后在那个位置附近,看看它是否有一个 body。
对于无法对正在解析的文档的结构进行假设的情况(即通用解析器),RTL 会快得多。
超级快
.list {}
.list_li {}
.list_li_span{}
.list_li_span_a{}
不要使用 ID!
你在开玩笑吗?
不!:)
你把这种冗长的类名放在所有东西上吗?
你听起来像个 CMS
@zolotoy – 好模式!
如果你通过脚本自动执行,这将非常出色。
如果你使用这种类名,为什么要使用标记?你是否将所有内容都包装在一个 DIV 中并设置浮动到左侧?
所以……
真的吗?
这种模式对于在高性能网站中更有效地渲染 CSS 很有用
很棒的文章。
你将如何测试它?换句话说,你如何衡量 CSS 的效率?你推荐哪些工具和方法?
Rick
http://static.yandex.net/reflowmeter/_reflow-meter.js
嘿,Chris,
您对这篇文章中关于伪选择器的看法如何?
我希望您的浏览器将伪选择器视为父选择器项的一部分。否则,整个 :hover 功能将给浏览器带来极大的麻烦。
所以,再次重申:您对此有何看法?
Google 指出了我的样式表中一些过度限定的选择器,在此之前,我对此一无所知。很棒的文章!
“顺便说一句,我还想提一下,由于 CSS 样式选择器也被许多 JavaScript 库使用,因此这些相同的概念也适用。”
这并不完全正确。jQuery 中的标签限定方法速度更快。因为当你选择像 $(‘.class’) 这样的东西时,它在幕后做的是使用 getElementByTagName,并在其中添加一个星号,然后检查每个元素是否具有该类。像 $(‘a.class’) 这样的操作效率更高。
不过,我很好奇为什么解析器从右到左解析,而我们写的却是从左到右呢?
在 JavaScript 中,使用 ID 选择器是最快/最简单的选择器,就像 CSS 一样。
嘿,Chris 和 Hassan。
你们两位在 jQuery 代码评论方面都是正确的——在过去,通过 ID/通过 DOM 帮助 jS/jQuery 找到元素,在使用类时速度更快。
然而,如今看起来 jQuery 使用的是 getElementByClassName,而该方法最近被添加到较新的浏览器中(Chrome 肯定有)!
阅读/搜索——https://code.jqueryjs.cn/jquery-1.4.2.js
了解更多详细信息!
的确如此,但您提出的观点非常有效,很容易被忽视。
jQuery 基本上“实现了”CSS 选择,因此它选择元素的方式不同于浏览器天真地选择元素以应用 CSS 样式的方式。它封装了本机 JavaScript 方法,以便更轻松地进行开发,并在本机 JavaScript 函数的基础上以最佳性能执行操作。
浏览器具有更全面的本机方法来应用 CSS 规则,并使用不同的方法。
对于 JavaScript,您选择的元素相对较少,用于操作。对于浏览器 DOM 样式,每个 DOM 元素都必须进行评估。因此,后端逻辑的处理方式不同。
在上面(关于浏览器解析器 RTL 问题的早期帖子中),我更详细地描述了为什么它从右到左执行的原因。
很棒的文章。我刚开始自学 CSS 不到一年,我仍然认为自己是一个新手,尤其是在最佳实践和掌握所有语义方面。我很高兴阅读到“标签限定”不是一个好主意。在尝试自学时,我查看了其他设计师的代码,并一直在做很多这种操作。我以为这是出于组织目的而应该做的事情,我很高兴得知事实并非如此!
太棒了!帮我解决了我的一个问题。天哪,我无法强调这对我有多大帮助!
Chris,感谢您的文章。实际上,在我阅读这篇文章之前,我刚刚开始遵循大多数这些实践,但并非因为我认为它们可以加快 CSS 加载速度,而是因为我喜欢它们使我的代码保持简洁的方式。但是,我发现,为了避免使用太多后代选择器和类名,我不得不开始使用 !important 属性来解决特异性问题。我个人并不介意这样做,但想知道您对此有何看法……我知道有些人非常反对总是使用 !important,或者至少尽量避免使用……
虽然我从不会在 html body 部分使用后代选择器
ul li a { }
它在构建快速网站和应用程序开发方面提供了很多力量,尤其是在我们有许多共享类似设计的应用程序的环境中。
例如,我们正在构建一个内部物业管理应用程序,其中包括工程、安全、时间跟踪以及租户与我们互动的部分。通过跳过过多的 ID 和类,我将我的 HTML 和 CSS 代码从 900 行减少到 300 行(这是一个庞大的应用程序),并且它允许我的年轻设计师和开发人员更快地编写代码,因为某些基本的 HTML 标签在以某种方式使用时会默认。
Steve Souders 也讨论了这个问题 在他的博客上
我尽量避免使用非常低效的规则,我认为现在也是时候仔细查看那些低效的规则了!
嘿,Chris,
这是一篇很棒的文章。我是您的长期读者,第一次评论!
当我读到这个时,我有一种“啊哈”的顿悟。
#main-navigation li a { font-family: Georgia, Serif; }
#main-navigation { font-family: Georgia, Serif; }
我编写 CSS 代码已经有一段时间了,我犯了这种错误好多次。效率至上!
再次感谢您所有精彩的帖子和屏幕截图!
哈哈,虽然我读到了您的“记住”部分,但我还是搞砸了回复。
我最好去“提交一个笨蛋”(:)
以这种方式编写样式表可能在为移动设备编写样式表时很有用。移动设备仍然比计算机慢。因此,每一秒钟都宝贵,对吧?
大家好 :) 很有趣的文章。
虽然在大型网站(我指的是包含大量内容和针对不同部分的不同布局的大型网站)中尽可能编写优化的 CSS 代码是件好事,但类名可能会出现一些问题。
如果我的内容中有 6 或 7 种间距元素,例如
1. 菜单项
2. 段落
3. 侧边菜单项
4. 侧边菜单块
5. 列表项
6. 其他东西
它们都可以被归类为 .spacer,但是根据其标签名称对它们进行样式设置比分配长而难以理解的类名(如 “.sideNavigation-MenuBlockSpacer”)容易得多,而且在语义上更正确,而我们可以使用类似这样的东西——“#menuBlock li.spacer”。
所以——不要为了性能而牺牲语义,反之亦然 :)
CSS 只是我们将来都会面临的一个速度问题,因为我听说 Google 开始将加载时间纳入其算法中。我发现 Firebug 的 Yslow 附加组件(适用于 Firefox)非常有用,可以查看网站性能不佳的原因。例如,Chris,我看到您正在进行 10 个外部 JavaScript 请求。当您与全世界竞争时,每一秒都很重要……
这真的是*渲染*性能还是只是*解析*?
渲染体验更多地取决于如何触发和处理重绘和重排,不是吗?
取决于您如何定义“渲染”。
我认为渲染是指从程序(在本例中为浏览器)接收输入到将其绘制到屏幕上的时间段。为了做到这一点,它首先必须解析输入(CSS 指令)以确定要绘制的内容,然后进行绘制。
因此,解析是渲染过程的一部分。我这个门外汉猜测,遍历 DOM 并找出哪些元素需要应用哪些样式可能是渲染过程中最耗时的部分之一。
很棒的文章!
这里有一些关于优化 CSS 以加快加载时间的好点——对于大型项目来说非常重要,而且现在 Google 将页面加载时间纳入其算法中,这变得更加重要!
感谢 Chris!
很有趣,我不知道选择器是从右到左读取的。我当然可以理解为什么这会大大降低效率。我从不进行标签限定,并且通常会编写紧凑的后代选择器,但您指出了其中可以改进的一些方面。谢谢!
Chris,这篇文章对于任何从事网页开发工作的人或对该领域感兴趣的人来说,都包含着极其重要的提示。但是,我不同意您的一些说法,让我们来谈谈。
永远不要这样做
ul#main-navigation { }
大多数开发项目都在使用内容管理系统,例如 Drupal 和 WordPress 或 Joomla!,这些系统中通常会使用预定义的模板标签,因此必须采用比平时更高的层次结构来构建样式表。
根据我对我的经验以及一些测试的评论,我发现
.class-list { };
的效果不如使用
ul.class-list { };
当我们为该元素指定类时,CSS 的渲染效果通常会更好,我尝试实现评论中提到的建议,使用
/*ul*/.class-list { };
但它与第一次使用没有区别。
我也明白,使用以下代码效率更高
div.main div.box ul li a { };
而不是使用
.class-link { };
<div class="box">
<ul>
<li>
<a class="class-link" rel="nofollow"></a></li>
</ul>
</div>
</div>
我们讨论的不仅仅是速度,还有代码的组织和标准化。您对这些考虑有什么意见?考虑到您所说的,今天的计算机速度快得多,而且随着时间的推移会越来越快。
我怀疑在每个元素上都加一个 ID 会有什么性能优势,因为这样浏览器就必须匹配更多的规则,而且不能重复使用那么多东西。当然,ID 选择器可能比其他类型选择器在单独使用时更快,但这并不意味着如果您滥用它们,您的页面就会更快。
您更有可能通过消除冗余规则来获得更好的效果,这是一种双赢的策略,因为它还会使您的 CSS 更短,从而减少页面加载的延迟。
实际上,对于大多数网站来说,网络延迟比 CSS 选择器匹配更重要。
同样重要的是实际的标记和应用于它的样式,而不是选择器。(例如,如果您要求浏览器将 20 个带 alpha 的 png 叠加在一起,它几乎肯定会在绘制图像上花费比匹配选择器更多的时间)
几周前我在另一篇帖子中对此进行了评论:https://css-tricks.cn/specifics-on-css-specificity/#comment-75911.
保持 HTML 节点数量少,您可能不必太关心渲染 CSS 需要多长时间(除非是移动设备) - 使用以下方法检查页面中的元素数量:
document.getElementsByTagName('*').length
尽量保持在 1000 个以下。如果您想了解更多详细信息,可以阅读这篇有趣的文章:CSS 选择器的性能影响 - 真实的基准测试,展示了通过改进选择器实际可以获得多少收益。
PS:并非所有 JS CSS 选择器引擎都使用从右到左的方法。
干杯。
对于具有大型 css 文件(2000 行以上)的页面来说,这是一个很好的技巧,但在普通页面中,速度提升并不明显。
不错!
中文翻译:http://www.vfresh.org/w3c/727
说得好
“我认为这里的教训是不要为了高效的 CSS 而牺牲语义或可维护性。”
在平衡效率与实用性和干净的标记时,做出明智的决定很重要。所以这些技巧有助于理解这种平衡。谢谢!
如果您编写高效且良好的 CSS 代码,您的客户会喜欢吗?或者您从客户那里得到更多提示?也许没有,但您会喜欢专业,而且每个浏览器都会很好地呈现您的网站 :)
后代选择器如此昂贵真是可惜,它们非常有用,可以避免用重复的类和 ID 来杂乱 HTML - 毕竟我们已经有一个树形关系可以使用。
不错!
我从大约 2002/03 年起就开始坚定地使用 CSS,在那之前,我还是一个使用标签内属性和所有旧东西的恐龙。我的 CSS 并不完美,达不到精英的标准,但我写得非常干净,易于阅读,而且在上传之前,我会把它放到一个“压缩器”中。我的问题过去是,现在仍然可能是冗余。我可以将更多东西组合在一起,以便缩短它。最后,我不会像很多年轻人那样痴迷于图像和名声,并为 0.7kb 而苦恼,但我确实尝试了。
很棒的帖子,以前从未想过这个。
ul#main-navigation { } 比 #main-navigation { } 更好,它可以方便地识别它是哪个元素,并且更具可读性。
我不确定是否属实,因为浏览器首先会在 DOM 中查找所有 UL 元素,然后搜索 ID,而不是直接在 DOM 中搜索 ID。如果我错了,请纠正我。
我会尽快尝试测试一下,看看是否真的有区别。
我也不知道是对还是错。
但经过一些测试/研究,我认为它有不同的“CSS 特定性值”( https://css-tricks.cn/specifics-on-css-specificity/)
例如,div.box 比 .box 具有更大的 CSS 特定性值。
例如
.box{
display:block;
background:#000;
height:200px; width:200px;
}
div.box{
background:#DDD;
}
颜色最终会被覆盖,变成 #DDD。
但如果我们这样写
div.box{
display:block;
background:#000;
height:200px; width:200px;
}
.box{
background:#DDD;
}
颜色仍然是 #000
如果我使用错误的示例或错了,请纠正我。
另一种提高渲染速度的方法是避免使用 @import 语句。
查看 Steve Souders 关于此主题的这篇精彩文章。
你好!
感谢您提供这些内容。
但是您能用一些性能测试和图形来证明您的论点吗?
致敬
Chris
只有在使用大量 css 的大型网站上才能看到巨大的性能提升,而这些性能问题实际上可以为您节省几毫秒。
另一种提高性能的方法是只提供特定页面使用的 css。基本上,您必须为每个页面/模板创建单独的样式表。当然,这需要一些额外的后端,并且并非所有项目都可行或可能。
这些都是非常好的观点,但我肯定不会做的一件事是为每个 CSS 目标添加一个 类 或 ID,仅仅是为了提高渲染速度 - HTML 大小也是我关心的一个因素。
从现在起,我会在编写 CSS 时考虑到这些要点 - 尤其是在避免使用太多通配选择器方面 - 但性能的提高并不值得对已存在的 CSS 进行重构。
我想另一种提高性能的方法是只提供特定页面使用的 css。基本上,您必须为每个页面/模板创建单独的样式表。当然,这需要一些额外的后端,并且并非所有项目都可行或可能。
太棒了.. 非常感谢..
我想再补充一点
最好按字母顺序排列 css 属性,例如
.class{
widht:100px;
background:#000000;
}
而不是这样
.class{
background:#000000;
widht:100px;
}
为了获得更好的性能..
感谢分享..
我认为这只是您个人的偏好,如果有的话。
感谢您提供这篇文章,Chris!我学到了一些以前只怀疑有问题,但从不知道确切情况的事情。比如 - 标签限定。有趣的是,Eric Myer 实际上在他的书《Eric Myer on CSS》中教授了这种实践。
当然,那是 8 年前的事了,开发理念已经走过了很长的路,但我记得当时(即使作为一个新手,那是我买的第一本 CSS 书)我就在想这似乎是一种编码的冗余方式。我从未采用这种实践,但如果很多开发者仍然以这种方式编写 CSS,我也不会感到惊讶,因为这条指令来自业界一个非常有名望和受人尊敬的人。
像这样的文章很重要,因为它们提醒我们,很好地持续质疑“最佳实践”的 HOW,更不用说何时或是否应该在每个项目的基础上应用它们。干得好。:)
惊讶没有人提到过这一点:这对于移动网站来说非常重要。由于网络和处理速度较低,获得性能改进将更加明显。
至于到处添加 ID:如果您的 ID 是自描述的,就没有必要做类似 ul#main-navigation 的事情。正确的方法是将 ID 命名为 #ul-main-navigation,尽管它可能更好。类名和编程中的变量也是如此。不知道为什么人们不做这些。如果阅读变量可以回答“这个变量保存了什么?”,那么它就应该没问题。
理想情况下,在阅读 CSS 时,不需要参考 HTML。如果能做到这一点,那么可读性就相当好。
关于 CSS 选择器速度,还没有太多阐述.. 虽然我们有 SunSpider 用于 JS 和 Sizzle.js RTL 选择器引擎,但我想知道是否有 CSS 选择器速度测试?
虽然这篇文章很有道理,但我对后代标签选择器的性能影响持怀疑态度,更重要的是,性能问题究竟是源于选择器本身的复杂性,还是源于将 CSS 样式应用到返回元素集的过程。
有没有什么测试或统计数据来证明这篇文章中的观点呢?
太有意思了,我以前从未意识到这一点。我一直以为可能有最佳模式可以遵循,但我从没花时间深入研究并找出答案。
学到了新东西,谢谢!
你漏掉了一点
如果你正确地使用选择器,就可以减少 CSS 文件的大小——也就是说,我可以使用 2 行 CSS 代码来覆盖比将唯一 ID 应用到每个地方更多的内容。我的 CSS 文件比使用旧方法要短几百行。
另外,当 CSS 压缩后,它几乎不会影响页面速度。与臃肿混乱的 CSS 文件相比,我优化的、更小的 CSS 文件在压缩后性能会更好。
不相信我?自己试试。这篇文章对小型网站很有用,但肯定不适用于大型项目。
观点很有趣,但我希望看到一些真实的数据,以便了解真实的性能影响。
好吧,对于台式计算机来说确实如此,但许多目前使用的移动设备在渲染网页时的速度就像一台旧的奔腾 III :( 所以这篇文章似乎仍然非常有意义。
这意味着使用框架系统实际上很慢吗?
因为它只是将多个类串联起来,所以看起来还可以,但仍然没有 ID 那么快。这是正确的吗?
没错,Charlie,但一般来说,你提到的问题并不是导致页面变慢的最大问题。更多信息请参见 CSS 技巧。
有人见过用于测量特定页面渲染性能的工具吗?就像 Fiddler 用于测量服务器速度一样,我需要一个工具来分析特定页面渲染中的性能影响。
非常有意思的话题,我最近一直在思考这些问题。尤其是在使用 SASS 和嵌套一年后,看到了创建的无休止的后代选择器。出于这个原因,我现在尝试使用子选择器代替。
我有一个快速问题。这里提出的理由意味着 $(‘#object’).find(‘a’) 应该比 $(‘#object a’) 更有效,因为我们“覆盖了” CSS 的从右到左原则。这是正确的吗?