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

View in English Always switch to English

Verwenden des CSS Typed Object Model

Die CSS Typed Object Model API stellt CSS-Werte als typisierte JavaScript-Objekte zur Verfügung, um deren performante Manipulation zu ermöglichen.

Das Konvertieren von CSS Object Model Wertestrings in sinnvoll typisierte JavaScript-Repräsentationen und zurück (über HTMLElement.style) kann einen erheblichen Performance-Overhead verursachen.

Das CSS Typed OM macht die CSS-Manipulation logischer und leistungsfähiger, indem es Objektfunktionen (anstelle der Manipulation von CSSOM-Strings) bereitstellt, Zugang zu Typen, Methoden und einem Objektmodell für CSS-Werte bietet.

Dieser Artikel bietet eine Einführung in alle seine Hauptmerkmale.

computedStyleMap()

Mit der CSS Typed OM API können wir auf alle CSS-Eigenschaften und -Werte — einschließlich benutzerdefinierter Eigenschaften — zugreifen, die ein Element beeinflussen. Lassen Sie uns sehen, wie dies funktioniert, indem wir unser erstes Beispiel erstellen, das computedStyleMap() erforscht.

Abrufen aller Eigenschaften und Werte

HTML

Wir beginnen mit etwas HTML: einem Absatz mit einem Link sowie einer Definitionsliste, zu der wir alle CSS-Eigenschaften/Werte-Paare hinzufügen werden.

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

JavaScript

Wir fügen JavaScript hinzu, um unseren nicht gestalteten Link zu erfassen und eine Definitionsliste aller Standard-CSS-Eigenschaftenwerte, die den Link beeinflussen, mit computedStyleMap() zurückzugeben.

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, das die Eigenschaft size enthält, die angibt, wie viele Eigenschaften in der Map enthalten sind. Wir iterieren durch die Stilmap, erstellen ein <dt> und <dd> für jede Eigenschaft und jeden Wert.

Ergebnis

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

Haben Sie bemerkt, wie viele Standard-CSS-Eigenschaften ein Link hat? Aktualisieren Sie den ersten document.querySelector-Aufruf, um das <p> statt des <a> auszuwählen. Sie werden einen Unterschied in den Standardwerten von margin-top und margin-bottom feststellen.

.get() Methode / benutzerdefinierte Eigenschaften

Lassen Sie uns unser Beispiel aktualisieren, um nur einige wenige Eigenschaften und Werte abzurufen. Beginnen wir damit, unserem Beispiel etwas CSS hinzuzufügen, einschließlich einer benutzerdefinierten Eigenschaft und einer vererbbaren Eigenschaft:

css
p {
  font-weight: bold;
}

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

Statt alle Eigenschaften zu holen, erstellen wir ein Array von interessierenden Eigenschaften und verwenden die StylePropertyMapReadOnly.get()-Methode, um jeden ihrer Werte zu erhalten:

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 hinzugefügt, um zu demonstrieren, dass, hätten wir alle Eigenschaften eingeschlossen, jeder Wert, der auf currentColor standardmäßig ist (einschließlich caret-color, outline-color, text-decoration-color, column-rule-color, etc.) rgb(255 0 0) zurückgeben würde. Der Link hat font-weight: bold; von den Stilrichtungen des Absatzes geerbt und es wird als font-weight: 700 aufgelistet. Benutzerdefinierte Eigenschaften, wie unser --color: red, sind Eigenschaften. Daher sind sie über get() zugänglich.

Sie werden feststellen, dass benutzerdefinierte Eigenschaften den Wert behalten, wie er im Stylesheet geschrieben ist, während berechnete Stile als der berechnete Wert aufgelistet werden — color wurde als ein rgb() Wert aufgelistet und das zurückgegebene font-weight war 700, obwohl wir eine benannte Farbe und das Schlüsselwort bold verwenden.

CSSUnitValue und CSSKeywordValue

Die Stärke des CSS Typed OM liegt darin, dass Werte von Einheiten getrennt sind; das Parsen und Verkettungen von String-Werten könnte der Vergangenheit angehören. Jede CSS-Eigenschaft in einer Stilmap hat einen Wert. Ist der Wert ein Schlüsselwort, wird ein Objekt des Typs CSSKeywordValue zurückgegeben. Ist der Wert numerisch, wird ein CSSUnitValue zurückgegeben.

CSSKeywordValue ist eine Klasse, die Schlüsselwörter wie inherit, initial, unset und andere nicht zitatpflichtige Strings wie auto und grid definiert. Diese Unterklasse gibt Ihnen eine value-Eigenschaft über cssKeywordValue.value.

CSSUnitValue wird zurückgegeben, wenn der Wert einen Einheitstyp hat. Es ist eine Klasse, die Zahlen mit Maßeinheiten wie 20px, 40%, 200ms oder 7 definiert. Es wird mit zwei Eigenschaften zurückgegeben: einem value und einer unit. Mit diesem Typ können wir auf den numerischen Wert — cssUnitValue.value — und seine Einheit — cssUnitValue.unit zugreifen.

Lassen Sie uns einen einfachen Absatz schreiben, keine Stile anwenden und einige seiner CSS-Eigenschaften untersuchen, indem wir eine Tabelle mit der Einheit und dem Wert zurückgeben:

html
<p>
  This is a paragraph with some content. Open up this example in CodePen or
  JSFiddle, 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 interessierende Eigenschaft listen wir den Namen der Eigenschaft auf, verwenden .get(propertyName).value, um den Wert zurückzugeben, und listen, falls das von get() zurückgegebene Objekt ein CSSUnitValue ist, den Einheitstyp auf, den wir mit .get(propertyName).unit abrufen.

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",
  "animation-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);
}

Für diejenigen, die einen nicht unterstützenden Browser verwenden, sollte die obige Ausgabe in etwa so aussehen:

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

Sie werden bemerken, dass die zurückgegebene <length> Einheit px ist, die zurückgegebene <percentage> Einheit percent, die <time> Einheit s für 'Sekunden' und die einheitslose <number> Einheit number.

Wir haben keine width oder height für den Absatz deklariert, beide standardmäßig auf auto und geben daher ein CSSKeywordValue statt eines CSSUnitValue zurück. CSSKeywordValues haben keine Einheitseigenschaft, daher gibt unsere get().unit undefined zurück.

Wären width oder height in einem <length> oder <percent> definiert gewesen, wäre die CSSUnitValue Einheit px bzw. percent gewesen.

Es gibt weitere verfügbare Typen:

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

CSSStyleValue

Das CSSStyleValue-Interface des CSS Typed Object Model API ist die Basisklasse aller über die Typed OM API zugänglichen CSS-Werte, einschließlich CSSImageValue, CSSKeywordValue, CSSNumericValue, CSSPositionValue, CSSTransformValue, und CSSUnparsedValue.

Es hat zwei Methoden:

Wie oben erwähnt, gibt StylePropertyMapReadOnly.get('--customProperty') ein CSSUnparsedValue zurück. Wir können CSSUnparsedValue-Objektinstanzen mit den vererbten Methoden CSSStyleValue.parse() und CSSStyleValue.parseAll() analysieren.

Lassen Sie uns ein CSS-Beispiel mit mehreren benutzerdefinierten Eigenschaften, Transformationen, calc()s und anderen Merkmalen untersuchen. Wir schauen uns an, welche Typen sie haben, indem wir kurze JavaScript-Snippets einsetzen, die zu console.log() ausgeben:

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);
}

Lassen Sie uns die Klasse zu einem Button hinzufügen (ein Button, der nichts tut).

html
<button>Styled Button</button>

Wir greifen mit dem folgenden JavaScript auf unser StylePropertyMapReadOnly zu:

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

Die folgenden Beispiele beziehen sich auf allComputedStyles:

CSSUnparsedValue

Das 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 eine benutzerdefinierte Eigenschaft des Typs CSSUnparsedValue zurückgegeben. Beachten Sie den Leerraum vor dem 1.2rem. Um Einheit und Wert zu erhalten, benötigen wir ein CSSUnitValue, das wir mit der Methode CSSStyleValue.parse() auf dem CSSUnparsedValue abrufen können.

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 <button>-Element standardmäßig ein Inline-Element ist, haben wir display: inline-block; hinzugefügt, um das Sizing zu ermöglichen. In unserem CSS haben wir width: calc(30% + 20px);, was eine calc()-Funktion ist, um die Breite zu definieren.

Wenn wir get() die width, erhalten wir ein CSSMathSum zurück. CSSMathSum.values ist ein CSSNumericArray mit 2 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

Das display: inline-block; ermöglicht auch die Transformation. In unserem CSS haben wir transform: scale(0.95);, was eine transform-Funktion ist.

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 get() die transform-Eigenschaft erhalten, erhalten wir ein CSSTransformValue. Wir können die Länge (oder Anzahl) der Transformationsfunktionen mit der Eigenschaft length abfragen.

Da wir eine Länge von 1 haben, die eine einzelne Transformationsfunktion darstellt, geben wir das erste Objekt aus und erhalten ein CSSScale-Objekt. Wir bekommen CSSUnitValues, wenn wir die x, y, und z Skalierung abfragen. Die schreibgeschützte Eigenschaft CSSScale.is2D ist in diesem Szenario true.

Hätten wir translate(), skew() und rotate() Transformationsfunktionen hinzugefügt, wäre die Länge 4 gewesen, jede mit ihren eigenen x, y, z Werten und jede mit einer .is2D-Eigenschaft. Zum Beispiel, hätten wir transform: translate3d(1px, 1px, 3px) eingeschlossen, würde .get('transform') eine CSSTranslate mit CSSUnitValues für x, y, und z zurückgeben, und die schreibgeschützte .is2D-Eigenschaft wäre false gewesen.

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 get() das 'background-image', wird ein CSSImageValue zurückgegeben. Obwohl wir die CSS background-Shorthand-Eigenschaft verwendet haben, zeigt die vererbte Object.prototype.toString()-Methode, dass wir nur das Bild zurückgegeben haben, 'url("magic-wand.png")'.

Beachten Sie, dass der zurückgegebene Wert der absolute Pfad zum Bild ist — dies wird zurückgegeben, auch wenn der ursprüngliche url()-Wert relativ war. Wäre das Hintergrundbild ein Farbverlauf oder mehrere Hintergrundbilder gewesen, hätte .get('background-image') ein CSSStyleValue zurückgegeben. Das CSSImageValue wird nur zurückgegeben, wenn es ein einziges Bild gibt und nur, wenn diese einzelne Bilddeklaration eine URL ist.

Schließlich setzen wir all dies in einem Live-Beispiel zusammen. Denken Sie daran, die Konsole Ihres Browsers zu verwenden, um die Ausgabe zu inspizieren.

Zusammenfassung

Dies sollte Ihnen den Einstieg in das Verständnis des CSS Typed OM erleichtern. Schauen Sie sich alle CSS Typed OM Schnittstellen an, um mehr zu erfahren.

Siehe auch