วิธีสร้างแท็ก <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องค์ประกอบไปมากกว่าheadbody

นี่คือการทดสอบใน 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ได้รับการสนับสนุนในเบราว์เซอร์หลักทั้งหมด
Rob W

30
@RobW - ไม่รองรับใน IE8 และด้านล่าง มันรองรับเบราว์เซอร์สมัยใหม่ แต่ไม่ใช่เบราว์เซอร์หลักทั้งหมด
ทิม

5
ทำไมไม่เพียงแค่ใช้document.querySelector("head")? เป็นอีเวนต์ที่สนับสนุนโดย IE8 โดยซอร์ส
allenhwkim

8
@ allenhwkim: คำตอบก่อนวันเปิดตัวของquerySelector(); วันนี้ฉันอาจจะไปด้วยdocument.headใช้ได้ตั้งแต่ IE9
Christoph

2
ฉันต้องผนวกองค์ประกอบสไตล์ไว้ที่ส่วนหัวก่อนเข้าstyle.styleSheet.cssTextใช้ ก่อนที่มันจะถูกผนวกเข้าstyle.styleSheetเป็นโมฆะ
Will Hawker จะ

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

การต่อท้ายโหนดข้อความไม่ทำงานใน IE แต่การวางองค์ประกอบสไตล์ไว้ในหัวทำให้โซลูชันของฉันทำงานใน Chrome ได้! :-)

1
สำหรับ IE ใช้styleNode.styleSheet.cssText = ...
Christoph

7
(ความคิดเห็นที่ล่าช้ามาก) "ทุกอย่างขึ้นอยู่กับผู้ชมของคุณหากไม่มีใครในกลุ่มผู้ชมของคุณใช้ Chrome ก็อย่าเหงื่อออกเลย" ทัศนคตินี้เป็นสิ่งที่นำไปสู่คนที่ถูกล็อคเข้าสู่ IE6 เป็นเวลาหลายปีหลังจาก IE7 . "แต่แอปพลิเคชันบนเว็บที่ฉันต้องใช้งานได้เฉพาะใน IE6"
Stephen P

1
ใช่คุณพูดถูกและฉันก็ไม่จำเป็นต้องสนับสนุนให้ทำเช่นนั้น (ดังนั้นทั้งหมด: "หากคุณกำลังมองหาผู้ชมที่ใหญ่ที่สุดเท่าที่จะเป็นไปได้มันก็เป็นการดีที่สุดที่จะสนับสนุนเบราว์เซอร์เกรด A ทั้งหมด") ผู้ชมสำหรับแพลตฟอร์มของคุณเป็นสิ่งสำคัญ
Tom

31

<style>แท็กควรอยู่ใน<head>องค์ประกอบและแต่ละแท็กที่เพิ่มเข้ามาควรถูกเพิ่มเข้าไปที่ด้านล่างของ<head>แท็ก

ใช้insertAdighborHTMLเพื่อฉีดแท็กสไตล์ลงในแท็กส่วนหัวของเอกสาร:

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อะไร
Christoph

4
สิ่งที่ไม่linkองค์ประกอบมีจะทำอย่างไรกับคำถาม? OP ขอstyleองค์ประกอบ คำตอบนี้ไม่เกี่ยวข้องกับคำถาม
vsync

2
@vsync ใช้styleสำหรับเพิ่มรูปแบบอินไลน์linkถูกต้องสำหรับแหล่งที่มาของสไตล์ชีทและนี่มีข้อดีของการหลีกเลี่ยงปัญหาข้ามเบราว์เซอร์
majick

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


ทำงานได้อย่างสมบูรณ์แบบใน Firefox, Chrome และล่าสุดเช่น 8 (หรืออย่างน้อยที่สุดวิธีที่ฉันพิมพ์) ฉันไม่รู้จริงๆว่าเพราะเหตุใดจึงไม่มีคะแนนเพิ่มเติม
Harry Pehkonen

สิ่งนี้ไม่มีคะแนนอีกต่อไปเพราะมันไม่ถูกต้องไม่ดีสำหรับการฉีด<style>แท็กนอก<head>แท็ก แท็กสไตล์ควรปรากฏที่อื่น แต่ภายใน<head>แท็ก นั่นคือมาตรฐาน html ที่นำมาใช้อย่างกว้างขวาง มีแอตทริบิวต์ลักษณะสำหรับการกำหนดสไตล์แบบอินไลน์และสามารถใช้แอตทริบิวต์แท็กกับแท็กใดก็ได้ภายใน<body>แท็กรวมถึง<body>แท็กด้วยตนเอง
เหมือนผี

รหัสนี้ใช้ไม่ได้สำหรับฉัน ฉันสร้างโค้ดที่สั้นกว่าซึ่งใช้งานได้ในสามเบราว์เซอร์และจะโพสต์คำตอบของฉันที่นี่
David Spector

ฉันไม่สามารถเข้าใจได้ว่าทำไม Chrome จึงไม่อัปเดตสไตล์ของฉันเมื่อฉันเพิ่มสไตล์บล็อกในส่วนหัวแบบไดนามิก ฉันลองสิ่งนี้และอัปเดตอย่างน่าอัศจรรย์ ฉันต้องตรวจสอบสิ่งที่แตกต่างจริง ๆ ในรหัสนี้ที่เรียกเบราว์เซอร์เพื่อแสดง css อีกครั้ง แต่ขอบคุณมาก!
prograhammer

5

ตัวแปรออบเจกต์นี้จะผนวกแท็กสไตล์เข้ากับแท็กส่วนหัวด้วยแอตทริบิวต์ type และกฎการเปลี่ยนแปลงอย่างง่ายหนึ่งกฎภายในซึ่งตรงกับ id / คลาส / อิลิเมนต์เดียวทุกตัว อย่าลังเลที่จะปรับเปลี่ยนคุณสมบัติเนื้อหาและเพิ่มกฎให้มากที่สุดเท่าที่คุณต้องการ เพียงตรวจสอบให้แน่ใจว่ากฎ 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 ไชโย
Spooky

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

ทั้งหมดดี แต่สำหรับ styleNode.cssText เพื่อทำงานใน IE6 กับโหนดที่สร้างขึ้นโดย javascipt คุณต้องผนวกโหนดเข้ากับเอกสารก่อนที่คุณจะตั้งค่า cssText

ข้อมูลเพิ่มเติม @ http://msdn.microsoft.com/en-us/library/ms533698%28VS.85%29.aspx


4

ฟังก์ชั่นนี้จะทำการฉีด css ทุกครั้งที่คุณเรียกใช้ฟังก์ชันappendStyleดังนี้:
appendStyle('css you want to inject')

สิ่งนี้ทำงานโดยการฉีดstyleโหนดเข้าไปในส่วนหัวของเอกสาร นี่เป็นเทคนิคที่คล้ายกับสิ่งที่ใช้ทั่วไปในการโหลด JavaScript ของ lazy มันทำงานได้อย่างต่อเนื่องในเบราว์เซอร์ที่ทันสมัยที่สุด

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 ล่าสุด แน่นอนว่ามีข้อผิดพลาดของ JavaScript มากเกินไปใน Internet Explorer ที่ต้องกังวลเกี่ยวกับการรวมไว้ในความเข้ากันได้ของเบราว์เซอร์อีกต่อไป
David Spector

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 ขึ้นไป


การฉีดบล็อกสไตล์ลงในหัวแบบไดนามิกไม่ได้เป็นการปรับปรุงสไตล์ในบางกรณี มันใช้งานได้ดี!
prograhammer

-1
this link may helpful to you: 

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


โปรดอย่าใช้บล็อคข้อความ / รหัสที่จัดรูปแบบไว้ล่วงหน้าสำหรับย่อหน้าสั้น ๆ การลิงก์คำตอบด้วยวิธีนี้ก็ไร้ประโยชน์เช่นกัน โปรดสรุปเว็บไซต์ก่อน
FryingggPannn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.