使用浏览器解析CSS而不触及DOM /样式

时间:2016-11-20 20:16:53

标签: javascript css

我有类似的东西:

const someCSS = `
    .foo {
        padding: 20px;
        background-color: #ddf;
        width: 100px;
    }
    .bar {
        height: 100px;
    }
    .foo {
        padding-top: 30px; /* this overrides the previous one */
    }
`;

我可以添加这个做DOM并使用每个规则(jsFiddle)取回所有选择器:

const style = document.createElement('style');
style.innerHTML = someCSS;
document.head.append(style);

const styleSheet = Array.from(document.styleSheets).find(ss => ss.ownerNode == style);
const rules = Array.from(styleSheet.rules).map(rule => rule.cssText);

function styleToObject(rules, mergeWith = {}) {
    return [...rules].reduce(
        (obj, rule) => (obj[rule] = rules[rule], obj), mergeWith
    );
}

const styleObject = Array.from(styleSheet.rules).reduce(
    (obj, rule) => (obj[rule.selectorText] = styleToObject(rule.style, obj[rule.selectorText]), obj), {}
);

document.querySelector('pre').appendChild(
    document.createTextNode(JSON.stringify(styleObject, null, '\t'))
);

得到这样的东西:

{
    ".foo": {
        "padding-top": "30px",
        "padding-right": "20px",
        "padding-bottom": "20px",
        "padding-left": "20px",
        "background-color": "rgb(221, 221, 255)",
        "width": "100px"
    },
    ".bar": {
        "height": "100px"
    }
}

有没有其他方法可以让浏览器执行此操作,而无需触及DOM?我的意思是有一个浏览器解析的CSS文本(没有正则表达式),而没有在页面中实际设置任何样式。

我想将它添加到iFrame中,但在将其附加到DOM之前,该文档不可用...

1 个答案:

答案 0 :(得分:6)

简短的回答是否定的,你不能不改变DOM。

如果您关心的是添加的元素触发重绘或加载的样式以任何方式影响页面,您可以添加一个&#34; never-matching&#34;媒体规则到您创建的<style> - 元素。

例如:

style.setAttribute('media', '(max-width: 0)');

Working fiddle

修改的 正在研究一个利用这个技巧/黑客/解决方案的例子,你可以找到它here。现在才注意到问题的更新在力学上非常相似(尽管我的样本将在较少的绿色浏览器中工作(不是问题的一部分,我知道)。)

我检查了一些我在尝试做类似事情时遇到的消息来源,最值得注意的是MDN - CSSStylesheets非常透彻并说明:

  

创建CSSStyleSheet对象并将其插入到文档中   当样式表为时,styleSheets会自动由浏览器列出   加载文档。由于document.styleSheets列表不能   直接修改,没有创建新CSSStyleSheet的有用方法   手动对象(尽管Constructable Stylesheet Objects可能会获得   在某些时候添加到Web API)。要创建新样式表,   在文档中插入或元素。

(强调我的。已经由@Ouroborus提到的CSO)

我还没有对各种浏览器进行过大量测试,但是我没有通过向<head>添加(媒体查询)样式节点来看到重绘和/或重排,不像添加<iframe>

我很好奇,如果有人在这里知道一个依赖于(交叉)浏览器处理CSS的解决方案而没有点击DOM,因为我还没有找到它并最终建立了一个Tokenizer / Lexer创造了这样一棵树)。