使用Javascript将CSS样式表作为字符串注入

时间:2013-03-19 16:33:46

标签: javascript css dom google-chrome-extension

我正在开发Chrome扩展程序,我希望用户能够添加自己的CSS样式来更改扩展程序页面(而不是网页)的外观。我已经研究过使用document.stylesheets,但似乎它希望拆分规则,并且不会让你注入完整的样式表。是否有一个解决方案可以让我使用字符串在页面上创建一个新的样式表?

我目前没有使用jQuery或类似的,所以最好使用纯Javascript解决方案。

4 个答案:

答案 0 :(得分:57)

您可以创建样式元素并将字符串添加为innerHTML。像这样:

function addStyleString(str) {
    var node = document.createElement('style');
    node.innerHTML = str;
    document.body.appendChild(node);
}

addStyleString('body { color: red }');
addStyleString('body { background: silver }');
// This way allows you to add CSS in multiple passes

重要编辑:请注意,IE9及以下版本仅允许使用up to 32 stylesheets,因此请注意使用上述代码段。在IE10中,该数字增加到4095。)

如果,当用户添加新CSS时,您想删除旧样式并添加新样式,则可以将该功能切换为一个节点的引用。

(function() {
    var node = document.createElement('style');
    document.body.appendChild(node);
    window.addStyleString = function(str) {
        node.innerHTML = str;
    }
}());

addStyleString('body { color: red }');
addStyleString('body { background: silver }');
// This way will remove the old style when the new one is added

答案 1 :(得分:15)

感谢this guy,我找到了正确的答案。以下是它的完成方式:

function addCss(rule) {
  let css = document.createElement('style');
  css.type = 'text/css';
  if (css.styleSheet) css.styleSheet.cssText = rule; // Support for IE
  else css.appendChild(document.createTextNode(rule)); // Support for the rest
  document.getElementsByTagName("head")[0].appendChild(css);
}

// CSS rules
let rule  = '.red {background-color: red}';
    rule += '.blue {background-color: blue}';

// Load the rules and execute after the DOM loads
window.onload = function() {addCss(rule)};

fiddle

答案 2 :(得分:3)

我最近有同样的需求,写了一个与Liam相同的功能,除了允许多行CSS。

injectCSS(function(){/*
    .ui-button {
        border: 3px solid #0f0;
        font-weight: bold;
        color: #f00;
    }
    .ui-panel {
        border: 1px solid #0f0;
        background-color: #eee;
        margin: 1em;
    }
*/});

// or the following for one line

injectCSS('.case2 { border: 3px solid #00f; } ');

source of this function。您可以download Github repo example usage here。或者查看更多use it with RequireJS

我的偏好是{{3}},但在没有AMD加载程序的情况下它也可以作为一个全局函数。

答案 3 :(得分:1)

您听说过诺言吗?它们可以在所有现代浏览器上使用,并且使用起来相对简单。看一下将css注入html头的简单方法:

function loadStyle(src) {
    return new Promise(function (resolve, reject) {
        let link = document.createElement('link');
        link.href = src;
        link.rel = 'stylesheet';

        link.onload = () => resolve(link);
        link.onerror = () => reject(new Error(`Style load error for ${src}`));

        document.head.append(link);
    });
}

您可以按以下方式实现它:

window.onload = function () {
    loadStyle("https://fonts.googleapis.com/css2?family=Raleway&display=swap")
        .then(() => loadStyle("css/style.css"))
        .then(() => loadStyle("css/icomoon.css"))
        .then(() => {
            alert('All styles are loaded!');
        }).catch(err => alert(err));
}

真的很酷,对吧?这是一种使用Promises决定样式优先级的方法。

或者,如果您想同时导入所有样式,则可以执行以下操作:

function loadStyles(srcs) {
    let promises = [];
    srcs.forEach(src => promises.push(loadStyle(src)));
    return Promise.all(promises);
}

像这样使用它:

loadStyles([
    'css/style.css',
    'css/icomoon.css'
]);

您可以实现自己的方法,例如按优先级导入脚本,同时导入脚本或同时导入样式和脚本。如果我获得更多选票,我将发布我的实施方案。

如果您想了解有关承诺的更多信息,请阅读更多here