【问题标题】:JavaScript get list of styles currently applied to an elementJavaScript 获取当前应用于元素的样式列表
【发布时间】:2015-12-15 20:14:06
【问题描述】:

仅列出呈现的样式,而不是未应用的任意样式

我已经尝试了很多方法来将样式应用于元素,但都出现了空白。

请不要引用getComputedStyle 作为解决方案,除非您可以解决垃圾退货问题。

主要问题是window.getComputedStyle(document.querySelector('ANY ELEMENT')).fill 将返回"rgb(0, 0, 0)",这在几乎所有情况下不是正确的样式,并且没有明显的方法来确定它是否实际被应用。

上面的例子不是唯一的问题案例; getComputedStyle 返回的大量规则是错误的,如果应用它们将彻底改变页面的外观。

静态解析不是一个选项,因为在某些情况下 .css 文件位于另一个没有跨域标头的服务器上;它还隐藏了document.styleSheets 中常见的样式。

有没有什么方法可以获取应用样式的列表,仅此而已?

根据要求,此代码将演示问题(在 Chrome 上):

var all = document.getElementsByTagName('*');
for(var i in all)
    if (all[i].style) all[i].style.cssText = window.getComputedStyle(all[i]).cssText;

编辑:我的答案包含适用于所有浏览器的代码。我保留在上面以保留评论线程。

【问题讨论】:

  • 要确定是否呈现了 特定 样式很复杂,更不用说所有样式了。谷歌“如何判断一个 html 元素是否可见”,以了解需要多少代码才能做到这一点。每个广泛的样式类别都可能都有奇怪的边缘情况。可能有一个解决方案,但我怀疑它是否实用。如果有人证明我错了,我会很兴奋。
  • @JaredSmith 我已经编写了代码来进行可见性检查,以及通过模拟如何呈现某些内容以及可能覆盖哪些元素来进行遮挡检查。当信息可用时它并不复杂,在这种情况下我不相信它。浏览器清楚地呈现页面上的所有内容,因此它确切知道它应用了哪些样式来生成它正在显示的页面,但似乎没有提供此信息的 API(原因不明)。
  • 复杂?不,我说错了。乏味?是的。 getBoundingClientRectpositionz-index 用于每个元素。根据 z-index(如果相关)计算重叠和遮挡。不要忘记父母的溢出!将所有这些乘以所有可能的显示、颜色、字体、大小等 css 属性。如果它适合任何合理大小的 js,我会感到惊讶,如果它具有可接受的性能特征,我会更惊讶。
  • @JaredSmith 有什么意义?检查是否应用了样式应该很简单,它与检查元素是否可见并不相似。可靠地检查可见性是相当多的代码,但这完全不相关
  • 这似乎是关于父子关系的问题或循环问题。如果你一个一个地尝试而不是循环所有元素,它可以正常工作。

标签: javascript html css


【解决方案1】:

这里是不需要检查深度的版本。 您代码中的问题是前一个元素中的内联样式分配会影响下一个结果的 getComputedStyle 结果。这意味着 getComputedStyle 的值总是在循环中变化。您可以先将其存储在这样的数组中。

var all = document.getElementsByTagName('*');
tmpArr = []
for(var i in all) {
    if (all[i].style) {
        tmpArr[i] = window.getComputedStyle(all[i]).cssText;
    }
}
for(var i in all) {
    if (all[i].style) {
        all[i].style.cssText = tmpArr[i]; ;
    }
}
console.log("finish");

你可以把tmpArr[i] = window.getComputedStyle(all[i]).cssText;改成tmpArr[i] = window.getComputedStyle(all[i]).cssText + "-webkit-text-fill-color:#691099!important";来测试是否有效

inline style 太多,打开inspector会很慢,但是只要把style设置成inline style就可以解决问题。

【讨论】:

  • 我添加了一个更准确地满足问题的答案,并且还有应用程序的测试代码
【解决方案2】:

部分答案(更新):

通过调用我的函数getRenderedStyles可以只获取活动样式:

getRenderedStyles 现在绕过活动样式表以获得更准确的输出。

function getRenderedStyles(element) {
    var tmpele, tmpstyle, elestyle, varstyle, elecolor, eletag;
    var styles   = {};
    var defstyle = {};
    elestyle   = window.getComputedStyle(element);
    elecolor   = elestyle.color; 
    eletag     = element.tagName;
    var frag = document.createDocumentFragment();
    frag.appendChild(document.documentElement);
    tmpele   = document.appendChild(document.createElement(eletag));
    tmpstyle = window.getComputedStyle(tmpele);
    styles['color']     = elecolor===tmpstyle.color?undefined:elecolor;
    tmpele.style.color  = elecolor; // workaround for color propagation on other styles 
    for (var i in tmpstyle)
        defstyle[i] = tmpstyle[i];
    tmpele.remove();
    document.appendChild(frag);
    varstyle = element.style;
    for (var i in varstyle) {
        if ((((typeof varstyle[i])==="string"))&&(i!=="cssText")) {
            if ((defstyle[i]!==elestyle[i]))
                styles[i] = elestyle[i];
        }
    }
    return styles;
}

遗憾的是,浏览器在某些情况下似乎仍然返回无效样式,因此存在 caviat。经常改变元素的位置。

要验证这一点,您可以运行以下代码,考虑到父/子继承,以尝试将当前样式正确应用到页面:

function DOMDepth(element) {
    var cur  = element;
    var deep = 0;
    while(cur.parentNode)
        deep++, cur = cur.parentNode;
    return deep;
}

function getElementsByDepth() {
    var all = document.getElementsByTagName('*');
    var depth_map = {};
    var deepest   = 0;
    for(var i in all) {
        var depth = DOMDepth(all[i]);
        deepest   = depth>deepest?depth:deepest;
        depth_map[depth] = depth_map[depth] || [];
        depth_map[depth].push(all[i]);
    }
    depth_map['deepest'] = deepest;
    return depth_map;
}

function inlineComputedStyles() {
    var depth_map = getElementsByDepth();
    for (var i = depth_map.deepest; i>0; i--) {
        var elements = depth_map[i];
        for (var j in elements) {
            var styles = getRenderedStyles(elements[j]);
            for (var k in styles) {
                elements[j].style[k] = styles[k];
            }
        }
    }
}

我已经测试了前面的内容,可以确认它没有遇到问题中sn-p的颜色问题。遗憾的是,我不确定为什么某些元素仍然会发生变化,或者是否有办法解决它。

特别感谢 Kit Fung 指出继承问题。

【讨论】:

  • 在 Kit Fung 的回答中,变形显得更加随机,而考虑到深度的变形更加均匀。这可能是剩余差异的线索
猜你喜欢
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 2021-09-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-31
  • 1970-01-01
  • 2015-03-28
相关资源
最近更新 更多