Javascript ile bir <style> etiketi nasıl oluşturulur?


336

<style>JavaScript ile bir HTML sayfasına bir etiket eklemek için bir yol arıyorum .

Şimdiye kadar bulduğum en iyi yol:

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

Bu Firefox, Opera ve Internet Explorer'da çalışır, ancak Google Chrome'da çalışmaz. Ayrıca <br>IE için ön ile biraz çirkin .

Herkes bir <style>etiket oluşturmak için bir yol biliyor mu

  1. Daha güzel

  2. Chrome ile çalışır?

Ya da belki

  1. Bu kaçınmam gereken standart olmayan bir şey

  2. Üç çalışan tarayıcı harika ve Chrome'u kim zaten kullanıyor?

Yanıtlar:


663

styleÖğeyi headyerine yerine eklemeyi deneyin body.

Bu IE (7-9), Firefox, Opera ve Chrome'da test edildi:

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.headtüm büyük tarayıcılarda desteklenir.
Rob W

30
@RobW - IE8 ve önceki sürümlerde desteklenmez. Modern tarayıcılarda desteklenir, ancak tüm büyük tarayıcılarda desteklenmez.
Tim

5
neden sadece kullanmıyorsun document.querySelector("head")? IE8 tarafından kaynağa
allenhwkim

8
@allenhwkim: cevap querySelector(); bugün, document.headIE9
Christoph

2
Erişmeden önce stil elemanını kafasına eklemem gerekiyordu style.styleSheet.cssText. Eklenmeden style.styleSheetönce boştu.
Hawker

38

IE tarayıcısı olmayan tarayıcılara IE stili createStyleSheet()ve addRule()yöntem ekleyen bir betik :

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

Harici dosyalar ekleyebilirsiniz.

document.createStyleSheet('foo.css');

ve üzerinden dinamik olarak kurallar oluşturun

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

Bu, garip bir CMS bağlamında harici bir CSS dosyası yüklemeye çalışırken bana çok yardımcı oldu. Ben addRule / removeRule kısmı ile bazı sorunla karşılaştım, bu yüzden sadece bu seçti ve her şey iyi çalışıyor.
Kirkman14

33

styleBir linketikete (harici bir CSS'ye atıfta bulunarak) karşı bir etiket eklemek istediğinizi varsayıyorum , bu yüzden aşağıdaki örnekte yapılan şey budur:

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

Ayrıca, kullandığınız sorunun farkına vardım innerHTML. Bu aslında bir sayfaya veri eklemenin standart olmayan bir yoludur. En iyi uygulama, bir metin düğümü oluşturmak ve onu başka bir öğe düğümüne eklemektir.

Son sorunuzla ilgili olarak, bazı kişilerin çalışmanızın tüm tarayıcılarda çalışması gerektiğini söylediğini duyacaksınız. Her şey kitlenize bağlıdır. Kitlenizdeki hiç kimse Chrome'u kullanmıyorsa, terlemeyin; ancak, mümkün olan en büyük kitleye ulaşmak istiyorsanız, tüm büyük A sınıfı tarayıcıları desteklemek en iyisidir


1
Bu benim çözümümle aynı; ikisi de IE'de çalışmıyor!
Christoph

Metin düğümü eklemek IE'de çalışmaz. Ancak stil öğesini kafaya koymak çözümümü Chrome'da çalıştırıyor! :-)

1
IE için, kullanınstyleNode.styleSheet.cssText = ...
Christoph

7
(Çok geç yorum) "Her şey kitlenize bağlıdır. Kitlenizden hiç kimse Chrome kullanmıyorsa, terlemeyin" Bu tutum, insanların IE7 ve hatta IE8'den sonraki yıllar boyunca IE6'ya kilitlenmesine yol açan şeydir. . "Ama kullanmak zorunda web uygulaması sadece IE6 çalışır"
Stephen P

1
Evet, haklısın ve ben de bunu yapmayı savunmuyorum (dolayısıyla bütün: "mümkün olan en büyük kitleye ulaşmak istiyorsanız, tüm büyük A sınıfı tarayıcıları desteklemek en iyisidir"). platformunuz için kitle önemlidir.
Tom

31

<style>etiketler <head>öğenin içindeki yerlerden olmalı ve eklenen her etiket etiketin altına eklenmelidir <head>.

Belge başı etiketine bir stil etiketi enjekte etmek için insertAdjacentHTML kullanma :

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


Katılıyorum, en iyi ve basit ama üzerinde kontrol yoksa kötü enjekte css dikkat edin!
Sonsuz

24

Tüm tarayıcılarda çalışan ve bunlarla uyumlu bir örnek:

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

7
yanlış eleman: styleyok relveya hrefnitelik var - bunu mu demek istediniz link?
Christoph

4
linkelementin soru ile ne ilgisi var? OP istedistyle eleman . Bu cevabın şu soru ile ilgisi yoktur
vsync

2
@vsync stylesatır içi stiller eklemek içindir,link stil sayfası kaynakları için doğrudur ve bunun tarayıcılar arası sorunları önleme avantajı vardır.
majick

7

Çoğu zaman mevcut kuralları geçersiz kılma ihtiyacı vardır, bu nedenle HEAD'e yeni stiller eklemek her durumda işe yaramaz.

Tüm geçerli olmayan "VÜCUT eklemek" yaklaşımları özetleyen ve kullanımı ve hata ayıklama (IE8 +) daha uygun olan bu basit işlev ile geldi .

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

Gösteri: codepen , jsfiddle


En yeni Firefox, Chrome ve ie8'de (veya en azından yazdığım şekilde) mükemmel çalıştı . Bunun neden daha fazla puanı olmadığını gerçekten bilmiyorum.
Harry Pehkonen

Bunun daha fazla puanı yok, çünkü geçerli değil, <style>etiketi dışına enjekte etmek de iyi bir şey değil <head>. Stil etiketi başka hiçbir yerde değil <head>etiket içinde görünmelidir . Bu yaygın olarak kabul edilen html standardıdır. İçinde herhangi bir etikete uygulanabilir satır içi stil ve stil özelliği için stil niteliği yoktur <body>dahil olmak üzere etiketle <body>etiketi o kendini.
Ürkütücü

Bu kod benim için çalışmadı. Üç tarayıcıda çalışan ve cevabımı buraya gönderecek çok daha kısa bir kod hazırladım.
David Spector

Kafanıza dinamik olarak bir stil bloğu eklediğimde Chrome'un neden stilleri güncellemediğini anlayamadım. Bunu denedim ve sihirli bir şekilde güncelledi. Aslında css yeniden oluşturmak için tarayıcı tetikler bu kod burada fark ne olduğunu araştırmak gerekiyor. Ama, çok teşekkürler!
prograhammer

5

Bu nesne değişkeni, tip özniteliği ve içindeki her bir id / sınıf / öğeyle eşleşen tek bir basit geçiş kuralı ile baş etiketine stil etiketi ekler. İçerik özelliğini değiştirmekten çekinmeyin ve istediğiniz kadar kural enjekte edin. İçeriğin içindeki css kurallarının bir satırda kaldığından emin olun (veya isterseniz her yeni satırdan 'kaçın').

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
Bu çözümü beğendim, bu yüzden mobil cihazlarda düğme boyutlarını değiştirmek için kendim kullandım, ancak content özelliğinin bir satırda olması gerektiği yanlış: + operatörü ile birden fazla dizeyi (birden çok satır üzerinden) birleştirin.
RufusVS

Doğru. Bunu biliyorum ve biliyordum. Ancak, bazen, olması gerektiği gibi yazmak için çok tembelim. : D Şerefe.
Ürkütücü

5

İşte dinamik olarak bir sınıf eklemek için bir değişken

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

Bu işlev, işlevi şöyle çağırdığınızda css enjekte eder appendStyle:
appendStyle('css you want to inject')

Bu style, belgenin başına bir düğüm enjekte ederek çalışır . Bu, JavaScript'i tembel yüklemek için yaygın olarak kullanılana benzer bir tekniktir. Çoğu modern tarayıcıda tutarlı bir şekilde çalışır.

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>

Aşağıdaki snippet'i kullanarak harici CSS dosyalarını da tembel olarak yükleyebilirsiniz:

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>


Kabaca bağımsız olarak geliştirdiğim yaklaşım budur. Kısa ve tatlı ve en yeni Firefox, Microsoft Edge ve Chrome tarayıcılarda çalışır. Elbette, Internet Explorer'da artık tarayıcı uyumluluğuna dahil edileceği konusunda endişelenecek çok fazla JavaScript hatası var.
David Spector

3

Sen yazdın:

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

Neden olmasın?

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

Bundan böyle CSS kurallarını HTML koduna kolayca ekleyebilirsiniz:

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

... veya doğrudan DOM'a:

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

Bunun arkaik tarayıcılar dışında her yerde çalışmasını bekliyorum.

Kesinlikle 2019 yılında Chrome'da çalışıyor .


3

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

Şimdiye kadar en basit çözüm. Tek yapmanız gereken, normal styleişaretler arasında normalde nasıl etiket beyan ettiğinizle aynı yazmaktır


1
Merhaba ve siteye hoş geldiniz. Bu kod verilen sorunu çözse de, nasıl ve neden çalıştığına dair bir açıklama da eklemelisiniz.
Radiodef

1

Karşılaştığınız sorun bir sayfaya bir CSS dizesi enjekte ediyorsa bunu <link>öğeyle yapmak daha kolay<style> .

Aşağıda p { color: green; }sayfaya kural eklenmiştir .

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

Bunu JavaScript'te, yalnızca CSS dizenizi kodlayıp URL'ye HREFnitelik ekleyerek oluşturabilirsiniz . <style>Elemanların tüm tuhaflıklarından veya doğrudan stil sayfalarına erişmekten çok daha basit .

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

Bu, IE 5.5'te yukarı doğru çalışacaktır


Stil bloğunu dinamik olarak kafaya enjekte etmek, bazı durumlarda stili güncellemedi. Bu işe yarıyor!
prograhammer

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.