JavaScript获取当前应用于元素的样式列表 仅列出渲染样式,而不是未应用的任意样式

JavaScript获取当前应用于元素的样式列表 仅列出渲染样式,而不是未应用的任意样式,javascript,html,css,Javascript,Html,Css,我尝试了很多方法来将样式应用于元素,但结果都是空白 请不要引用getComputedStyle作为解决方案,除非您可以解决垃圾退货问题 主要问题是window.getComputedStyle(document.querySelector('ANY ELEMENT')).fill将返回“rgb(0,0,0)”,这在几乎任何情况下都不是正确的样式,并且如果实际应用或不应用它,则没有明显的方式来取消语言 上述例子并不是唯一的问题案例;getComputedStyle返回了大量错误的规则,如果应用这些

我尝试了很多方法来将样式应用于元素,但结果都是空白

请不要引用
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;

编辑:我的答案有代码,可以在所有浏览器上运行。我保留以上内容以保留注释线程。

以下是不需要检查深度的版本。 代码中的问题是,前一个元素中内联样式的赋值将影响下一个结果的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(所有[i]).cssText
to
tmpArr[i]=window.getComputedStyle(全部[i]).cssText+“-webkit文本填充颜色:#691099!重要”以测试它是否工作

由于内联样式太多,如果您打开inspector会很慢,但如果您只需要将样式设置为内联样式,则会解决问题。

部分答案(已更新): 通过调用my函数
getRenderedStyles
,可以仅获取活动样式:

getrenderdstyles
现在绕过活动样式表以获得更精确的输出

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

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

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];
            }
        }
    }
}
我已经测试了前面的代码,可以确认它没有问题中代码片段的颜色问题。可悲的是,我不确定为什么某些元素仍然在变化,或者是否有办法解决它


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

要确定是否呈现了特定的样式,这很复杂,更不用说所有样式了。谷歌“如何判断一个html元素是否可见”,了解需要多少代码才能做到这一点。每一大类风格都可能有奇怪的边缘情况。一个解决方案可能是可行的,但我怀疑它是否切实可行。如果有人证明我错了,我会非常激动的。@JaredSmith我已经编写了代码,可以通过模拟渲染的方式以及上面可能有什么元素来进行可见性检查和遮挡检查。当信息可用时,这并不复杂,在这种情况下,我不相信是这样。浏览器显然正在呈现页面上的所有内容,因此它确切地知道应用于显示页面的样式,但似乎没有API提供此信息(原因未知)。复杂吗?不,我说错了。乏味的对<代码>getBoundingClientRect
位置
,以及每个元素的
z索引
。根据z索引计算重叠和遮挡(如果相关)。不要忘记在父级上溢出!将所有这些乘以所有可能的显示、颜色、字体、大小等css属性。如果它适合任何大小合理的js,我会感到惊讶,如果它具有可接受的性能特性,我会更加惊讶。@JaredSmith有什么意义?检查是否应用了样式应该很简单,这与检查元素是否可见有很大的不同。这是一个相当大的代码量,以可靠地检查可见性,但这是完全无关的-似乎是有关父&子关系或循环的问题。如果你一个接一个地尝试,而不是循环所有元素,它工作正常。我添加了一个更准确地满足问题的答案,并且还有应用程序的测试代码。冯杰的答案变形看起来更随机,而考虑深度时的变形更均匀。这可能是一个线索,以其余的描述
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];
            }
        }
    }
}