导出 DOM 元素的 CSS

48

我经常在网页上发现漂亮的样式。为了复制DOM元素的CSS,我使用Google Chrome开发者工具检查该元素,并查看各种CSS属性,然后手动将它们复制到我的样式表中。

有没有办法轻松地导出给定DOM元素的所有CSS属性呢?


1
有人可能可以写一个快速的程序来完成这个任务。 - Freesnöw
3
使用Chrome开发者工具,您可以单击样式或计算样式中的任何位置,然后按Ctrl + A,接着按Ctrl + C以复制这些给定区域内的所有样式。在样式选项卡中,它并不完美,因为它会提取一些额外的内容。但比逐个选择要好一些。 - Doozer Blake
我可以制作一个书签小程序来完成这个任务... - zzzzBov
我必须说我很惊讶,没有人想出一种方法来做到这一点,虽然我想从你选择的开发工具中复制和粘贴足够容易。话虽如此,我认为能够导出元素的CSS将是一个不错的功能。 - Andy Rose
请查看在类似问题上发布的Chrome扩展程序:https://dev59.com/vmsz5IYBdhLWcg3wpZhF - Justin Ryder
显示剩余2条评论
3个回答

56

以下是一个exportStyles()方法的代码示例,它应该返回一个CSS字符串,其中包括给定元素的所有内联和外部样式,但不包括默认值(这是主要难点)。

例如:console.log(someElement.exportStyles());

由于您正在使用Chrome浏览器,因此我没有费心让它与IE兼容。 实际上,它只需要浏览器支持getComputedStyle(element)方法即可。

Element.prototype.exportStyles = (function () {  

    // Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result.
    var defaultStylesByTagName = {};

    // Styles inherited from style sheets will not be rendered for elements with these tag names
    var noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true};

    // This list determines which css default values lookup tables are precomputed at load time
    // Lookup tables for other tag names will be automatically built at runtime if needed
    var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"];

    // Precompute the lookup tables.
    for (var i = 0; i < tagNames.length; i++) {
        if(!noStyleTags[tagNames[i]]) {
            defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]);
        }
    }

    function computeDefaultStyleByTagName(tagName) {
        var defaultStyle = {};
        var element = document.body.appendChild(document.createElement(tagName));
        var computedStyle = getComputedStyle(element);
        for (var i = 0; i < computedStyle.length; i++) {
            defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]];
        }
        document.body.removeChild(element); 
        return defaultStyle;
    }

    function getDefaultStyleByTagName(tagName) {
        tagName = tagName.toUpperCase();
        if (!defaultStylesByTagName[tagName]) {
            defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName);
        }
        return defaultStylesByTagName[tagName];
    }

    return function exportStyles() {
        if (this.nodeType !== Node.ELEMENT_NODE) {
            throw new TypeError("The exportStyles method only works on elements, not on " + this.nodeType + " nodes.");
        }
        if (noStyleTags[this.tagName]) {
            throw new TypeError("The exportStyles method does not work on " + this.tagName + " elements.");
        }
        var styles = {};
        var computedStyle = getComputedStyle(this);
        var defaultStyle = getDefaultStyleByTagName(this.tagName);
        for (var i = 0; i < computedStyle.length; i++) {
            var cssPropName = computedStyle[i];
            if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) {
                styles[cssPropName] = computedStyle[cssPropName];
            }
        }

        var a = ["{"];
        for(var i in styles) {
            a[a.length] = i + ": " + styles[i] + ";";
        }
        a[a.length] = "}"
        return a.join("\r\n");
    }

})();

这段代码是基于我为一个稍微相关的问题提供的答案而编写的:提取当前DOM并将其作为带有样式的字符串打印


2
不过我有点觉得你没有包括 :focus:blur等。但是目前为止做得非常好! - Randomblue
@Randomblue:没错,它不包括伪类样式。我会考虑一下的! - Luc125
我已经为伪类设置了一份奖金!希望你能得到它。 - Randomblue
可以通过使用例如 getComputedStyle(element, ":first-letter") 来找到与伪元素(如 :first-letter:first-line)相关联的样式,但在我的代码中实现它可能会使所需的计算时间增加三倍,仅针对两个伪元素,并且对于更多的伪元素来说,速度会变得更慢... - Luc125
对于伪类(:active:hover等),getComputedStyle 根本不起作用。 无论如何,如果页面包含像 theElement.addEventListener("onmouseover", function (event) { $(this).addClassName(someClass); }); 这样的代码呢? 那么检索动态样式的唯一方法将是通过编程触发事件 - 这对于悬停事件可能没问题,但对于单击或聚焦事件则不行! - 或在调用 exportStyles 之前手动悬停或聚焦元素,这不完全是您想要的,我很抱歉... - Luc125
如果您想要获取键值格式,可以使用类似于以下内容的代码:document.querySelector('your-querry-selector').exportStyles().replace(/\r?\n|\r/g,'').replace('{','').replace('}','').split(";").forEach(function(item, index){var key, value, touple = item.split(":");key=touple[0];value=touple[1]; if(typeof window.temp === 'undefined'||index==0)window.temp=[];temp[key]=value;}); - sajed zarrinpour

2
我在引用 Doozer Blake 的优秀答案,他在上面的评论中提供了。如果你喜欢这个答案,请在上面给他的原始评论点赞:

虽然不是直接回答,但使用 Chrome 开发者工具,您可以单击 Styles 或 Computed Styles 中的任意位置,按 Ctrl+A 然后按 Ctrl+C 复制这些区域中的所有样式。在 Style 选项卡中并不完美,因为它会捕捉到一些额外的内容。不过比一个一个选择好多了。– Doozer Blake 3 小时前

您也可以使用 Firefox 的 Firebug 来执行相同操作,使用 Firebug 的“Computed”侧面板


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接