CSSOM und Typed OM

Aus SELFHTML-Wiki
(Weitergeleitet von JavaScript/CSS)
Wechseln zu: Navigation, Suche

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.

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] Aufbau des DOM

Dues passiert in folgenden Schritten:

  1. Konvertierung der Bytes in einzelne Zeichen.
  2. Tokenisierung: Zeichenfolgen werden in verschiedene Tokens umgewandelt, wie z.B. <html> oder <body>
  3. Lexing: Die ausgegebenen Token werden in DomTokenList-„Objekte“ konvertiert, die ihre Properties und Regeln definieren.
  4. 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:

Infografik, die die Schritte zum Erstellen des DOM zeigt

So entsteht erneut eine Baumstruktur - das CSS Object Model (CSSOM):[2]

Infografik, die DOM-Tree zeigt.

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:

Stylesheets auslesen ansehen …
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:

  1. CSSStyleSheet
    Ein einzelnes Stylesheet aus der obigen Liste.
  2. CSSRuleList
    Eine Liste aller CSSStyleRule-Regeln eines Styleheets
  3. CSSStyleRule
    Ein Objekt mit einer einfachen Style-Regel.

CSSStylesheet

Jedes einzelne Stylesheet bildet ein CSSStylesheet-Objekt.[3][4]

Eigenschaften

  • CSSStyleSheet.cssRules: gibt eine CSSRuleList aller CSS-Festlegungen zurück
  • CSSStyleSheet.ownerRule: Wenn das Stylesheet mittels einer @import-Regel geladen wurde, gibt die ownerRule-Eigenschaft diese CSSImportRule zurück, sonst gibt es null zurück.

Methoden


Sie können auf Ihr Stylesheet entweder über eine id oder das CSSStylesheet-Objekt zugreifen:

Beispiel
var sheets = document.styleSheets; // gibt eine array-ähnliche Liste aller Stylesheets aus

Am einfachsten ist es wohl, auf das erste verfügbare Stylesheet zuzugreifen:

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


CSS-Regelsatz mit insertRulee hinzufügen ansehen …
function changeStylez() {
  var sheet = document.styleSheets[0];
  sheet.insertRule("#über { background: #c32e04; color: white; }", 1);
}
Empfehlung: Da Sie immer nur eine Regel einfügen können, empfiehlt es sich bei größeren Änderungen eine @media -Regel einzufügen, die beliebig viel Regelsätze enthalten kann:
Beispiel
  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

[8] [9]

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 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, sonst false
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

  1. Objektmodell erstellen (web.dev) von Ilja Grigorik
  2. CCSWG.org: CSS Object Model (CSSOM) (Entwurf)
  3. W3C: Dynamic style - manipulating CSS with JavaScript
  4. MDN : CSSStyleSheet API
  5. David Walsh: Add Rules to Stylesheets with JavaScript
  6. MDN: Using the CSS Typed Object Model
    Umfassender Grundlagenartikel, auch wenn Mozilla CSS Typed OM noch nicht implementiert hat
  7. MDN: Houdini_APIs
  8. WHATWG: CSSStyleValue objects
  9. MDN: CSSStyleValue
  10. MDN: CSS Interface
  11. [* W3C: CSS Painting API, paintWorklet
  12. W3C: The CSS namespace, supports()
  13. W3C: CSS Object Model, escape()
  14. MDN: CSS: registerProperty() static method