Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Verwendung des CSS Typed Object Model

Die CSS Typed Object Model API stellt CSS-Werte als typisierte JavaScript-Objekte bereit, damit sie effizient verändert werden können.

Die Umwandlung von Werte-Strings des CSS Object Model in aussagekräftig typisierte JavaScript-Repräsentationen und zurück (über HTMLElement.style) kann einen erheblichen Leistungsaufwand verursachen.

Das CSS Typed OM macht die Bearbeitung von CSS logischer und effizienter: Statt CSSOM-Strings zu bearbeiten, können Sie Objektfunktionen nutzen und auf Typen, Methoden und ein Objektmodell für CSS-Werte zugreifen.

Dieser Artikel stellt die wichtigsten Funktionen vor.

computedStyleMap()

Mit der CSS Typed OM API können wir auf alle CSS-Eigenschaften und -Werte zugreifen, die sich auf ein Element auswirken – einschließlich benutzerdefinierter Eigenschaften. Sehen wir uns anhand eines ersten Beispiels an, wie das mit computedStyleMap() funktioniert.

Alle Eigenschaften und Werte abrufen

HTML

Wir beginnen mit HTML: einem Absatz mit einem Link sowie einer Definitionsliste, der wir alle CSS-Eigenschaft-Wert-Paare hinzufügen werden.

html
<p>
  <a href="https://example.com">Link</a>
</p>
<dl id="regurgitation"></dl>

JavaScript

Wir fügen JavaScript hinzu, das unseren nicht formatierten Link auswählt und mithilfe von computedStyleMap() eine Definitionsliste aller CSS-Standardwerte erstellt, die sich auf den Link auswirken.

js
// Get the element
const myElement = document.querySelector("a");

// Get the <dl> we'll be populating
const stylesList = document.querySelector("#regurgitation");

// Retrieve all computed styles with computedStyleMap()
const defaultComputedStyles = myElement.computedStyleMap();

// Iterate through the map of all the properties and values, adding a <dt> and <dd> for each
for (const [prop, val] of defaultComputedStyles) {
  // properties
  const cssProperty = document.createElement("dt");
  cssProperty.appendChild(document.createTextNode(prop));
  stylesList.appendChild(cssProperty);

  // values
  const cssValue = document.createElement("dd");
  cssValue.appendChild(document.createTextNode(val));
  stylesList.appendChild(cssValue);
}

Die Methode computedStyleMap() gibt ein StylePropertyMapReadOnly-Objekt zurück. Dessen Eigenschaft size gibt an, wie viele Eigenschaften die Map enthält. Wir durchlaufen die Style-Map und erstellen für jede Eigenschaft ein <dt> und für den jeweiligen Wert ein <dd>.

Ergebnis

In Browsern, die computedStyleMap() unterstützen, sehen Sie eine Liste aller CSS-Eigenschaften und -Werte. In anderen Browsern sehen Sie lediglich einen Link.

War Ihnen bewusst, wie viele CSS-Standardeigenschaften ein Link hat? Ändern Sie den ersten Aufruf von document.querySelector so, dass er <p> statt <a> auswählt. Sie werden einen Unterschied bei den berechneten Standardwerten von margin-top und margin-bottom feststellen.

Die Methode .get() und benutzerdefinierte Eigenschaften

Ändern wir unser Beispiel so, dass es nur einige Eigenschaften und Werte abruft. Zunächst fügen wir etwas CSS hinzu, darunter eine benutzerdefinierte und eine vererbbare Eigenschaft:

css
p {
  font-weight: bold;
}

a {
  --color: red;
  color: var(--color);
}

Statt alle Eigenschaften abzurufen, erstellen wir ein Array mit den Eigenschaften, die uns interessieren, und rufen ihre Werte jeweils mit der Methode StylePropertyMapReadOnly.get() ab:

js
// Get the element
const myElement = document.querySelector("a");

// Get the <dl> we'll be populating
const stylesList = document.querySelector("#regurgitation");

// Retrieve all computed styles with computedStyleMap()
const allComputedStyles = myElement.computedStyleMap();

// Array of properties we're interested in
const ofInterest = ["font-weight", "border-left-color", "color", "--color"];

// iterate through our properties of interest
for (const value of ofInterest) {
  // Properties
  const cssProperty = document.createElement("dt");
  cssProperty.appendChild(document.createTextNode(value));
  stylesList.appendChild(cssProperty);

  // Values
  const cssValue = document.createElement("dd");
  cssValue.appendChild(document.createTextNode(allComputedStyles.get(value)));
  stylesList.appendChild(cssValue);
}

Wir haben border-left-color aufgenommen, um zu zeigen, dass alle Eigenschaften, deren Wert standardmäßig currentColor ist (darunter caret-color, outline-color, text-decoration-color und column-rule-color), rgb(255 0 0) zurückgeben würden, wenn wir sie abfragen. Der Link hat font-weight: bold; von den Styles des Absatzes geerbt; der Wert wird als font-weight: 700 aufgeführt. Benutzerdefinierte Eigenschaften wie unser --color: red sind ebenfalls Eigenschaften und können daher mit get() abgerufen werden.

Beachten Sie, dass benutzerdefinierte Eigenschaften ihren im Stylesheet angegebenen Wert behalten, während berechnete Styles mit ihrem berechneten Wert aufgeführt werden: color wurde als rgb()-Wert aufgeführt, und für font-weight wurde 700 zurückgegeben, obwohl wir eine benannte Farbe und das Schlüsselwort bold verwenden.

CSSUnitValue und CSSKeywordValue

Eine Stärke des CSS Typed OM besteht darin, dass Werte und Einheiten getrennt vorliegen. Das Parsen und Verketten von Strings könnte damit der Vergangenheit angehören. Jede CSS-Eigenschaft in einer Style-Map hat einen Wert. Ist dieser Wert ein Schlüsselwort, wird ein CSSKeywordValue zurückgegeben. Bei einem numerischen Wert wird ein CSSUnitValue zurückgegeben.

CSSKeywordValue ist eine Klasse für Schlüsselwörter wie inherit, initial und unset sowie andere Strings, die ohne Anführungszeichen geschrieben werden, etwa auto und grid. Über cssKeywordValue.value stellt diese Unterklasse eine value-Eigenschaft bereit.

CSSUnitValue wird zurückgegeben, wenn der Wert einen Einheitentyp hat. Die Klasse definiert Zahlen mit Maßeinheiten wie 20px, 40% und 200ms sowie Zahlen wie 7. Sie stellt zwei Eigenschaften bereit: value und unit. Damit können wir auf den numerischen Wert – cssUnitValue.value – und seine Einheit – cssUnitValue.unit – zugreifen.

Schreiben wir einen einfachen Absatz ohne eigene Styles und untersuchen einige seiner CSS-Eigenschaften. Dazu geben wir eine Tabelle mit Einheit und Wert aus:

html
<p>
  This is a paragraph with some content. Open up this example in the playground,
  and change some features. Try adding some CSS, such as a width for this
  paragraph, or adding a CSS property to the ofInterest array.
</p>
<table id="regurgitation">
  <thead>
    <tr>
      <th>Property</th>
      <th>Value</th>
      <th>Unit</th>
    </tr>
  </thead>
</table>

Für jede untersuchte Eigenschaft führen wir ihren Namen auf und rufen mit .get(propertyName).value ihren Wert ab. Wenn das von get() zurückgegebene Objekt ein CSSUnitValue ist, führen wir außerdem den mit .get(propertyName).unit abgerufenen Einheitentyp auf.

js
// Get the element we're inspecting
const myElement = document.querySelector("p");

// Get the table we'll be populating
const stylesTable = document.querySelector("#regurgitation");

// Retrieve all computed styles with computedStyleMap()
const allComputedStyles = myElement.computedStyleMap();

// Array of properties we're interested in
const ofInterest = [
  "padding-top",
  "margin-bottom",
  "font-size",
  "font-stretch",
  "transition-duration",
  "animation-iteration-count",
  "width",
  "height",
];

// Iterate through our properties of interest
for (const value of ofInterest) {
  // Create a row
  const row = document.createElement("tr");

  // Add the name of the property
  const cssProperty = document.createElement("td");
  cssProperty.appendChild(document.createTextNode(value));
  row.appendChild(cssProperty);

  // Add the unitless value
  const cssValue = document.createElement("td");

  // Shrink long floats to 1 decimal point
  let propVal = allComputedStyles.get(value).value;
  propVal = propVal % 1 ? propVal.toFixed(1) : propVal;
  cssValue.appendChild(document.createTextNode(propVal));
  row.appendChild(cssValue);

  // Add the type of unit
  const cssUnit = document.createElement("td");
  cssUnit.appendChild(
    document.createTextNode(allComputedStyles.get(value).unit),
  );
  row.appendChild(cssUnit);

  // Add the row to the table
  stylesTable.appendChild(row);
}

Wenn Sie einen Browser ohne Unterstützung verwenden, sollte die obige Ausgabe ungefähr so aussehen:

Eigenschaft Wert Einheit
padding-top 0 px
margin-bottom 16 px
font-size 16 px
font-stretch 100 percent
transition-duration 0 s
animation-iteration-count 1 number
width auto undefined
height auto undefined

Beachten Sie, dass für <length> die Einheit px zurückgegeben wird, für <percentage> die Einheit percent und für <time> die Einheit s für Sekunden. Für das einheitenlose <number> wird number als Einheit zurückgegeben.

Wir haben für den Absatz weder width noch height festgelegt. Beide haben standardmäßig den Wert auto und geben daher ein CSSKeywordValue statt eines CSSUnitValue zurück. CSSKeywordValue-Objekte besitzen keine unit-Eigenschaft. Deshalb gibt get().unit in diesen Fällen undefined zurück.

Wären width oder height als <length> oder <percent> definiert, wäre die Einheit des CSSUnitValue entsprechend px oder percent.

Es gibt weitere Typen:

Sie können ein CSSUnitValue oder CSSKeywordValue verwenden, um weitere Objekte zu erstellen.

CSSStyleValue

Das Interface CSSStyleValue der CSS Typed Object Model API ist die Basisklasse aller CSS-Werte, auf die über die Typed OM API zugegriffen werden kann. Dazu gehören CSSImageValue, CSSKeywordValue, CSSNumericValue, CSSPositionValue, CSSTransformValue und CSSUnparsedValue.

Es verfügt über zwei Methoden:

Wie oben erwähnt, gibt StylePropertyMapReadOnly.get('--customProperty') ein CSSUnparsedValue zurück. Instanzen von CSSUnparsedValue können wir mit den geerbten Methoden CSSStyleValue.parse() und CSSStyleValue.parseAll() parsen.

Sehen wir uns ein CSS-Beispiel mit mehreren benutzerdefinierten Eigenschaften, Transformationen, calc()-Ausdrücken und weiteren Funktionen an. Mit kurzen JavaScript-Snippets, die Ergebnisse über console.log() ausgeben, untersuchen wir deren Typen:

css
:root {
  --main-color: hsl(198 43% 42%);
  --black: hsl(0 0% 16%);
  --white: hsl(0 0% 97%);
  --unit: 1.2rem;
}

button {
  --main-color: hsl(198 100% 66%);
  display: inline-block;
  padding: var(--unit) calc(var(--unit) * 2);
  width: calc(30% + 20px);
  background: no-repeat 5% center url("magic-wand.png") var(--main-color);
  border: 4px solid var(--main-color);
  border-radius: 2px;
  font-size: calc(var(--unit) * 2);
  color: var(--white);
  cursor: pointer;
  transform: scale(0.95);
}

Fügen wir die Klasse einem Button hinzu (der nichts tut).

html
<button>Styled Button</button>

Mit dem folgenden JavaScript rufen wir unser StylePropertyMapReadOnly ab:

js
const allComputedStyles = document.querySelector("button").computedStyleMap();

Die folgenden Beispiele beziehen sich auf allComputedStyles:

CSSUnparsedValue

CSSUnparsedValue repräsentiert benutzerdefinierte Eigenschaften:

js
// CSSUnparsedValue
const unit = allComputedStyles.get("--unit");

console.log(unit); // CSSUnparsedValue {0: " 1.2rem", length: 1}
console.log(unit[0]); // " 1.2rem"

Wenn wir get() aufrufen, wird für eine benutzerdefinierte Eigenschaft ein Wert vom Typ CSSUnparsedValue zurückgegeben. Beachten Sie das Leerzeichen vor 1.2rem. Um Einheit und Wert zu erhalten, benötigen wir ein CSSUnitValue. Dieses können wir abrufen, indem wir die Methode CSSStyleValue.parse() auf das CSSUnparsedValue anwenden.

js
const parsedUnit = CSSNumericValue.parse(unit);
console.log(parsedUnit); // CSSUnitValue {value: 1.2, unit: "rem"}
console.log(parsedUnit.unit); // "rem"
console.log(parsedUnit.value); // 1.2

CSSMathSum

Obwohl das Element <button> standardmäßig ein Inline-Element ist, haben wir display: inline-block; hinzugefügt, damit wir seine Größe festlegen können. In unserem CSS verwenden wir width: calc(30% + 20px); – die Funktion calc() legt hier die Breite fest.

Wenn wir width mit get() abrufen, erhalten wir ein CSSMathSum. CSSMathSum.values ist ein CSSNumericArray mit zwei CSSUnitValues.

Der Wert von CSSMathValue.operator ist sum:

js
const btnWidth = allComputedStyles.get("width");

console.log(btnWidth); // CSSMathSum
console.log(btnWidth.values); // CSSNumericArray {0: CSSUnitValue, 1: CSSUnitValue, length: 2}
console.log(btnWidth.operator); // 'sum'

CSSTransformValue mit CSSScale

display: inline-block; ermöglicht außerdem Transformationen. In unserem CSS verwenden wir transform: scale(0.95); – eine Funktion der Eigenschaft transform.

js
const transform = allComputedStyles.get("transform");

console.log(transform); // CSSTransformValue {0: CSSScale, 1: CSSTranslate, length: 2, is2D: true}
console.log(transform.length); // 1
console.log(transform[0]); // CSSScale {x: CSSUnitValue, y: CSSUnitValue, z: CSSUnitValue, is2D: true}
console.log(transform[0].x); // CSSUnitValue {value: 0.95, unit: "number"}
console.log(transform[0].y); // CSSUnitValue {value: 0.95, unit: "number"}
console.log(transform[0].z); // CSSUnitValue {value: 1, unit: "number"}
console.log(transform.is2D); // true

Wenn wir die Eigenschaft transform mit get() abrufen, erhalten wir ein CSSTransformValue. Mit der Eigenschaft length können wir die Anzahl der Transformationsfunktionen abfragen.

Da length den Wert 1 hat und damit eine einzelne Transformationsfunktion repräsentiert, geben wir das erste Objekt aus und erhalten ein CSSScale-Objekt. Wenn wir die Skalierungswerte für x, y und z abfragen, erhalten wir CSSUnitValues. Die schreibgeschützte Eigenschaft CSSScale.is2D ist in diesem Fall true.

Hätten wir außerdem die Transformationsfunktionen translate(), skew() und rotate() hinzugefügt, wäre length gleich 4. Jede Funktion hätte eigene x-, y- und z-Werte sowie eine .is2D-Eigenschaft. Hätten wir beispielsweise transform: translate3d(1px, 1px, 3px) verwendet, hätte .get('transform') ein CSSTranslate mit CSSUnitValues für x, y und z zurückgegeben; die schreibgeschützte Eigenschaft .is2D wäre false.

CSSImageValue

Unser Button hat ein Hintergrundbild: einen Zauberstab.

js
const bgImage = allComputedStyles.get("background-image");

console.log(bgImage); // CSSImageValue
console.log(bgImage.toString()); // url("magic-wand.png")

Wenn wir 'background-image' mit get() abrufen, wird ein CSSImageValue zurückgegeben. Obwohl wir die CSS-Kurzschreibweise background verwendet haben, zeigt die geerbte Methode Object.prototype.toString(), dass nur das Bild zurückgegeben wurde: 'url("magic-wand.png")'.

Beachten Sie, dass der zurückgegebene Wert den absoluten Pfad zum Bild enthält – auch dann, wenn der ursprüngliche url()-Wert relativ war. Wäre das Hintergrundbild ein Farbverlauf oder wären mehrere Hintergrundbilder angegeben, würde .get('background-image') ein CSSStyleValue zurückgeben. Ein CSSImageValue wird nur zurückgegeben, wenn genau ein Bild vorhanden ist und dieses Bild als URL angegeben wurde.

Zum Schluss führen wir alles in einem interaktiven Beispiel zusammen. Sehen Sie sich die Ausgabe in der Konsole Ihres Browsers an.

Zusammenfassung

Damit haben Sie eine Grundlage, um das CSS Typed OM zu verstehen. Sehen Sie sich alle Interfaces des CSS Typed OM an, um mehr zu erfahren.

Siehe auch