如何使用Javascript创建<style>标签?


336

我正在寻找一种<style>使用JavaScript 将标记插入HTML页面的方法。

到目前为止,我发现的最好方法是:

var divNode = document.createElement("div");
divNode.innerHTML = "<br><style>h1 { background: red; }</style>";
document.body.appendChild(divNode);

这在Firefox,Opera和Internet Explorer中有效,但在Google Chrome中不起作用。<br>IE的前面也有点难看。

有人知道创建<style>标签的方法吗

  1. 更好

  2. 使用Chrome吗?

或许

  1. 这是我应该避免的非标准事情

  2. 三种运行良好的浏览器都很棒,到底谁在使用Chrome?

Answers:


662

尝试将style元素添加到head而不是body

这已在IE(7-9),Firefox,Opera和Chrome中进行了测试:

var css = 'h1 { background: red; }',
    head = document.head || document.getElementsByTagName('head')[0],
    style = document.createElement('style');

head.appendChild(style);

style.type = 'text/css';
if (style.styleSheet){
  // This is required for IE8 and below.
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}

19
仅供参考,document.head所有主要浏览器均支持。
罗伯W

30
@RobW-IE8及以下版本不支持。现代浏览器支持该功能,但并非所有主流浏览器都支持。
蒂姆(Tim)

5
为什么不只是使用document.querySelector("head")?IE8支持此事件的来源
allenhwkim 2014年

8
@allenhwkim:答案早于引入querySelector();今天,我可能会选择document.head,自IE9
Christoph

2
在访问之前,我必须将style元素附加到头部style.styleSheet.cssText。在添加之前style.styleSheet为null。
Will Hawker

38

这是一个将IE样式createStyleSheet()addRule()方法添加到不具有IE样式和方法的浏览器的脚本:

if(typeof document.createStyleSheet === 'undefined') {
    document.createStyleSheet = (function() {
        function createStyleSheet(href) {
            if(typeof href !== 'undefined') {
                var element = document.createElement('link');
                element.type = 'text/css';
                element.rel = 'stylesheet';
                element.href = href;
            }
            else {
                var element = document.createElement('style');
                element.type = 'text/css';
            }

            document.getElementsByTagName('head')[0].appendChild(element);
            var sheet = document.styleSheets[document.styleSheets.length - 1];

            if(typeof sheet.addRule === 'undefined')
                sheet.addRule = addRule;

            if(typeof sheet.removeRule === 'undefined')
                sheet.removeRule = sheet.deleteRule;

            return sheet;
        }

        function addRule(selectorText, cssText, index) {
            if(typeof index === 'undefined')
                index = this.cssRules.length;

            this.insertRule(selectorText + ' {' + cssText + '}', index);
        }

        return createStyleSheet;
    })();
}

您可以通过添加外部文件

document.createStyleSheet('foo.css');

并通过以下方式动态创建规则

var sheet = document.createStyleSheet();
sheet.addRule('h1', 'background: red;');

这对尝试在陌生的CMS上下文中加载外部CSS文件很有帮助。我确实在addRule / removeRule部分遇到了麻烦,所以我消除了这些麻烦,一切正常。
Kirkman11年

33

我假设您要插入一个style标记而不是一个link标记(引用外部CSS),因此以下示例将执行以下操作:

<html>
 <head>
  <title>Example Page</title>
 </head>
 <body>
  <span>
   This is styled dynamically via JavaScript.
  </span>
 </body>
 <script type="text/javascript">
   var styleNode = document.createElement('style');
   styleNode.type = "text/css";
   // browser detection (based on prototype.js)
   if(!!(window.attachEvent && !window.opera)) {
        styleNode.styleSheet.cssText = 'span { color: rgb(255, 0, 0); }';
   } else {
        var styleText = document.createTextNode('span { color: rgb(255, 0, 0); } ');
        styleNode.appendChild(styleText);
   }
   document.getElementsByTagName('head')[0].appendChild(styleNode);
 </script>
</html>

另外,我在您的问题中注意到您正在使用 innerHTML。这实际上是将数据插入页面的非标准方式。最佳实践是创建一个文本节点并将其附加到另一个元素节点。

关于最后一个问题,您将听到有人说您的工作应该在所有浏览器上都能正常工作。这完全取决于您的听众。如果您的听众中没有人使用Chrome,请不要流汗。但是,如果您希望吸引尽可能多的受众,那么最好支持所有主要的A级浏览器


1
这基本上与我的解决方案相同;他们都不在IE中工作!
Christoph

附加文本节点在IE中不起作用。但是,将样式元素放在首位可以使我的解决方案在Chrome中正常工作!:-)

1
用于IE,请使用styleNode.styleSheet.cssText = ...
Christoph

7
(非常晚的评论)“这完全取决于您的受众群体。如果您的受众群体中没有人使用Chrome,那么请不要流汗。”这种态度导致人们在IE7甚至IE8可用后的多年里一直被锁定在IE6中。“但是我必须使用的Web应用程序只能在IE6中使用”
Stephen P 2010年

1
是的,您是对的,我也不一定要提倡这样做(因此,整体来说:“如果您想吸引尽可能多的受众,那么最好支持所有主要的A级浏览器”),但是知道平台的受众群体很重要。
汤姆(Tom)2010年

31

<style>标签应放置在<head>元素内,并且每个添加的标签应添加到<head>标签的底部。

使用insertAdjacentHTML将样式标签注入文档的head标签

本机DOM:

document.head.insertAdjacentHTML("beforeend", `<style>body{background:red}</style>`)


jQuery的

$('<style>').text("body{background:red}").appendTo(document.head)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


2
这是最好,最简单的解决方案,谢谢!
Ryzal Yusoff

同意,这是最好且最简单的方法,但是如果您无法控制它,请当心注入不良的CSS!
无尽的

24

一个适用于所有浏览器的示例:

var ss = document.createElement("link");
ss.type = "text/css";
ss.rel = "stylesheet";
ss.href = "style.css";
document.getElementsByTagName("head")[0].appendChild(ss);

7
错误的元素:style没有rel或没有href属性-您的意思是link
Christoph'Feb

4
哪些呢link元素有问题怎么办?OP要求style元素。这个答案与问题无关
vsync

2
@vsync style用于添加内联样式,link适用于样式表源,这具有避免跨浏览器问题的优点。
majick '16

7

通常,需要覆盖现有规则,因此在每种情况下都无法向HEAD附加新样式。

我想出了这个简单的函数,它总结了所有无效的 “附加到BODY”方法,并且使用和调试更加方便(IE8 +)。

window.injectCSS = (function(doc){
    // wrapper for all injected styles and temp el to create them
    var wrap = doc.createElement('div');
    var temp = doc.createElement('div');
    // rules like "a {color: red}" etc.
    return function (cssRules) {
        // append wrapper to the body on the first call
        if (!wrap.id) {
            wrap.id = 'injected-css';
            wrap.style.display = 'none';
            doc.body.appendChild(wrap);
        }
        // <br> for IE: http://goo.gl/vLY4x7
        temp.innerHTML = '<br><style>'+ cssRules +'</style>';
        wrap.appendChild( temp.children[1] );
    };
})(document);

演示:codepenjsfiddle


在最新的Firefox,Chrome ie8(或至少我键入它的方式)中完美运行。我真的不知道为什么这没有更多的要点。
哈里·佩科宁

这没有更多的要点,因为这是无效的,将<style>标记插入标记之外也不是一件好事<head>。样式标签不应出现在<head>标签中的其他任何地方。那是被广泛采用的html标准。有用于内联样式的样式属性,并且样式属性可以应用于标记内的任何<body>标记,包括<body>其自身的标记。
诡异的

该代码对我不起作用。我编写了一些短得多的代码,它们可以在三种浏览器中使用,并将在此处发布我的答案。
David Spector '18

当我向头部动态添加样式块时,我不知道为什么Chrome无法更新样式。我试过了,神奇地更新了它。我需要研究此代码中触发浏览器重新渲染CSS的实际区别是什么。但是,非常感谢!
prograhammer

5

该对象变量会将style标签附加到具有type属性和一个简单转换规则的head标签上,该规则与每个id / class / element匹配。随意修改内容属性并根据需要注入任意数量的规则。只要确保内容中的CSS规则保持一行即可(或者,如果愿意,可以“转义”每一行)。

var script = {

  type: 'text/css', style: document.createElement('style'), 
  content: "* { transition: all 220ms cubic-bezier(0.390, 0.575, 0.565, 1.000); }",
  append: function() {

    this.style.type = this.type;
    this.style.appendChild(document.createTextNode(this.content));
    document.head.appendChild(this.style);

}}; script.append();

1
我喜欢这个解决方案,所以我自己使用它来更改移动设备上的按钮大小,但是content属性需要在一行上是不正确的:只需使用+运算符将多个字符串(在多行上)连接起来。
RufusVS

真正。我知道,我知道。但是,有时候,我太懒惰了,无法按照我的预期去写。:D干杯。
诡异的

5

这是用于动态添加类的变体

function setClassStyle(class_name, css) {
  var style_sheet = document.createElement('style');
  if (style_sheet) {
    style_sheet.setAttribute('type', 'text/css');
    var cstr = '.' + class_name + ' {' + css + '}';
    var rules = document.createTextNode(cstr);
    if(style_sheet.styleSheet){// IE
      style_sheet.styleSheet.cssText = rules.nodeValue;
    } else {
      style_sheet.appendChild(rules);
    }
    var head = document.getElementsByTagName('head')[0];
    if (head) {
      head.appendChild(style_sheet);
    }
  }
}


4

每当您调用如下函数时,此函数都会注入css appendStyle
appendStyle('css you want to inject')

这是通过将style节点注入文档的头部来实现的。这与通常用于延迟加载JavaScript的技术类似。它在大多数现代浏览器中都能一致地工作。

appendStyle = function (content) {
  style = document.createElement('STYLE');
  style.type = 'text/css';
  style.appendChild(document.createTextNode(content));
  document.head.appendChild(style);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <h1>Lorem Ipsum</h1>
  <p>dolar sit amet</p>
  <button onclick='appendStyle("body { background-color: #ff0000;}h1 { font-family: Helvetica, sans-serif; font-variant: small-caps; letter-spacing: 3px; color: #ff0000; background-color: #000000;}p { font-family: Georgia, serif; font-size: 14px; font-style: normal; font-weight: normal; color: #000000; background-color: #ffff00;}")'>Press me to inject CSS!</button>
</body>

</html>

您还可以使用以下代码段延迟加载外部CSS文件:

appendExternalStyle = function (content) {
  link = document.createElement('LINK');
  link.rel = 'stylesheet';
  link.href = content;
  link.type = 'text/css';
  document.head.appendChild(link);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    html {
      font-family: sans-serif;
      font-display: swap;
    }
  </style>
</head>

<body>

  <h1>Lorem Ipsum</h1>
  <p>dolar sit amet</p>
  <button onclick='appendExternalStyle("data:text/css;base64,OjotbW96LXNlbGVjdGlvbntjb2xvcjojZmZmIWltcG9ydGFudDtiYWNrZ3JvdW5kOiMwMDB9OjpzZWxlY3Rpb257Y29sb3I6I2ZmZiFpbXBvcnRhbnQ7YmFja2dyb3VuZDojMDAwfWgxe2ZvbnQtc2l6ZToyZW19Ym9keSxodG1se2NvbG9yOnJnYmEoMCwwLDAsLjc1KTtmb250LXNpemU6MTZweDtmb250LWZhbWlseTpMYXRvLEhlbHZldGljYSBOZXVlLEhlbHZldGljYSxzYW5zLXNlcmlmO2xpbmUtaGVpZ2h0OjEuNjd9YnV0dG9uLGlucHV0e292ZXJmbG93OnZpc2libGV9YnV0dG9uLHNlbGVjdHstd2Via2l0LXRyYW5zaXRpb24tZHVyYXRpb246LjFzO3RyYW5zaXRpb24tZHVyYXRpb246LjFzfQ==")'>press me to inject css!</button>
</body>

</html>


这大概是我独立开发的方法。简短有趣,可在最新的Firefox,Microsoft Edge和Chrome浏览器中使用。当然,Internet Explorer中有太多JavaScript错误,不必担心将其包含在浏览器兼容性中。
David Spector '18

3

你写了:

var divNode = document.createElement("div");
divNode.innerHTML = "<br><style>h1 { background: red; }</style>";
document.body.appendChild(divNode);

为什么不呢?

var styleNode = document.createElement("style");
document.head.appendChild(styleNode);

因此,您可以轻松将CSS规则附加到HTML代码:

styleNode.innerHTML = "h1 { background: red; }\n";
styleNode.innerHTML += "h2 { background: green; }\n";

...或直接到DOM:

styleNode.sheet.insertRule("h1 { background: red; }");
styleNode.sheet.insertRule("h2 { background: green; }");

我希望这可以在除旧版浏览器之外的所有地方使用。

绝对可以在2019年在Chrome 中使用。


3

document.head.innerHTML += `
  <style>
    h1 {
      color: red; 
    }
    p {
      color: blue;
    }
  </style>`
<h1>I'm red!</h1>
<p>I'm blue!</p>

到目前为止,最直接的解决方案。您所要做的就是style在反引号之间键入与通常声明标签相同的方式


1
嗨,欢迎来到该网站。尽管此代码可以解决给定的问题,但您还应说明其工作方式和原因。
Radiodef

1

如果您面临的问题是在页面中注入CSS字符串,那么使用<link>元素比使用CSS 元素更容易做到这一点。<style>元素。

以下将p { color: green; }规则添加到页面。

<link rel="stylesheet" type="text/css" href="data:text/css;charset=UTF-8,p%20%7B%20color%3A%20green%3B%20%7D" />

您只需在URL中对CSS字符串进行编码并将其添加为HREF属性,就可以在JavaScript中创建它。比所有<style>元素的古怪或直接访问样式表简单得多。

let linkElement: HTMLLinkElement = this.document.createElement('link');
linkElement.setAttribute('rel', 'stylesheet');
linkElement.setAttribute('type', 'text/css');
linkElement.setAttribute('href', 'data:text/css;charset=UTF-8,' + encodeURIComponent(myStringOfstyles));

这将在IE 5.5以上版本中运行


在某些情况下,将样式块动态注入到头部不会更新样式。虽然有效!
prograhammer

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.