Signatur
Beschreibung
Mit der CSS-Regel @function (Spezifikation „CSS Mixins and Functions“) lassen sich eigene CSS-Funktionen definieren, etwa @function --double(--x) { result: calc(var(--x) * 2); }. Im CSSOM wird eine solche Regel als CSSFunctionRule dargestellt. Jeder zusammenhängende Block von Deklarationen in ihrem Körper erscheint in CSSFunctionRule.cssRules als eigenes CSSFunctionDeclarations-Objekt.
Die Eigenschaft style gibt die Deklarationen dieses Blocks als CSSFunctionDescriptors-Objekt zurück. Diese Schnittstelle erweitert CSSStyleDeclaration. Der Deskriptor result steht als eigene Eigenschaft bereit. Lokale Custom Properties wie --tmp liest du mit getPropertyValue() aus.
Die Eigenschaft ist nützlich für DevTools, Linter, Polyfills oder Analysewerkzeuge, die Funktionsdefinitionen zur Laufzeit untersuchen wollen. Schreibgeschützt ist nur die Referenz auf das Objekt. Du kannst style also kein anderes Objekt zuweisen.
Steht der Körper in bedingten Regeln wie @media oder @supports, liegen die zugehörigen CSSFunctionDeclarations verschachtelt in deren cssRules. Wer alle Deklarationen finden will, muss den Regelbaum also rekursiv durchlaufen.
Rückgabewert
CSSFunctionDescriptors-Objekt (Unterklasse von CSSStyleDeclaration) mit den Deklarationen dieses Blocks. Es enthält den Deskriptor result und lokale Custom Properties.Beispiele
Den result-Deskriptor einer @function auslesen
// Funktioniert nur in Browsern mit @function-Unterstützung
const styleEl = document.createElement('style');
styleEl.textContent = `
@function --double(--x) {
result: calc(var(--x) * 2);
}
`;
document.head.append(styleEl);
const sheet = styleEl.sheet;
const fnRule = [...sheet.cssRules].find(
(r) => typeof CSSFunctionRule !== 'undefined' && r instanceof CSSFunctionRule
);
if (fnRule) {
const decls = fnRule.cssRules[0]; // CSSFunctionDeclarations
console.log(fnRule.name);
console.log(decls.style.result);
} else {
console.log('@function wird nicht unterstützt');
}
Lokale Custom Properties im Funktionskörper lesen
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
@function --spacing(--factor) {
--base: 8px;
result: calc(var(--base) * var(--factor));
}
`);
const [fnRule] = sheet.cssRules;
const { style } = fnRule.cssRules[0];
console.log(style.getPropertyValue('--base').trim());
console.log(style.result);
console.log(style.length); // Anzahl der Deklarationen
Alle Deklarationsblöcke rekursiv sammeln (auch in @media)
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
@function --gap() {
result: 8px;
@media (min-width: 800px) {
result: 16px;
}
}
`);
const collect = (rules, out = []) => {
for (const rule of rules) {
if (rule instanceof CSSFunctionDeclarations) {
out.push(rule.style.result);
} else if (rule.cssRules) {
collect(rule.cssRules, out);
}
}
return out;
};
console.log(collect(sheet.cssRules[0].cssRules));
// Wichtig · Fallstricke
- Experimentell:
@function,CSSFunctionRule,CSSFunctionDeclarationsundCSSFunctionDescriptorsgibt es derzeit nur in Chromium-basierten Browsern (ab etwa Version 139). Prüfe vorher, ob die Funktion verfügbar ist, z. B. mittypeof CSSFunctionRule !== 'undefined'. Nicht unterstützende Browser verwerfen die Regel beim Parsen, sie taucht dann gar nicht incssRulesauf. - Schreibgeschützt:
decls.style = …hat keine Wirkung und wirft im Strict Mode einen Fehler. Geschützt ist aber nur die Objekt-Referenz, nicht der Inhalt des Objekts. - Nur
resultund Custom Properties (--*) sind im Funktionskörper gültig. Normale CSS-Eigenschaften wiecolorwerden verworfen und erscheinen nicht instyle. - Die Werte werden in serialisierter Form zurückgegeben. Leerzeichen und Schreibweise können daher vom Quelltext abweichen, z. B. führende Leerzeichen bei Custom Properties. Nutze bei Bedarf
trim(). - Bedingte Blöcke (
@media,@supports,@container) erzeugen verschachtelte Regeln.fnRule.cssRules[0]allein erfasst also nicht immer alle Deklarationen.