【问题标题】:How to determine if HTML element has pseudo element?如何判断 HTML 元素是否有伪元素?
【发布时间】:2016-10-23 18:45:23
【问题描述】:

有没有办法确定给定的 HTML 元素是否应用了伪元素(::before / ::after)而不调用

window.getComputedStyle(element, ":before/:after");

已编辑:答案是

getComputedStyle 的问题在于性能。我需要验证页面上的每个元素是否具有伪元素——这就是性能非常关键的原因。 我尝试从 document.styleSheets 访问 cssRules 以查找末尾带有 ::before 或 ::after 的选择器,将其删除并找到与选择器其余部分匹配的元素,但此解决方案有其自身的问题:

  • 无法访问来自不同域的样式表
  • 可能需要检查数千个 cssRules(再次检查性能)

我还尝试比较带有和不带有伪元素的元素的大小和偏移量,但没有任何效果。即使没有准确的方法,我也很乐意找到一种方法,将要检查的元素数量至少减少 30%。


当我确定该元素具有伪元素时,我终于可以调用 getComputedStyle 来调查伪元素样式并对其进行更改。这部分完美运行。


已编辑:我无法控制源页面。页面样式可以从不同的域动态上传。假设我的代码是一个内容脚本或库,例如必须将所有伪元素前景更改为基于该伪元素的其他 CSS 属性计算的某种颜色。

所以主要问题是更改基于其他 CSS 属性,如果不实际检索伪元素的计算样式并计算更改,您无法为所有伪元素设置相同的样式。

例如你有 youtube.com 页面,你需要找到所有的伪元素和

  • 如果此伪元素具有背景图像,则缩放该元素
  • 如果此伪元素只有一个文本,则将其颜色更改为红色
  • 等等……

【问题讨论】:

  • 您能否提供更多详细信息,说明您正在做什么以及为什么?也许你试图达到的目标可以用不同于你想象的方式来实现......
  • 我需要找到页面上所有的伪元素并改变它们的样式。例如字体颜色。
  • 点击浏览器中的 F12 按钮。找到这个<link href="http://domain.com/path/to/css/style.css" rel="stylesheet">href 值复制并粘贴到您的浏览器地址栏并转到那里。复制并粘贴到您的帖子中。除非您能在中途遇到我们,否则我们无法为您提供帮助,所以发布您的代码,您应该阅读minimal reproducible example
  • 不确定它是否真的能改善事情,但您可以排除替换元素,如 imginputtextareaselect 等不允许伪元素。
  • 这很有趣 - 不知道某些元素不能有伪 - 将检查它。谢谢。

标签: javascript html css pseudo-element


【解决方案1】:

究竟是什么导致您现有的解决方案出现问题?

这种遍历元素的方法:

var allElements = document.getElementsByTagName("*");
for (var i = allElements.length; i--;) {
  //var usedStyle = window.getComputedStyle(allElements[i], ":before/:after");    
  ...
}

大约每 1 毫秒有 数千个 个元素。

并且getComputedStyle 的调用不会太慢,因为它会获取在调用时已经计算的数据(在呈现的文档上)。

所以这一切都应该足够快。是的,原则上它是O(N) 任务,但只运行一次,对吧?

【讨论】:

  • “并且 getComputedStyle 的调用不会太慢,因为它会获取在调用时已经计算好的数据” - 不,没有那么容易。调用 getComputedStyle 会导致重排,请参阅 stackoverflow.com/a/1278213/1427878
  • 是的,它非常慢 - 例如使用 youtube 页面几乎需要 5 秒!
  • 最后发现它并没有那么慢 - 我只是同时有另一个进程减慢了一切。所以我会坚持使用 getComputedStyle
【解决方案2】:

我认为getComputedStyle() 是了解元素是否附加了伪元素的唯一可靠方法。

但由于无法通过 DOM 方法对其进行编辑,这意味着您必须在文档中添加新规则。

所以一个简单的解决方案,如果如您上次编辑中所述,您将对 所有 伪元素应用相同的规则,则使用通配符 * 选择器:

*:before,*:after{ /*your rules*/ }

var style = document.createElement('style');
style.innerHTML = `*:before,*:after{
  color: green !important;
}`;
setTimeout(function() {
  document.head.appendChild(style);
}, 1500);
div:before {
  content: 'hello';
  color: blue;
}
div:after {
  content: 'world';
  color: red;
}
<div></div>

【讨论】:

  • 是的,我现在确实使用类似的方法。我为所有者元素设置自定义属性的唯一区别:
  • <div before-style="1231243523341">...</div> => [before-style="1231243523341"]:before { color: red; }
  • @pasza 请记住,:before,:after 的已定义规则可能比您的规则具有更高的特异性,因此您的样式可能不会被应用。
  • 我忘了在我的问题中提到这一点(现在是),我需要根据每个伪元素的其他 CSS 属性对其进行不同的更改......所以我仍然需要获得实际的计算样式。所以主要的问题是如何找出那个元素是伪元素。
  • 是的,这就是为什么我实际上使用这样的东西:[before-style="1231243523341"]:not(important):before { color: red !important;但即使这样也不能保证结果...
猜你喜欢
  • 1970-01-01
  • 2014-07-18
  • 2013-07-25
  • 2011-11-02
  • 2014-01-11
  • 2010-09-25
  • 1970-01-01
  • 2010-10-20
  • 2011-02-22
相关资源
最近更新 更多