Как создать тег <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));
}
Christoph
источник
19
К вашему сведению, document.headподдерживается во всех основных браузерах.
Роб W
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;');
Christoph
источник
Это было очень полезно для меня при попытке загрузить внешний файл 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 = ...
Christoph
7
(Очень поздний комментарий) «Все зависит от вашей аудитории. Если никто из вашей аудитории не использует Chrome, то не переживайте» Это отношение приводит к тому, что люди блокируются в IE6 в течение многих лет после выхода IE7 и даже IE8 , «Но веб-приложение, которое я должен использовать, работает только в IE6»
Стивен П
1
Да, вы правы, и я не обязательно выступаю за это тоже (отсюда и в целом: «если вы хотите охватить максимально возможную аудиторию, тогда лучше поддерживать все основные браузеры класса А»), но зная аудитория для вашей платформы важна.
Том
31

<style>теги должны быть местами внутри <head>элемента, и каждый добавленный тег должен быть добавлен в конец <head>тега.

Использование insertAdjacentHTML , чтобы ввести тег стиля в документ головы тег :

Родной ДОМ:

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>

VSync
источник
Согласитесь, это лучше и проще, но следите за плохо введенным 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 работает не во всех случаях.

Я придумал эту простую функцию, которая суммирует все недопустимые подходы «добавить к телу» и просто удобнее использовать и отлаживать (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

Garlaro
источник
Прекрасно работал в последних версиях Firefox, Chrome и ie8 (или, по крайней мере, так, как я его набрал). Я действительно не знаю, почему это не имеет больше очков.
Гарри Пехконен
Это больше не имеет смысла, потому что это недопустимо, и нет ничего хорошего в том, чтобы вставлять <style>тег вне <head>тега. Тег стиля не должен появляться нигде, кроме <head>тега. Это широко принятый стандарт HTML. Существует атрибут style для встроенного стиля, и атрибут style можно применять к любому тегу внутри <body>тега, включая <body>тег самостоятельно.
жуткий
Этот код не работал для меня. Я создал гораздо более короткий код, который работает в трех браузерах, и опубликую свой ответ здесь.
Дэвид Спектор
Я не мог понять, почему Chrome не обновлял мои стили, когда я динамически добавил блок стилей в голову. Я попробовал это и волшебным образом обновляет. Мне нужно выяснить, в чем на самом деле разница здесь в этом коде, который запускает браузер для повторного рендеринга CSS. Но большое спасибо!
программер
5

Эта переменная объекта добавит тег стиля к тегу head с атрибутом type и одним простым правилом перехода внутри, который соответствует каждому отдельному 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
Мне понравилось это решение, поэтому я сам использовал его для изменения размеров кнопок на мобильных устройствах, но неправильно, чтобы свойство содержимого было в одной строке: просто объедините несколько строк (по нескольким строкам) с оператором +.
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 году.

7vujy0f0hy
источник
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 и выше

moefinley
источник
Динамическое введение блока стиля в голову не обновляло стиль в некоторых случаях. Это работает, хотя!
программер
-1
this link may helpful to you: 

http://jonraasch.com/blog/javascript-style-node

Винод Пурма
источник
Пожалуйста, не используйте предварительно отформатированные блоки текста / кода для короткого абзаца. Ссылка для ответа таким способом также бесполезна. Пожалуйста, подведите итог сайта в первую очередь.
FriedggPannn