Jan 10

CSS-Stylesheets zur Laufzeit mit Javascript erzeugen

Tag: Canvas,JavascriptPatrick @ 6:50 pm

An dieser Stelle möchte ich eine relative unbekannte Möglichkeit zur Manipulation des Aussehens von Webseiten vorstellen, über die ich selbst erst vor wenigen Tagen gestolpert bin. Die Rede ist von DOM CSS.

In den meisten Anwendungsfällen ändert man das Erscheinungsbild von Elementen, indem man diese direkt anspricht (zum Beispiel mit getElementById(id) ) und mittels style-Attribut beeinflusst.

Mit DOM CSS ist es möglich, solche Änderungen in CSS-Regeln wie div.menu { color: black } durchzuführen. Dazu bieten alle modernen Browser Funktionen zum Entfernen bestehender und zum Erstellen neuer CSS-Regeln.

Dabei halten sich die meisten Browser-Entwickler an die W3C-Vorgaben, nur Microsofts Internet Explorer – wie so oft – nicht. Dennoch bietet der IE ähnliche Funktionen.

Grundsätzlich adressiert man zuerst das Stylesheet, das man mit Javascript beeinflussen will. Dies kann man zum Beispiel über die getElement-Methoden tun.

Das document-Object stellt mit document.styleSheets[index] eine weitere Möglichkeit zum Ansprechen von Stylesheets zur Verfügung, womit sowohl alle internen style-Elemente als auch alle externen, mit link erzeugten CSS-Definitionen erreicht werden können.

In standardkonformen Browsern greift man mit cssRules[index] auf bestehende CSS-Regeln zu, der IE reagiert nur auf die MS-eigene Methode rules[index].

Anschließend kann man mit dem style-Attribut wie gewohnt die Eigenschaftswerte verändern. Zum Beispiel:

document.styleSheets[0].cssRules[0].style.backgroundColor = "yellow";

Außerdem gibt es die Möglichkeit mittels der selectorText-Methode den Selector eines CSS-Regel auszulesen. Damit lässt eine Schleife konstruieren, die alle CSS-Regeln nach einem bestimmten Eintrag durchsucht, wie nachfolgend demonstriert:

if( document.styleSheets[0].cssRules ) {
	var myrules = document.styleSheets[0].cssRules;
} else {
	if ( document.styleSheets[0].rules ) {
		var myrules = document.styleSheets[0].rules;
	}
}

if( myrules ) {
	for( i = 0; myrules[i]; i++ ){
		if( myrules[i].selectorText == "p"){
			myrule = myrules[i];
			break;
		}
	}
}

Um neue Regeln hinzuzufügen, verwendet man in standardkonformen Browsern die insertRule[definition, index]-Methode, für den Explorer heißt die Funktion addRule[selector, style, index (optional)].

Vorhandene CSS-Definitionen löscht man mittels deleteRule[index] beziehungsweise removeRule[index (optional)] im IE.

Nachfolgend ist der komplette Code eines Mini-Beispiel zu finden. Dabei wird zuerst ein neues style-Elemente zur Laufzeit erstellt, in das HTML-Gerüst eingebettet und abschließend mittels DOM CSS eine Regel für das body-Element festgelegt, die Hintergrund- und Schriftfarbe verändert.

<br />
if( document.styleSheets ) {
	var myStyle = document.createElement("style");
	myStyle.setAttribute( "type", "text/css" );
	document.getElementsByTagName("head")[0].appendChild(myStyle);

	var styles = document.styleSheets.length;
	myStyle = document.styleSheets[styles-1];

	if( document.styleSheets[0].cssRules ) {
		myStyle.insertRule("body { color: red; background-color: black; }", 0);
	} else {
		if ( document.styleSheets[0].rules ) {
			myStyle.addRule("body", "color: red; background-color: black;");
		}
	}
}

Ich favorisiere den Weg über das Hinzufügen eines neuen style-Elements anstatt dem Bearbeiten vorhandener Definitionen, da mir dies übersichtlicher und logischer vorkommt. Zumal – in den meisten Fällen – die zuletzt festgelegte CSS-Regel bei Überschneidungen zur Darstellung vom Browser genutzt wird.

Der Vorteil gegenüber dem traditionellen Ändern von style-Attributen über das direkte Ansprechen liegt vor allem in der Geschwindigkeit bei einer großen Anzahl von Elementen, die verändert werden sollen.

Ein Browser kann erheblich schneller 1.000 Elementen eine neue Schriftfarbe über eine CSS-Regel zuweisen als in einer Schleife eben diese Elemente direkt zu adressieren und jedem die neue Schriftfarbe zuzuweisen.

Interessant ist DOM CSS daher bei Javascript-Anwendungen, die neue HTML-Elemente (für runde Ecken beispielsweise) in den Code einbinden.

4 Antworten zu “CSS-Stylesheets zur Laufzeit mit Javascript erzeugen”

  1. Thomas Scholz sagt:

    Danke für die gute Erklärung!
    Wie rückwärtskompatibel ist das denn?

  2. Patrick sagt:

    Auf jeden Fall funktioniert es mit dem Internet Explorer ab Version 6. Firefox 3 – sicherlich auch 2 – kommt damit ebenso zurecht wie Opera 9+ und Safari 3. Safari 2 kann wegen nicht-vorhandenseins eines (älteren) Macs nicht testen.

  3. Cybaer sagt:

    Prinzipiell funktioniert es in allen Browsern mit „modernem“ DOM. Nur Opera besitzt das styleSheets-Objekt erst ab Version 9. Und dann gibt es noch das Problem, daß der IE/Mac sowohl die (proprietäre) rules- als auch die (standardisierte) cssRules-Collection kennt. Leider hat er aber bei cssRules nicht die Methoden/Eigenschaften, die ein standardkonformer Browser hier hat. Beim Konqueror (mindestens bis 3.x) ist es genau andersherum. Er kennt ebenfalls beide Collections, aber er beherrscht nur die standardkonformen Methoden/Eigenschaften. Außerdem haben (mindestens ältere) Browser mit KHTML-Engine (also im wesentlichen Konqueror & Safari) einen Bug bei insertRule(), der die Nutzung verhindert.

    Ich gehe deswegen einen anderen Weg, um neue Regeln anzuhängen. Die IEs bekommen ihren proprietären Weg, und der standardkonforme Rest bekommt einen Workaround, der auch auf älteren Operas, Safaris und Konquerors funktioniert: Das interne Stylesheet nicht aus Sicht des CSSDOMs sondern aus Sicht des (HTML-)DOMs behandeln. Also als simpler Textknoten, und diesem Textknoten einfach neuen „Stylesheet-Text“ hinzufügen (s. addStyle()).

  4. Css manipulieren sagt:

    […] zweiten Spiegelstrich das dynamische Erzeugen einer Klasse gemeint ist findet sich hier ein Tut: CSS-Stylesheets zur Laufzeit mit Javascript erzeugen | Ajaxschmiede.de Ansonsten musst du sagen, was du mit "Selector" meinst. Den Begriff verwende ich nur, […]

Hinterlasse einen Kommentar

You must be logged in to post a comment.