使用 CSS 生成的内容(即伪元素)是不是比添加更多 DOM 元素更有效(即解析/渲染更快)?
Posted
技术标签:
【中文标题】使用 CSS 生成的内容(即伪元素)是不是比添加更多 DOM 元素更有效(即解析/渲染更快)?【英文标题】:Is the use of CSS generated content (i.e. pseudo elements) more efficient (i.e. parsed/rendered faster) than adding more DOM elements?使用 CSS 生成的内容(即伪元素)是否比添加更多 DOM 元素更有效(即解析/渲染更快)? 【发布时间】:2013-04-08 02:27:02 【问题描述】:为了让我的移动网络应用程序保持精简和高效,我试图在任何给定时间限制 DOM 上的元素数量。我打算限制使用 DOM 元素的一种方法是尽可能使用伪 :before
和 :after
元素生成内容。
例如,不是用这样的元数据表示一个列表项:
<dd class="item">
<div class="name">Name</div>
<div class="desc">Description</div>
<div class="location">Location</div>
<div class="genre">Genre</div>
</dd>
我可以这样表示(并使用content:
属性来显示元数据):
<dd class="child"
data-name="Name"
data-desc="Description"
data-location="Location"
data-genre="Genre">
</dd>
因此,一个 DOM 元素具有数据属性,而不是 5 个单独的元素和可以说是更清晰的标记。 此处演示:http://jsfiddle.net/quc8b/2/
这种技术真的会提高性能吗?我的想法是,使用更少的 DOM 元素,javascript 应该可以更快地解析,并且我应该能够更快地添加/删除列表项节点。但是渲染(即绘画、布局和回流)会更快吗?换句话说,CSS 生成的内容渲染/解析是否比传统元素和文本节点更快或更有效?
浏览器如何在渲染树和文档树中内部处理 CSS 生成的内容对我来说是未知的(也许是影子 DOM?)。有没有讨论这个的文章?
【问题讨论】:
伪元素在 DOM 中不存在,直到 CSS 规则将其插入到元素之前或之后。这意味着额外的 DOM 操作,尽管不需要额外的逻辑来匹配选择器本身。 从语义上讲,数据的两种表示形式存在很大差异。第一个表示带有名称、描述、位置和类型的定义。第二个表示定义。就是这样。如果不出意外,通过 CSS 渲染内容肯定无法访问。 @ricardohdz 但是这种 DOM 操作方法是否比通过 javascript 操作更有效? 如果你更关心性能,我会去通过 CSS 来实现它,因为 Javascript 只会在所有元素都绘制好并且文档准备好之后才遍历/操作 DOM(此时您的 CSS 伪选择器已被应用)。 @MikeMcCaughan 同意,但在我的特定场景中,数据在标记中的表示方式对我来说不是效率问题。我想了解不同类型的 DOM 节点之间的性能关系,以及它们如何通过 javascript 影响布局/流时间和 DOM 遍历时间。如果通过 JS 和 CSS 可以访问 less,那么也许这可能会提高性能? 【参考方案1】:请注意这个答案是多年前给出的。下面列出的许多陈述不再有效。在提供应可访问的内容时,仍然不鼓励使用伪元素。
我不知道伪元素的性能,但我担心你把性能放在首位。
与“真实” DOM 节点相比,伪元素具有相当大的缺点:
它们不能过渡或动画 您不能使用 Javascript 动态更改它们的外观 它们对搜索引擎来说远没有那么“重要” 它们在调试时很麻烦 他们的数量限制为一个:before
和一个:after
元素
它们不能包含 html 标记,例如链接或其他容器
你伤害了内容和外观分离的概念
某些 HTML 元素不能有伪元素
如需进一步阅读,请参阅Tag-Wiki
我相信还有更多。另一方面是某种性能提升,我相信这将是微不足道的。
【讨论】:
在开发类似原生的嵌入式 Web 应用程序(这是我的用例)时,性能至关重要。如果整体技术可以使应用程序更具响应性,我愿意容忍某些 CSS 可访问性限制。 是的,这不能回答问题。 它们可以被转换/动画它们可以使用 JS 改变外观(通过添加类/属性,但这是可能的)。它们在调试时并不麻烦(曾经使用过 Google Chrome 开发者工具?)它们可以包含多个信息,单个 :before 或 :after ,因此每个 1 就足够了。没有内容和外观问题的分离。此外,在许多情况下,性能至关重要,使用 CSS 将一些元素转换为有用的小部件比使用 JS 容易得多,您不需要清理它 这是两年多以前写的。目前,没有任何开发工具可以显示这些元素。【参考方案2】:我也有兴趣弄清楚这一点。所以我做了一个简单的小测试用例。
我创建了两个html页面进行比较:
A.伪选择器:
HTML:其中 50.000 个:<p>paragraph</p>
CSS:p:before display: inline-block; width: 10px; height: 10px; margin-right: 5px; background-color: red; content: "";
B.许多 DOM 元素:
HTML:其中 50.000 个:<p><span class="icon"></span> paragraph</p>
CSS:.icon display: inline-block; width: 10px; height: 10px; margin-right: 5px; background-color: red;
测试:
我使用了在 2015 Macbook Pro 上运行的 Chrome Devtools 性能监视器。
Test1:“开始分析并重新加载页面”
选项 B 以大约 400 毫秒的优势输掉了比赛。 解析需要 2452 毫秒,而“伪”变体需要 2033 毫秒。 我将这个测试运行了 3 次,结果相似。
Test2:调整窗口大小
为了测量重新布局,我开始了一个单独的记录,通过将浏览器窗口从全屏更改为半屏(使用窗口管理器中的快捷键)来调整浏览器窗口的大小 3 次
“许多 DOM 元素”是赢家,渲染时间为 1136 毫秒,而“伪元素”则为 1463 毫秒。
Test3:回流
我试图通过使用这段 Javascript 测量页面高度来引起回流:document.body.offsetHeight;
但是执行的时间从来没有超过 4 毫秒……没有足够的时间来可靠地衡量性能。
显然 50.000 个元素不足以导致该区域的任何显着放缓。
PS:测试选择不是那么科学,它们只是我最先想到的
【讨论】:
以上是关于使用 CSS 生成的内容(即伪元素)是不是比添加更多 DOM 元素更有效(即解析/渲染更快)?的主要内容,如果未能解决你的问题,请参考以下文章