Coding-Schatzkästlein
Kleine Tips & Scripts zum Webdesign
Start > DHTML > Stylesheets ergänzen

DHTML: CSS-Stylesheet mit JavaScript erstellen oder um Regeln ergänzen

Zusammenfassung

Name:  add Style
Aufgabe:  Ermöglicht das Hinzufügen von Stylesheets zum Dokument und von Regeln zum Stylesheet.
Benötigt:  JavaScript 1.5 (gesichert, nicht gesichert für JavaScript 1.0)
Beispiel:  addStyle("body { color: red; }")
addStyle("body { color: red; }",1)
addStyle("body { color: red; }","screen")
Testseite

Download:  addstyle.zip

English summary at end of page!

Eine Funktion, mit der man browserunabhängig ein Stylesheet seines Dokuments ändert, habe ich mit cssRule() bereits veröffentlicht. Das funktioniert logischerweise nur, wenn es bereits ein Stylesheet mit einer CSS-Regel gibt, die man ändern kann.

Aber natürlich bieten die DHTML-fähigen Browser auch JavaScript-Methoden an, um dynamisch neue Stylesheets, bzw. neue Regeln in diesen anzulegen. Aber leider, wer hätte das gedacht >;-), unterscheiden sich die Methoden vom Internet Explorer und dem Rest der Welt. In einzelnen sind hierfür gedacht:

  • createElement() um HTML-Elemente im Allgemeinen und eben auch STYLE-Elemente im Besonderen anzulegen (die dann z.B. mit appendChild() im Dokumenten-Baum hinzugefügt werden).
  • addRule() im IE-DOM, bzw. insertRule() im W3C-DOM, um in einem existierenden Stylesheet eine neue Regel zu ergänzen.

Soweit die einfache Theorie, was sagt aber die mal wieder problematische Praxis? Die sagt, daß z.B. bei dieser offiziellen Vorgehensweise Browser mit der KHTML-Engine leider einen Bug haben können, oder daß im IE mit createElement() erstellte Stylesheets nicht sofort zur Verfügung stehen (der IE "bevorzugt" sein proprietäres createStyleSheet()), oder ...
Aber kein Problem: Aus Sicht des DOM ist der Inhalt eines STYLE-Elements, also die CSS-Regeln selbst, ja ohnehin nur ein simpler Textknoten. Warum also nicht einfach createTextNode() verwenden? Das klappt auch super - außer im Internet Explorer. Der IE besteht auf seinem addRule(). Also doch Anlaß genug, das unterschiedliche Browserverhalten durch eine optimierte Funktion zu vereinheitlichen.

Der Funktionsaufruf:

addStyle([rules[,target]])

Der 1. (optionale) Parameter rules ist ein String mit einer oder mehreren neuen CSS-Regeln in der Form selector { property:value; }, also z.B.: body { color: black; background-color: red; } div { border: 1px solid black; }

Achtung: Da der IE bei dynamischen Styles den Umgang mit gruppierten Selektoren prinzipiell nicht beherrscht, teilt addStyle() im IE gruppierte Selektoren in ihre Einzelselektoren auf! Aus z.B. html, body { font-size: 120%; } wird also im IE html { font-size: 120%; } body { font-size: 120%; }! Die anderen Browser haben hingegen tatsächlich einen gruppierten Selektor (natürlich mit all den Unterschieden, die diese Browser dann dennoch hier machen - s. auch cssRule()).

Der 2. (optionale) Parameter target bestimmt das zu ergänzende Stylesheet. Mögliche Werte für target sind:

  • Eine Zahl, die die Nummer des zu ergänzenden STYLE-Elements definiert (0 für das erste STYLE-Element, 1 für das zweite, usw. Die neuen Regeln werden dann diesem Stylesheet hinzugefügt. Bei negativen Zahlen, wird von hinten gezählt (-1 für das letzte STYLE-Element, -2 für das vorletzte, usw.). Wird zu der übergebenen Zahl kein passendes STYLE-Element gefunden, so wird das am nächstenliegende, also das erste oder das letzte STYLE-Element ergänzt.
  • Ein String mit einer Medientyp-Angabe (screen, print, etc.). Es wird eine neues STYLE-Element für diesen Medientyp erzeugt.
  • Wird kein target-Parameter übergeben, so wird ein neues, allgemeines Stylesheet angelegt (also gültig für alle Medien).

Die Funktion gibt als Ergebnis das Objekt des erzeugten bzw. bearbeiteten STYLE-Elements zurück, oder null falls die Aktion nicht durchgeführt werden konnte.

Beispiele:

  • addStyle("body { font-size: 120%; }",0); fügt am Ende des 1. STYLE-Elements die angegebene Regel ein, bzw. erstellt ein neues Stylesheet, falls es nicht existiert.
  • alert(addStyle("body { font-size: 120%; }",0).innerHTML); dito, jedoch wird anschließend der Inhalt des (ergänzten oder neuen) STYLE-Elements in einer Alert-Box ausgegeben.
  • addStyle("body { font-size: 120%; }","print"); fügt ein neues Drucker-Stylesheet mit der Regel ein.
  • addStyle("body { font-size: 120%; } p { text-align: justify; }"); fügt ein neues Stylesheet mit 2 Regeln ein (gültig für alle Medien).
  • addStyle(); fügt ein neues, leeres Stylesheet ein (gültig für alle Medien).
    Achtung: Leere Stylesheets werden beim Safari & Konqueror ggf. nicht in die styleSheets-Collection aufgenommen!
  • addStyle("body { font-size: 120%; }",9999); fügt im letzten STYLE-Element die angegebene Regel ein, davon ausgehend, daß es nicht mehr als 10000 STYLE-Elemente gibt. ;-)
  • addStyle("body { font-size: 120%; }",-1); fügt im letzten STYLE-Element die angegebene Regel ein, selbst falls es mehr als 10000 STYLE-Elemente geben sollte. ;-))
  • if(!cssRule("body@print","font-size","12pt")) { addStyle("body { font-size: 12pt; }","print"); } ändert mittels cssRule() im Drucker-Stylesheet die Textgröße des Elements BODY auf 12pt, oder erstellt ein neues Drucker-Stylesheet mit dieser Regel, falls keine existierende Regel geändert werden konnte. Für diesen Zweck steht auch die Funktion setCssStyle() zur Verfügung:
setCssStyle() (Kombination cssRule() & addStyle())

Testseite 1: addStyle()-Beispiele
Testseite 2: setCssStyle()-Beispiele
(cssRule() & addStyle() kombiniert)

Der externe Quellcode: addstyle.zip

A cross-browser function to change a documents style sheet has been published by me as cssRule(). Obviously this function can only be used if an appropriate CSS rule already exists for changing.

Of course, DHTML compatible browsers have JavaScript methods to add new style sheets (createElement()) and CSS rules (insertRule()) dynamically. But again: The IE (with a delay at createElement() and needing addRule() for new rules) differs from the rest of the world, whith KHTML browsers having a nasty bug at insertRule().

The solution is this cross-browser function using proprietary createStyleSheet() & addRule() on IE and createElement() & createTextNode() on all other browsers - a little workaround which also works perfectly on buggy Konquerors. The function call:

addStyle([rules[,target]])

The 1st (optional) parameter rules is a string containing one or more CSS rules to add specified as selector { property:value; }, i.e.: body { color: black; background-color: red; } div { border: 1px solid black; }

The 2nd (optional) parameter target determines the style sheet to add the rules. Possible values are:

  • An integer defining the number of the STYLE element (0 for the 1st STYLE element, 1 for the 2nd and so on). New rules will be added at the end of that style sheet. Negative numbers will cause counting backwards (-1 for the last STYLE element, ...). If there is no matching STYLE element, the next near by will be used (the first or the last STYLE element).
  • A string with a media type (screen, print, ...). A new STYLE element of that media type will be created.
  • With no target at all, a new common style sheet (used by all medias) will be created.

The function returns the object of the created or used STYLE element or null on error.

Examples:

  • addStyle("body { font-size: 120%; }",0); adds the rule at the end of the 1st STYLE element or creates a new STYLE element with that rule if no STYLE element exists.
  • alert(addStyle("body { font-size: 120%; }",0).innerHTML); the same, but showing the contents of the STYLE element in an alert box afterwards.
  • addStyle("body { font-size: 120%; }","print"); creates a new printer style sheet with that rule.
  • addStyle("body { font-size: 120%; } p { text-align: justify; }"); creates a new style sheet with 2 rules (used by all medias).
  • addStyle(); creates a new, empty style sheet (used by all medias).
    Attention: Empty style sheets are probably ignored by Safaris & Konquerors styleSheets collection!
  • if(!cssRule("body@print","font-size","12pt")) { addStyle("body { font-size: 12pt;","print"); } changes the font size at the BODY element of a printer style sheet using cssRule() to 12pt or creates a new printer style sheet if no existing rule could be changed.
Test page: addStyle() examples

The external source code: addstyle.zip



Updates:
27.09.2007: 
Korrektur: Workaround für den IE eingebaut, weil er bei addRule() nicht mit einem "leerem Stil" umgehen kann.
28.07.2007: 
Erweiterung: Es können jetzt mehrere Regeln anstatt nur einer übergeben werden, und Workaround für IE-Verhalten bei gruppierten Selektoren eingebaut.
31.05.2007: 
Korrektur: Im Download-Script (nicht in der intern von dieser Website benutzen Version) war versehentlich eine Codezeile doppelt, und die Regel wurde im IE zweimal angelegt (was prinzipiell ärgerlich, technisch aber unproblematisch ist).


Kurz-URL dieses Artikels: http://Coding.binon.net/AddStyle