Javascript insertRule, removeRule

Style insertRule removeRule – übersichtlicher als lange style-Strings

Das Ändern von style-Attributen und CSS-Klassen gehört zu den Hauptaufgaben von Javascript. Anstelle von wiederholten Queries und Änderungen des style-Attributs oder von CSS-Klassen ist das Einfügen, Entfernen oder Deaktivieren direkt im Stylesheet effizienter.

insertRule und removeRule fügen neue CSS-Stile in ein Stylesheet ein und entfernen sie wieder. Das Verfahren ist übersichtlicher als lange Strings style-Attributen.

document.styleSheets gibt eine aufklappbare Liste der Stylesheets der Seite zurück.

var sheets = document.styleSheets;
▾ StyleSheetList
▸ 0: CSSStyleSheet {ownerRule: null, cssRules: CSSRuleList, rules: CSSRuleList, insertRule: function, deleteRule: function, …}
▸ 1: CSSStyleSheet {ownerRule: null, cssRules: CSSRuleList, rules: CSSRuleList, insertRule: function, deleteRule: function, …}
▸ 2: CSSStyleSheet {ownerRule: null, cssRules: CSSRuleList, rules: CSSRuleList, insertRule: function, deleteRule: function, …}

Eine Array-Notation gibt Zugriff auf die Elemente der Liste.

var sheet = document.styleSheets[0];
▾ CSSStyleSheet
▾ cssRules: CSSRuleList
▸ 0: CSSFontFaceRule {style: CSSStyleDeclaration, type: 5, cssText: "@font-face { font-family: Roboto; font-style: norm…in/roboto-v18-latin-regular.woff) format(woff); }", parentStyleSheet: CSSStyleSheet, parentRule: null, …}
▸ 1: CSSFontFaceRule {style: CSSStyleDeclaration, type: 5, cssText: "@font-face { font-family: Roboto; font-style: norm…-latin/roboto-v18-latin-300.woff) format(woff); }", parentStyleSheet: CSSStyleSheet, parentRule: null, …}
▸ 2: CSSStyleRule {selectorText: "body", style: CSSStyleDeclaration, type: 1, cssText: "body { padding: 0px; margin: 0px; line-height: 1.4…t-family: Roboto, sans-serif; font-weight: 300; }", parentStyleSheet: CSSStyleSheet, …}

Stylesheet mit Javascript erzeugen

Statt alle Blöcke immer wieder mit setAttribute() und removeAttribute() zu ändern, initialisiert ein dynamisch erzeugtes StyleSheet alle Blöcke.

Herzlich süß
DSC07390-300
Caramels gummies toffee sesame snaps chupa chups candy jelly beans.
Occelli
DSC05777-300
Cake dessert candy canes marzipan chocolate cake cupcake. Lemon drops toffee jelly tootsie roll jelly carrot cake cheesecake.
Tartufo
DSC09079-300
Tart lollipop liquorice sugar plum. Candy canes caramels lemon drops icing wafer chocolate cake lemon drops chocolate. Candy canes caramels lemon drops icing wafer chocolate cake lemon drops chocolate.
Süßer Morgen
DSC07230-300
Pastry caramels lemon drops gummies.

Und hier soll alles fest sein.

Zuerst: Das höchste Accordion-Element heraussuchen, damit alle Ebenen des Accordion-Effekts dieselbe Höhe haben:

var tallest = 0;
for (var i=0; i< box.length; i++) {
   var height = box[i].clientHeight;
   tallest = height > tallest ? height : tallest;
}

var style = document.createElement("style");
document.head.appendChild(style);
style.type="text/css";

document.createElement erzeugt <style>-Elemente on the fly, nicht anders als das Erzeugen von Elementen im body des Dokuments.

Die dynamischen Regeln in das frisch erzeugte Stylesheet einfügen:

style.appendChild(document.createTextNode(".jumper {height: " +  tallest + "px}"));

Das neue Stylesheet sitzt am Ende des Head-Elements, als wäre es immer schon da gewesen.

<style>
 .jumper {height: 474px}
</style>

Statt jedem Element des Akkordions ein

insertRule / addRule

Stylesheets haben eine Methode insertRule, die CSS-Regeln auf dieselbe Weise einfügt wie die Notation in der CSS-Datei oder in style-Tags.

Gegenüber CSS im style-Attribut setzt ein dynamisches insertRule auch gleich Breakpoints und verzweigt das CSS im style-Tag mit der @supports-Regel.

// stylesheet.insertRule(rule, index);

style.sheet.insertRule("ul { height: 0; overflow:hidden; transition: height 1s; }", 0 );
style.sheet.insertRule(".toggle { height: " + tallest + "px; overflow:visible; }", 1 );

Das zweite Argument ist der Index, an dem die Regel eingefügt wird. Per Vorgabe werden neue Regeln am Ende des Stylesheets eingefügt, aber der Parameter muss trotzdem immer gesetzt werden. Der Index darf nicht größer sein als die Zahl der Regeln im Style-Element und reagiert ausgesprochen sensibel, wenn der Index außer Kontrolle gerät.

IndexSizeError: DOM Exception 1: Index or size was negative, or greater than the allowed value.

insertRule wurde von IE9 noch nicht unterstützt. In IE9 wirkte noch addRule() (das wiederum von Firefox nicht unterstützt wird und obendrein kein Standard ist). Wer IE9 unbedingt noch versorgt will:

function addCSSRule(sheet, selector, rules, index) {
   if ("insertRule" in sheet) {
      sheet.insertRule(selector + "{" + rules + "}", index);
   } else if ("addRule" in sheet) {
      sheet.addRule(selector, rules, index);
   }
}

addCSSRule (style.sheet, "#nav_menu ul", "height: 0; overflow:hidden; transition: height 1s;", 0);
addCSSRule (style.sheet, ".toggle", "height: " + tallest + "px !IMPORTANT; overflow:visible !IMPORTANT;", 0);

Mit einer äquivalenten Methoden werden CSS-Regeln aus dem Stylesheet entfernt:

stylesheet.removeRule(i) // moderne Browser 
stylesheet.deleteRule(i) // IE9

Statt über alle Elemente zu iterieren, kann die CSS-Klasse toggle direkt aus einem Element mit classList.remove('toggle') entfernt werden, wenn ein neues Element im Accordion aktiviert wird.

for (var i=0; i<h.length; i++) {
   h[i].onclick = function () {
      document.querySelector('.toggle').classList.remove('toggle');
      this.nextElementSibling.classList.add('toggle');
   }
}

Regeln für Media Queries einfügen

Nicht nur die volle Breite der Selektoren, sondern auch Media Queries können in dynamisch erzeugten Stylesheets eingesetzt werden. Das funktioniert mit insertRule:

sheet.insertRule("@media only screen and (max-width:1260px) { .accordion { max-width:480px } }");

styleSheets auflisten

Das styleSheet-Objekt enthält alle externen Stylesheets der Seite – sowohl Styleheets, die mit <style> notiert sind als auch diejenigen, die mit <link rel="stylesheet"> eingebunden sind.

document.styleSheets gibt eine Liste der Stylesheets der Webseite zurück. Die Liste kann nicht geändert werden, aber document.styleSheets kann einzelne Stylesheets deaktivieren.

Der Rückgabewert von document.styleSheets sieht aus wie ein Array, ist aber eine nodeList. Der Zugriff erfolgt über den Index.

var sheets = document.styleSheets;
var len = sheets.length; 
for (var i=0; i<len; i++) {
    console.log(document.styleSheets[i]);
}

sheets[0] ist das erste styleSheet im Dokument, das durch ein link- oder style-Element eingebunden ist. sheets.length ist die Anzahl der styleSheets.

    window.addEventListener ("load", function () { var sheets = document.styleSheets; var len = sheets.length; for (var i=0; ihref = ' + sheets[i].href + ' '; console.log (document.styleSheets[i]); } });

    Die Eigenschaften der styleSheets (type, disabled, title, media, href, ownerDocument, parentStyleSheet) liefern weitere Informationen. Bis auf disabled können alle Eigenschaften nur gelesen werden.

    Der Zugriff auf die geladenen styleSheets kann auch durch die DOM Core-Methoden document.getElementsByTagName('style') und document.getElementsByTagName('link') erfolgen. Dann können die Attribute title, href, media, … durch setAttribte() geändert werden.

    var firstSheet = document.getElementsByTagName('style')[0].sheet;
    var owner = document.styleSheets[0].ownerNode;
    

    stylesheets disabled

    disabled ist ein boole'scher Wert und gibt an, ob ein styleSheet in Kraft ist (disabled = false) oder nicht. Default ist false.

    <link rel="stylesheet" href="dom-stylesheets.css" title="extra" />
    
    var sheets = document.styleSheets;
    var len = sheets.length;
    for (var i=0; i<len; i++) {
       if (sheets[i].title && sheets[i].title == 'extra') {
          sheets[i].disabled = true;
       }
    }
    

    styleSheets identifizieren

    Das styleSheet-Objekt unterstützt nur den Zugriff durch den Index, also über die Position des styleSheets im Dokument. Zur Identifikation kann aber auch die href-Eigenschaft herangezogen werden, wenn das Stylesheet durch ein <link>-Tag in das Dokument eingebunden wurde oder das title-Attribut (sofern title gesetzt ist und die title-Attribute eindeutig sind).

    Ein gleichlautendes title-Attribut erlaubt das Zusammenfassen von zwei oder mehr Style Sheets zu einer Gruppe, die gemeinsam außer Kraft gesetzt oder deaktiviert werden können.

    Weitere Eigenschaften von styleSheets

    ownerNode
    gibt einen Verweis auf den Knoten zurück, der das aktuelle styleSheet enthält. Gibt in regulären HTML-Seiten i.d.R. ein LINK- oder STYLE-Element zurück. In XML-Dokumenten kann dies die linkende ProcessingInstruction sein.
    parentStyleSheet
    Verweis auf das Top-Level-Stylesheet bei Style Sheets, die durch die @page-Regel eingebunden sind. Bei Style Sheets, die durch LINK- oder STYLE eingebunden sind, wird null zurückgegeben.
    media
    Gibt das media-Objekt des styleSheets als Liste zurück. Die Eigenschaft mediaText gibt den Medientyp als String zurück. Default ist screen.
    <style> insertRule removeRule
    function addCSSRule(sheet, selector, rules, index) { if ("insertRule" in sheet) { sheet.insertRule(selector + "{" + rules + "}", index); } else if("addRule" in sheet) { sheet.addRule(selector, rules, index); } } var h = document.querySelectorAll(".accordion h5"); var box = document.querySelectorAll('.accordion .inbox'); var tallest = 0; for (var i=0; i< box.length; i++) { var height = box[i].clientHeight; tallest = height > tallest ? height : tallest; console.log ('height ' + height + ' ' + tallest); } window.onresize = function () { for (var i=0; i< box.length; i++) { var height = box[i].clientHeight; tallest = height > tallest ? height : tallest; console.log ('height ' + height + ' ' + tallest); } } var style = document.createElement('style'); style.type='text/css'; document.querySelector('head').appendChild(style); document.querySelector('.accordion .inbox').classList.add('toggle'); var aheight = document.querySelector('.accordion').clientHeigth; addCSSRule (style.sheet, ".accordion .inbox", "height: 0; overflow:hidden; transition: height 1s;", 0); addCSSRule (style.sheet, ".toggle", "height: " + tallest + "px !IMPORTANT; overflow:visible !IMPORTANT;", 0); addCSSRule (style.sheet, ".accordion", "height: " + aheight + "px !IMPORTANT; overflow:hidden !IMPORTANT;", 0); for (var i=0; i