CSSOM und Typed OM
HTML- und auch CSS-Dokumente sind Text, die vom Browser analysiert (geparst) und dann gerendert werden. Dabei wird das HTML-Markup in ein Document Object Model (DOM) umgewandelt.
Parallel dazu werden Stylesheets ebenfalls geparst und bilden das CSSOM (CSS Object Modul). Es lässt sich - genau wie das DOM - mit JavaScript auslesen und beeinflussen. Da es einige Beschränkungen hat, wurde mit Houdini ein CSS Typed OM eingeführt, das im 2. Kapitel vorgestellt wird.
In diesem Artikel erhältst du einen Blick hinter die Kulissen und lernst, wie neue Regeln direkt in das Stylesheet eingefügt werden können, ohne weitere HTTP-Requests beim Nachladen alternativer Stylesheets zu benötigen.
Inhaltsverzeichnis
Bevor der Browser die Seite rendern, d.h. darstellen kann, muss er das HTML- und auch CSS-Markup analysieren (parsen). Dabei wird das HTML-Markup in ein Document Object Model (DOM) umgewandelt.[1]
Dues passiert in folgenden Schritten:
- Konvertierung der Bytes in einzelne Zeichen.
- Tokenisierung: Zeichenfolgen werden in verschiedene Tokens umgewandelt, wie z.B.
<html>
oder<body>
- Lexing: Die ausgegebenen Token werden in DomTokenList-„Objekte“ konvertiert, die ihre Properties und Regeln definieren.
- die einzelnen Objekte werden in einem Elementbaum eingehängt, der das DOM bildet.
Dieses DOM wird in der Webseite vom Browser gerendert und kann durch JavaScript manipuliert werden.
CSSOM
Wenn beim Zusammenbau des DOM ein Link-Tag gefunden wird, das auf ein externes CSS-Stylesheet verweist, wird auch dieses geparst und dann ausgewertet.
Wie bei HTML müssen wir die empfangenen CSS-Regeln so konvertieren, dass sie vom Browser verstanden werden und funktionieren. Daher wiederholen wir den HTML-Prozess, aber für CSS statt HTML:
So entsteht erneut eine Baumstruktur - das CSS Object Model (CSSOM):[2]
Diese Baumstruktur ist deshalb nötig, weil einige Elemente ihre Eigenschaften von ihren Elternelementen erben (→ CSS/Vererbung).
So wird die für body festgelegte Schriftgröße von 16px auf alle p und auch die span vererbt. ein span als Kind von p wird jedoch gar nicht angezeigt.
Im Regelfall muss man sich um den CSSOM-Baum nicht viel kümmern, da das gesamte Rendering im Backend stattfindet. Allerdings muss das CSSOM vollständig geladen sein, bevor die Webseite angezeigt wird, da es festlegt, wie jedes Element auf der Seite aussehen soll. Würde die Seite vor der CSSOM geladen, würde sie zuerst als reines HTML (FOUC (Flash of unstyled Content)) erscheinen, gefolgt von den Stilen ein paar Sekunden später.
Außerdem kann das CSSOM nicht zwischengespeichert werden; sie muss für jede Seite neu erstellt werden. Tatsächliche CSS-Dateien können gecached werden, aber das Rendern einer Seite im Browser erfordert immer die Ausführung des CSSOM-Parsers.
Zugriff mit JavaScript
Bestandteil jedes Anfängertutorials ist das Hinzuzufügen, Entfernen und Ändern von Bestandteilen einer Webseite, die so genannte DOM-Manipulation.
Genau so kann auch auf das CSSOM zugegriffen werden:
const styleSheet = [];
const styleSheets = document.styleSheets;
for (let i = 0; i < styleSheets.length; i++) {
styleSheet.push(styleSheets[i]);
}
console.log(styleSheet);
Mit document.styleSheets
werden alle Stylesheets in einer StyleSheetList ermittelt und mit der Konsole ausgegeben.
Jedes einzelne Stylesheet bildet ein CSSStylesheet
-Objekt, das aus mehreren Unterobjekten besteht:
- CSSStyleSheet
- Ein einzelnes Stylesheet aus der obigen Liste.
- CSSRuleList
- Eine Liste aller CSSStyleRule-Regeln eines Styleheets
- CSSStyleRule
- Ein Objekt mit einer einfachen Style-Regel.
CSSStylesheet
Jedes einzelne Stylesheet bildet ein CSSStylesheet-Objekt.[3][4]
Eigenschaften
CSSStyleSheet.cssRules
: gibt eineCSSRuleList
aller CSS-Festlegungen zurückCSSStyleSheet.ownerRule
: Wenn das Stylesheet mittels einer@import
-Regel geladen wurde, gibt dieownerRule
-Eigenschaft dieseCSSImportRule
zurück, sonst gibt esnull
zurück.
Methoden
- CSSStyleSheet.deleteRule: löscht eine CSS-Festlegung
- CSSStyleSheet.insertRule: fügt eine CSS-Festlegung in das aktuelle Stylesheet ein
Sie können auf Ihr Stylesheet entweder über eine id oder das CSSStylesheet-Objekt zugreifen:
var sheets = document.styleSheets; // gibt eine array-ähnliche Liste aller Stylesheets aus
Am einfachsten ist es wohl, auf das erste verfügbare Stylesheet zuzugreifen:
var sheet = document.styleSheet[0];
deleteRule
Die CSSStyleSheet.deleteRule-Methode löscht eine CSS-Festlegung.
stylesheet.deleteRule(index)
Folgende Parameter ist nötig:
index
: ganze Zahl, welche Festlegung gelöscht werden soll.
insertRule
Die CSSStyleSheet.insertRule-Methode fügt eine CSS-Festlegung in das aktuelle Stylesheet ein.[5]
Syntax
stylesheet.insertRule(regel, index)
Folgende Parameter sind nötig:
regel
: bestehend aus einem DOM-String, der den Selektor und die Festlegung beinhaltet.index
: ganze Zahl, an welcher Stelle die Festlegung eingefügt werden soll.Empfehlung: Wenn Sie bestehende Regeln überschreiben wollen, benötigen Sie einen anderen Wert als 0.
function changeStylez() {
var sheet = document.styleSheets[0];
sheet.insertRule("#über { background: #c32e04; color: white; }", 1);
}
sheet.insertRule("@media all { Selektor1 { Regel : Wert } Selektor2 { Regel : Wert} }", 1);
CSS Typed OM
Die CSSOM-Spezifikation ist großartig, um Stylesheets mittels JavaScript aufzubauen. Man kann ein leeres style-Element im head unterbringen, man kann ihm diverse Unterklassen von CSSRule-Objekten hinzufügen und diesen Rules Selektoren und Eigenschaften geben.
Anders sieht es aus, wenn man die Werte der so gesetzten Eigenschaften wieder auslesen will. Das CSSOM ist ausschließlich auf Strings aufgebaut. Das heißt: Der Browser muss, um die vom CSSOM vorgegebene Darstellung zu liefern, seinen internen numerischen Wert in einen String verwandeln und ein "px" anhängen, nur damit du es dann wieder auseinandernehmen musst.
Die CSS Typed Object Model API vereinfacht die Manipulation von CSS-Eigenschaften, indem sie CSS-Werte als typisierte JavaScript-Objekte und nicht als Zeichenketten bereitstellt. Dies vereinfacht erst einmal die CSS-Bearbeitung.[6] [7]
Bereits im Kapitel CSS-Eigenschaften_auslesen wurde ein Beispiel vorgestellt, in dem mit computedStyleMap() die Schriftgröße der ausgewählten Elemente zurückgegeben wurde.
CSSStyleValue
CSS-Objekt
Zusätzlich zu CSSOM und Typed OM gibt es noch ein CSS-Objekt. Das CSS-Objekt bietet Methoden und Ereignisse an, um aus JavaScript heraus mit CSS interagieren zu können. Es repräsentiert eine statische Klasse, von der keine Instanzen erzeugt werden können.[10]
Konstruktor
- Nicht aufrufbar, statisches Objekt
Statische Methoden
Statische Eigenschaften
paintWorklet
Die Verwendung des Paint Worklet ist derzeit noch im Draft-Stadium. Es soll ermöglichen, für HTML Elemente das Rendering per JavaScript auszuführen – analog beispielsweise zum Paint-Event in Windows-Programmen.[11]
supports
CSS.supports() gehört zum CSS-Conditional-Rules-Modul Level 3 und bietet aus JavaScript heraus die gleiche Funktion wie die @supports-Direktive in CSS-Dateien.[12]
Aufrufvarianten
isSupported = CSS.supports(bedingung);
isSupported = CSS.supports(eigenschaft, wert);
Die Variante 1 erhält als Parameter eine Zeichenkette, wie sie auch innerhalb der Klammern einer @supports-Regel in einer CSS-Datei notiert würde. Beachten Sie, dass Namen, die CSS-Steuerzeichen enthalten, escaped werden müssen (siehe dazu CSS.escape).
Bei Variante 2 übergibt man den Namen einer CSS-Eigenschaft und einen möglichen Wert.
Das Ergebnis der Funktion ist ein boolescher Wert, der angibt, ob der Browser die angefragte Funktionalität unterstützt.
escape
Diese Funktion ist Teil des CSSOM (CSS-Object-Model) und dient dazu, die in einem String vorhandenen CSS-Steuerzeichen zu maskieren. Auf diese Weise können Strings wie ".hello#world" oder "that[s]=life" in CSS-bezogenen DOM-Funktionen (z. B. querySelector) als Klassennamen oder IDs verwenden werden.[13]
registerProperty
Diese Methode gehört zum Properties and Values API der CSS Houdini Initiative und dient dazu, Syntaxregeln für Custom Properties festzulegen.[14]
CSS.registerProperty( propertyDefinition )
Als propertyDefinition
übergeben Sie ein Objekt, z. B. als Objektliteral, mit den folgenden Eigenschaften:
- name
- Der Name des custom property, für das sie eine Syntax festlegen möchten
- syntax
- (optional) Die Syntaxregel. Bitte schauen Sie für nähere Angaben in Abschnitt 5, Syntax, der W3C Spezifikation.
- inherits
- Boolescher Wert. Setzen Sie
true
, wenn ein Element dieses Custom Property an seine Kindelemente vererben darf, sonstfalse
- initialValue
- Der Wert, der für das Custom Property verwendet werden soll, wenn er nicht in einer CSS Regel festgelegt wurde.
Wenn Sie die Syntaxangabe weglassen, wird "*" verwendet, d.h. jeder Wert ist zulässig. In diesem Fall benötigen Sie keine Angabe für initialValue. In allen anderen Fällen müssen Sie als initialValue einen Wert festlegen, der auf das angegebene Syntaxmuster passt.
Siehe auch
Weblinks
- ↑ Objektmodell erstellen (web.dev) von Ilja Grigorik
- ↑ CCSWG.org: CSS Object Model (CSSOM) (Entwurf)
- ↑ W3C: Dynamic style - manipulating CSS with JavaScript
- ↑ MDN : CSSStyleSheet API
- ↑ David Walsh: Add Rules to Stylesheets with JavaScript
- ↑ MDN: Using the CSS Typed Object Model
Umfassender Grundlagenartikel, auch wenn Mozilla CSS Typed OM noch nicht implementiert hat - ↑ MDN: Houdini_APIs
- ↑ WHATWG: CSSStyleValue objects
- ↑ MDN: CSSStyleValue
- ↑ MDN: CSS Interface
- ↑ [* W3C: CSS Painting API, paintWorklet
- ↑ W3C: The CSS namespace, supports()
- ↑ W3C: CSS Object Model, escape()
- ↑ MDN: CSS: registerProperty() static method