如何创建<风格>标签与Javascript?

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

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

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

这适用于Firefox, Opera和Internet Explorer,但不适用于谷歌Chrome。而且,对于IE来说,<br>在前面有点难看。

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

  1. 是更好的

  2. 工作与Chrome?

或者

  1. 这是我应该避免的不规范的事情

  2. 三个可用的浏览器都很棒,谁会用Chrome呢?

432980 次浏览

我假设你想要插入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级浏览器

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

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

尝试将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));
}

下面是一个脚本,它将ie风格的createStyleSheet()addRule()方法添加到没有它们的浏览器中:

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;');

下面是动态添加类的一个变体

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);
}
}
}

一切都好,除了styleNode。要在IE6中使用javascipt创建的节点工作,您需要在设置cssText之前将节点附加到文档中;

进一步信息@ http://msdn.microsoft.com/en-us/library/ms533698%28VS.85%29.aspx

通常情况下,需要重写现有的规则,因此向HEAD添加新样式并不适用于所有情况。

我想出了这个简单的函数,它总结了所有< em >无效< / em >“追加到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

这个对象变量将把style标签附加到带有type属性的head标签上,其中有一个简单的转换规则,匹配每个id/class/元素。你可以随意修改内容属性并注入你需要的任意数量的规则。只要确保内容内的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();

<style>标签应该放在<head>元素中,每个添加的标签都应该添加到<head>标签的底部。

使用insertAdjacentHTML向文档头标记中注入样式标签:

本机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>

如果你面临的问题是将一串CSS注入到页面中,使用<link>元素比<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" />

你可以在JavaScript中通过URL编码你的CSS字符串并添加HREF属性来创建它。比<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以上工作

当你像这样调用appendStyle函数时,这个函数将注入css appendStyle('css you want to inject') < / p > 这是通过在文档头部注入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>

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

到目前为止最直接的解决方案。你所要做的就是像通常声明style标签一样,在反勾号之间输入

你写的:

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; }");

我希望这在任何地方都能工作,除了老式浏览器。

绝对工作在Chrome 2019年。

据我所知,有4种方法。

var style= document.createElement("style");
(document.head || document.documentElement).appendChild(style);
var rule=':visited {    color: rgb(233, 106, 106) !important;}';


//no 1
style.innerHTML = rule;
//no 2
style.appendChild(document.createTextNode(rule));


//no 3 limited with one group
style.sheet.insertRule(rule);
//no 4 limited too
document.styleSheets[0].insertRule('strong { color: red; }');


//addon
style.sheet.cssRules //list all style
stylesheet.deleteRule(0)  //delete first rule


任何正在寻找Typescript版本的人,

const addStyles = (styles) => {
let styleNode : HTMLStyleElement = document.createElement('style');
styleNode.type = 'text/css';
if (styleNode.style)
styleNode.style.cssText = styles;
else
styleNode.appendChild(document.createTextNode(styles));
        

/* Append style to the head element */
document.head.appendChild(styleNode);
}

此外,在react/vue/angular中,如果需要直接注入CSS,可以使用posstcss-js将CSS转换为JSS,并使用CSS-in-JSS直接注入一个新的样式表。欲了解更多信息,请关注这个文档

更新

你可以根据@Brandon McConnell的评论使用document.head

最琐碎的答案:

function addStyle (styleText) {
const styleNode = document.createElement('style');
styleNode.type = 'text/css';
styleNode.textContent = styleText;
document.documentElement.appendChild(styleNode);
return styleNode;
}
const style = document.createElement("style")
style.textContent = "h1 { background-color: red; }"
document.head.appendChild(style)

现代&简单的方法

上面的代码是它的要点;如果你想知道原因,请继续阅读。

为什么又是另一个答案?公认的答案是老旧的,包括Internet Explorer等过时浏览器的冗余代码。其他答案是不必要的复杂或使用像.innerHTML这样的属性,允许跨站脚本攻击。

不需要type属性

大多数回答者设置type属性是这样的:除非您需要支持旧的浏览器,否则不需要设置此属性。

根据样式:样式信息元素- HTML | MDNtype属性是可选的,默认为text/css:

type

此属性将样式语言定义为MIME类型(不应指定字符集)。此属性是可选的,如果没有指定,默认为text/css;空字符串或text/css以外的值不会被使用。请注意:在现代web文档中包含这个属性的理由非常少。

添加CSS

要添加CSS,请使用.textContent,因为它比其他方法更安全、更快。与.innerHTML相反,它不解析HTML,因此可以防止跨站脚本攻击

另一个类似的属性.innerText,类似于.textContent,但它考虑了CSS样式,只表示“渲染”。文本内容。因为我们对“渲染”的内容不感兴趣,所以我们更喜欢.textContent

设置.textContent做什么?

设置.textContent属性将删除所有节点(元素)的子节点,并将它们替换为给定的字符串值。

在哪里放置元素?

style元素应该包含在header中:“<style>元素必须包含在文档. ...的<head>中”。(& lt; style>... | MDN)

要获得头部,请使用document.head,因为它已经所有主流浏览器均支持很长时间了,因此不需要其他回退。