Javascript insertRule, removeRule

Javascript insertRule removeRule

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.

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

Der Einsatz von CSS-Regeln und die CSS-Syntax sind zudem einfacher, stabiler und weniger fehleranfällig.

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

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

let 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 Blöcke immer wieder mit elem.style oder setAttribute() und removeAttribute() zu ändern, initialisiert ein dynamisch erzeugtes StyleSheet alle Blöcke.

  • Liquorice wafer lollipop sesame
  • snaps gummi bears. Wafer jelly beans chupa chups cotton candy
  • caramels carrot cake topping oat cake.
  • Cake carrot cake marshmallow cheesecake cake lemon drops pudding apple pie.

Fruitcake marshmallow sugar plum soufflé biscuit.

Sesame snaps pie lemon drops.

Zuerst: Die maximale Höhe des Accordion-Elements berechnen, damit der Inhalt nach dem Accordion beim Öffnen und Schließen der Stufen nicht auf- und abtanzt.

var acco = document.querySelectorAll (".accordion>div");
var maxHeight = 0;

for (var i=0; i<acco.length; i++) {
	if (acco[i].clientHeight > maxHeight) {
		maxHeight = acco[i].clientHeight;
	}
}
var style = document.createElement("style");
document.head.appendChild(style);

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 (".wrap { height: " + maxHeight + "px }"));

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

<style>.wrap { height: 380px }</style>

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