Як створити тег <style> за допомогою Javascript?


336

Я шукаю спосіб вставити <style>тег на сторінку HTML із JavaScript.

Найкращий спосіб, який я знайшов поки що:

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?

Відповіді:


663

Спробуйте додати 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
FYI, document.headпідтримується у всіх основних браузерах.
Роб Ш

30
@RobW - Не підтримується в IE8 та нижче. Він підтримується в сучасних браузерах, але не у всіх основних.
Тім

5
чому б не просто використовувати document.querySelector("head")? Це подія, яку підтримує IE8 від джерела
allenhwkim

8
@allenhwkim: відповідь передує введенню querySelector(); Сьогодні я, мабуть, пішов би з document.head, доступний з IE9
Крістоф

2
Мені довелося додати елемент стилю до голови перед тим, як отримати доступ style.styleSheet.cssText. До того, як це було додано, style.styleSheetбуло недійсним.
Буде Хоукер

38

Ось сценарій, який додає стиль 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;');

Це мені дуже допомогло при спробі завантажити зовнішній файл CSS у дивному контексті CMS. У мене виникли проблеми з частиною addRule / removeRule, тому я просто усунув їх, і все працює добре.
Kirkman14

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!
Крістоф

Додавання текстового вузла не працює в IE. Але введення елемента стилю в голову змушує моє рішення працювати в Chrome! :-)

1
для IE, використовуйтеstyleNode.styleSheet.cssText = ...
Крістоф

7
(Дуже пізній коментар) "Все залежить від вашої аудиторії. Якщо ніхто з вашої аудиторії не користується Chrome, то не потійте його" Це ставлення - це те, що призводить до того, що люди заблоковані в IE6 роками після того, як IE7 і навіть IE8 є доступними . "Але веб-додаток, який я маю використовувати, працює лише в IE6"
Stephen P

1
Так, ти маєш рацію, і я не обов'язково виступаю за те, щоб це робити (отже, і ціле: "якщо ти хочеш досягти якомога більшої аудиторії, то найкраще підтримати всі основні браузери A класу"), але знаючи аудиторія для вашої платформи важлива.
Том

31

<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, якщо ви не контролюєте це!
Нескінченний

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?
Крістоф

4
що стосується linkелемента до питання? ОП попросили styleелемента. Ця відповідь не має нічого спільного з питанням
vsync

2
@vsync style- це додавання вбудованих стилів, linkє правильним для джерел таблиць стилів, і це має перевагу уникнути проблем із перехресними веб-переглядачами.
травень

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

Демонстрація: codepen , jsfiddle


Ідеально працював в останніх Firefox, Chrome і в ie8 (або, принаймні, так, як я його набрав). Я дійсно не знаю, чому це не має більше балів.
Гаррі Пеконен

У цьому немає більше балів, оскільки це не вірно, ні добре вводити <style>тег за межами <head>тегу. Тег стилів не повинен з’являтися ніде більше, крім <head>тегу. Це широко прийнятий стандарт html. Є атрибут стилю для вбудованого стилю, а атрибут стилю може бути застосований до будь-якого тегу в <body>тезі, включаючи <body>тег його самостійно.
Моторошний

Цей код для мене не працював. Я створив якийсь набагато коротший код, який працює в трьох браузерах, і я опублікую тут свою відповідь.
Девід Спектор

Я не міг зрозуміти, чому Chrome не оновлює мої стилі, коли я динамічно додав блок стилів до голови. Я спробував це і магічно оновив. Мені потрібно дослідити, в чому насправді різниця тут у цьому коді, який запускає браузер для повторного відображення css. Але, велике спасибі!
prograhammer

5

Ця змінна об’єкт додасть тег стилю до тегу 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();

1
Мені це рішення сподобалось, тому я використовував його сам, щоб змінити розміри кнопок на мобільних пристроях, але неправильно, що властивість вмісту має бути в одному рядку: просто об'єднайте кілька рядків (через кілька рядків) з оператором +.
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, щоб переживати про включення його у сумісність браузера.
Девід Спектор

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

Я очікую, що це буде працювати скрізь, крім архаїчних браузерів.

Однозначно працює в Chrome у 2019 році.


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>елементом простіше, ніж<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 вище


Динамічне введення блоку стилів у голову в деяких випадках не оновлювало стиль. Це працює, хоча!
програмамер

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.