Làm cách nào để tạo thẻ <style> bằng Javascript?


336

Tôi đang tìm cách chèn <style>thẻ vào trang HTML bằng JavaScript.

Cách tốt nhất tôi tìm thấy cho đến nay:

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

Điều này hoạt động trong Firefox, Opera và Internet Explorer nhưng không có trong Google Chrome. Ngoài ra, nó hơi xấu với <br>phía trước cho IE.

Có ai biết cách tạo ra một <style>thẻ

  1. Đẹp hơn

  2. Hoạt động với Chrome?

Hoặc có thể

  1. Đây là một điều không chuẩn tôi nên tránh

  2. Ba trình duyệt hoạt động rất tuyệt và ai sử dụng Chrome?

Câu trả lời:


663

Hãy thử thêm stylephần tử vào headchứ không phải body.

Điều này đã được thử nghiệm trong IE (7-9), Firefox, Opera và 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
FYI, document.headđược hỗ trợ trong tất cả các trình duyệt chính.
Rob W

30
@RobW - Nó không được hỗ trợ trong IE8 trở xuống. Nó được hỗ trợ trong các trình duyệt Hiện đại, nhưng không phải tất cả các trình duyệt chính.
Tim

5
Tại sao không chỉ sử dụng document.querySelector("head")? Sự kiện này được IE8 hỗ trợ theo nguồn
allenhwkim

8
@allenhwkim: câu trả lời trước khi giới thiệu querySelector(); hôm nay, tôi có thể đi cùng document.head, có sẵn kể từ IE9
Christoph

2
Tôi đã phải nối phần tử kiểu vào đầu trước khi truy cập style.styleSheet.cssText. Trước khi nó được nối style.styleSheetlà null.
Will Hawker

38

Đây là tập lệnh bổ sung các kiểu createStyleSheet()addRule()phương thức IE cho các trình duyệt không có chúng:

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

Bạn có thể thêm các tập tin bên ngoài thông qua

document.createStyleSheet('foo.css');

và tự động tạo quy tắc thông qua

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

Điều này rất hữu ích với tôi khi cố gắng tải một tệp CSS bên ngoài trong ngữ cảnh CMS lạ. Tôi đã gặp một số rắc rối với phần addRule / removeRule, vì vậy tôi chỉ cần loại bỏ chúng và mọi thứ đều hoạt động tốt.
Kirkman14

33

Tôi giả sử rằng bạn muốn chèn stylethẻ so với linkthẻ (tham chiếu CSS bên ngoài), vì vậy đó là ví dụ sau đây:

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

Ngoài ra, tôi nhận thấy trong câu hỏi của bạn rằng bạn đang sử dụng innerHTML . Đây thực sự là một cách không chuẩn để chèn dữ liệu vào một trang. Cách thực hành tốt nhất là tạo một nút văn bản và nối nó vào một nút phần tử khác.

Đối với câu hỏi cuối cùng của bạn, bạn sẽ nghe một số người nói rằng công việc của bạn sẽ hoạt động trên tất cả các trình duyệt. Tất cả phụ thuộc vào khán giả của bạn. Nếu không có ai trong đối tượng của bạn sử dụng Chrome, thì đừng đổ mồ hôi; tuy nhiên, nếu bạn đang muốn tiếp cận đối tượng lớn nhất có thể, thì tốt nhất là hỗ trợ tất cả các trình duyệt cấp A chính


1
Điều này về cơ bản giống như giải pháp của tôi; không ai trong số họ làm việc trong IE!
Christoph

Nối một nút văn bản không hoạt động trong IE. Nhưng việc đặt yếu tố phong cách vào đầu giúp giải pháp của tôi hoạt động trong Chrome! :-)

1
đối với IE, hãy sử dụngstyleNode.styleSheet.cssText = ...
Christoph

7
(Nhận xét rất muộn) "Tất cả phụ thuộc vào đối tượng của bạn. Nếu không có ai trong khán giả của bạn sử dụng Chrome, thì đừng đổ mồ hôi" Thái độ này là nguyên nhân dẫn đến việc mọi người bị khóa vào IE6 trong nhiều năm sau khi IE7 và thậm chí IE8 có sẵn . "Nhưng ứng dụng web tôi phải sử dụng chỉ hoạt động trong IE6"
Stephen P

1
Đúng, bạn đúng và tôi cũng không nhất thiết phải ủng hộ việc đó (vì thế toàn bộ: "nếu bạn đang muốn tiếp cận đối tượng lớn nhất có thể, thì tốt nhất là hỗ trợ tất cả các trình duyệt cấp A chính") nhưng biết khán giả cho nền tảng của bạn là quan trọng.
Tom

31

<style>các thẻ phải là các vị trí trong thành <head>phần và mỗi thẻ được thêm vào sẽ được thêm vào dưới cùng của <head>thẻ.

Sử dụng insertAdjiềnHTML để thêm thẻ kiểu vào thẻ đầu tài liệu :

DOM gốc:

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
Đây là giải pháp tốt nhất và đơn giản nhất, cảm ơn bạn!
Ryzal Yusoff

Đồng ý, nó tốt nhất và đơn giản nhưng coi chừng css bị tiêm kém nếu bạn không kiểm soát được nó!
Vô tận

24

Một ví dụ hoạt động và tuân thủ tất cả các trình duyệt:

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

7
yếu tố sai: stylekhông có relhoặc hrefthuộc tính - ý bạn là linkgì?
Christoph

4
những gì hiện linkyếu tố đã làm với các câu hỏi? OP yêu cầu styleyếu tố. Câu trả lời này không liên quan gì đến câu hỏi
vsync

2
@vsync stylelà để thêm các kiểu nội tuyến, linklà chính xác cho các nguồn của biểu định kiểu và điều này có lợi thế là tránh các vấn đề về trình duyệt chéo.
Majick

7

Thông thường, cần phải ghi đè các quy tắc hiện có, do đó, việc thêm các kiểu mới vào ĐẦU không hoạt động trong mọi trường hợp.

Tôi đã đưa ra chức năng đơn giản này tóm tắt tất cả các cách tiếp cận "nối vào BODY" không hợp lệ và chỉ thuận tiện hơn khi sử dụng và gỡ lỗi (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);

Bản trình diễn: codepen , jsfiddle


Hoạt động hoàn hảo trong Firefox, Chrome mới nhất trong eg8 (hoặc ít nhất là cách tôi nhập nó). Tôi thực sự không biết tại sao điều này không có nhiều điểm hơn.
Harry Pehkonen

Điều này không có nhiều điểm hơn, bởi vì nó không hợp lệ, cũng không phải là điều tốt để tiêm <style>thẻ bên ngoài <head>thẻ. Thẻ kiểu sẽ không xuất hiện ở nơi nào khác ngoài <head>thẻ. Đó là tiêu chuẩn html được áp dụng rộng rãi. Có thuộc tính style cho kiểu dáng nội tuyến và thuộc tính style có thể được áp dụng cho bất kỳ thẻ nào trong <body>thẻ, bao gồm cả <body>thẻ tự.
Ma quái

Mã này đã không làm việc cho tôi. Tôi đã tạo ra một số mã ngắn hơn nhiều hoạt động trong ba trình duyệt và sẽ đăng câu trả lời của tôi ở đây.
David Spector

Tôi không thể hiểu tại sao Chrome không cập nhật kiểu của mình khi tôi thêm khối kiểu vào đầu một cách linh hoạt. Tôi đã thử điều này và kỳ diệu là nó cập nhật. Tôi cần điều tra xem sự khác biệt thực sự ở đây trong mã này sẽ kích hoạt trình duyệt kết xuất lại css. Nhưng, cảm ơn rất nhiều!
prograhammer

5

Biến đối tượng này sẽ gắn thẻ kiểu vào thẻ head với thuộc tính type và một quy tắc chuyển đổi đơn giản bên trong khớp với mọi id / class / phần tử duy nhất. Vui lòng sửa đổi thuộc tính nội dung và đưa ra nhiều quy tắc bạn cần. Chỉ cần đảm bảo rằng các quy tắc css bên trong nội dung vẫn nằm trong một dòng (hoặc 'thoát' mỗi dòng mới, nếu bạn thích như vậy).

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
Tôi thích giải pháp này, vì vậy tôi đã tự mình sử dụng nó để thay đổi kích thước nút trên thiết bị di động, nhưng không chính xác là thuộc tính nội dung cần phải nằm trên một dòng: Đơn giản là ghép nhiều chuỗi (trên nhiều dòng) với toán tử +.
RufusVS

Thật. Tôi biết và tôi biết điều đó. Nhưng, đôi khi, tôi quá lười để viết như tôi phải làm. : D Chúc mừng.
Ma quái

5

Đây là một biến thể để tự động thêm một lớp

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

Hàm này sẽ tiêm css bất cứ khi nào bạn gọi hàm appendStylenhư thế này:
appendStyle('css you want to inject')

Điều này hoạt động bằng cách tiêm một stylenút vào phần đầu của tài liệu. Đây là một kỹ thuật tương tự như những gì thường được sử dụng để tải JavaScript lười biếng. Nó hoạt động nhất quán trong hầu hết các trình duyệt hiện đại.

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>

Bạn cũng có thể tải các tệp CSS bên ngoài bằng cách sử dụng đoạn mã sau:

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>


Đây là cách tiếp cận mà tôi đã phát triển độc lập. Ngắn gọn và ngọt ngào và hoạt động trong các trình duyệt Firefox, Microsoft Edge và Chrome mới nhất. Tất nhiên, có quá nhiều lỗi JavaScript trong Internet Explorer để lo lắng về việc bao gồm nó trong khả năng tương thích trình duyệt nữa.
David Spector

3

Bạn đã viết:

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

Tại sao không phải điều này?

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

Do đó, bạn có thể dễ dàng nối các quy tắc CSS vào mã HTML:

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

... hoặc trực tiếp đến DOM:

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

Tôi hy vọng nó sẽ hoạt động ở mọi nơi trừ các trình duyệt cổ xưa.

Chắc chắn hoạt động trong Chrome vào năm 2019.


3

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

Cho đến nay các giải pháp đơn giản nhất. Tất cả những gì bạn phải làm là nhập giống như cách bạn thường khai báo stylethẻ, giữa các backticks


1
Xin chào và chào mừng đến với trang web. Mặc dù mã này có thể giải quyết vấn đề nhất định, bạn cũng nên bao gồm một lời giải thích về cách thức và lý do tại sao nó hoạt động.
Radiodef

1

Nếu vấn đề bạn gặp phải là tiêm một chuỗi CSS vào một trang thì việc thực hiện điều này với <link>phần tử sẽ dễ dàng hơn <style>phần tử.

Sau đây thêm p { color: green; }quy tắc cho trang.

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

Bạn có thể tạo điều này bằng JavaScript chỉ bằng cách mã hóa chuỗi CSS của bạn và thêm HREFthuộc tính đó. Đơn giản hơn nhiều so với tất cả các <style>yếu tố của các yếu tố hoặc truy cập trực tiếp vào bảng định kiểu.

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

Điều này sẽ hoạt động trong IE 5.5 trở lên


Việc tiêm khối kiểu động vào đầu không cập nhật kiểu trong một số trường hợp. Điều này làm việc mặc dù!
prograhammer

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.