Een CSS-variabele op een onderliggend element overschrijven bouwt geen samengestelde aangepaste eigenschap opnieuw op die van het bovenliggende element is overgeërfd. Het bovenliggende element heeft de geneste verwijzing al opgelost. Als je de waarde van het onderliggende element wilt gebruiken, declareer je de samengestelde eigenschap op dat element of stel je daar de uiteindelijke eigenschap samen.
Deze handleiding legt dit gedrag uit en beschrijft een reproduceerbare desktopoefening in Chrome op een Mac. De opdracht is om de rand van een component de lokale kleuroverschrijving te laten volgen, terwijl de gedeelde standaardwaarden behouden blijven.
Waarom behoudt de overgeërfde samengestelde waarde de kleur van het bovenliggende element?
Bekijk dit CSS-fragment. Het gaat ervan uit dat een element .sample-tile binnen een element .sample-board staat:
.sample-board {
--sample-color: teal;
--sample-border: 6px solid var(--sample-color);
}
.sample-tile {
--sample-color: darkorange;
border: var(--sample-border);
}
De rand van het onderliggende element blijft turkoois. Volgens de CSS Variables-specificatie worden de geneste functies var() in aangepaste eigenschappen opgelost op het moment dat de berekende waarde wordt bepaald, vóór overerving. Het onderliggende element erft daardoor een samengestelde waarde die overeenkomt met 6px solid teal; het erft geen expressie die --sample-color van het onderliggende element zal invullen. CSS Custom Properties for Cascading Variables Module Level 1.
Hier zijn twee afzonderlijke eigenschappen. Als je --sample-color op het onderliggende element instelt, verandert de lokale waarde van die eigenschap. Daarmee declareer je niet ook een nieuwe waarde voor --sample-border. In de verwijzing naar aangepaste eigenschappen van MDN staat dat gewone, niet-geregistreerde aangepaste eigenschappen worden geërfd en berekende waarden hebben waarin de variabelen zijn ingevuld. Aangepaste eigenschappen: CSS-variabelen.
De volgorde in dit voorbeeld is:
- Het bovenliggende element berekent
--sample-coloralsteal. - De waarde van
--sample-borderwordt ingevuld met die kleur, wat6px solid tealoplevert. - Het onderliggende element erft die samengestelde waarde en stelt daarnaast zijn eigen kleurtoken in op
darkorange. - De declaratie
bordervan het onderliggende element gebruikt de overgeërfde samengestelde waarde met turkooizen kleur.
Dit is geen permanente momentopname van het bovenliggende element. Als de kleur van het bovenliggende element verandert, kan de samengestelde waarde worden bijgewerkt en opnieuw worden geërfd. De grens ligt bij het element waarop de geneste verwijzing wordt opgelost: een overschrijving op een afstammeling werkt niet door naar die berekening erboven. CSS Variables: afhankelijkheden oplossen.
Reproduceer het gedrag in Chrome op een Mac
Gebruik een lege pagina, zodat bestaande paginastijlen niet in de weg zitten. Open een nieuw Chrome-tabblad, typ about:blank in de adresbalk en druk vervolgens op Command + Option + J om de Console te openen. Google beschrijft deze Mac-sneltoets in de DevTools-handleiding. Chrome DevTools openen.
Het volgende volledige programma voor de browserconsole maakt drie benoemde abstracte vormen en hun stylesheet. Het heeft geen bibliotheken, afbeeldingen, netwerkverzoeken of bestaande pagina-elementen nodig. Voer het hele blok één keer uit op de lege pagina. De verwachte resultaten hieronder zijn afgeleid van de gedocumenteerde CSS-regels; ze worden niet gepresenteerd als metingen die in een browser zijn vastgelegd.
(() => {
const board = document.createElement("section");
board.className = "sample-board";
const style = document.createElement("style");
style.textContent = `
.sample-board {
--sample-color: teal;
--sample-border: 6px solid var(--sample-color);
display: flex;
flex-wrap: wrap;
gap: 24px;
padding: 32px;
font: 16px system-ui;
}
.sample-board .sample-tile {
--sample-color: darkorange;
display: grid;
place-items: center;
width: 120px;
height: 80px;
border: var(--sample-border);
border-radius: 24px;
background: white;
color: black;
}
.sample-board .sample-local {
--sample-border: 6px solid var(--sample-color);
}
.sample-board .sample-direct {
border: 6px solid var(--sample-color);
}
`;
const samples = [
["Inherited", "sample-inherited"],
["Local", "sample-local"],
["Direct", "sample-direct"]
];
const tiles = samples.map(([label, className]) => {
const tile = document.createElement("div");
tile.className = `sample-tile ${className}`;
tile.textContent = label;
board.append(tile);
return tile;
});
document.head.append(style);
document.body.append(board);
function report(stage) {
console.log(stage);
console.table(tiles.map((tile) => {
const computed = getComputedStyle(tile);
return {
sample: tile.textContent,
localColor: computed
.getPropertyValue("--sample-color").trim(),
composite: computed
.getPropertyValue("--sample-border").trim(),
paintedBorder: computed.borderTopColor
};
}));
}
report("Initial values");
board.style.setProperty("--sample-color", "rebeccapurple");
report("After changing the parent color");
})();
Het programma toont twee tabellen. De verwachte randkleuren zijn:
| Voorbeeld | Aanvankelijk | Na wijziging van het bovenliggende element | Reden |
|---|---|---|---|
Inherited |
Turkoois | Paars | Gebruikt de berekende samengestelde waarde van het bovenliggende element |
Local |
Oranje | Oranje | Declareert de samengestelde waarde op het onderliggende element |
Direct |
Oranje | Oranje | Vult de lokale kleur rechtstreeks in border in |
Alle drie de onderliggende elementen behouden darkorange als hun lokale kleurtoken. Het voorbeeld Direct is hier de nuttige diagnostiek: de overgeërfde samengestelde waarde bevat nog steeds de kleur van het bovenliggende element, maar de weergegeven rand gebruikt het lokale token, omdat de declaratie voor die rand de samengestelde waarde niet gebruikt.
getComputedStyle() leest opgeloste eigenschapswaarden nadat actieve stylesheets zijn toegepast. Daarmee kun je dus zien wat een element daadwerkelijk krijgt, in plaats van alleen de geschreven expressie. Een kleur kan worden geserialiseerd als een waarde van het type rgb() in plaats van als de oorspronkelijke kleurnaam. Window: de methode getComputedStyle().
Laad het lege tabblad opnieuw om de oefening te wissen. Plaats de gekozen CSS-oplossing in het stylesheet van een pagina die je zelf hebt gemaakt; wijzigingen in de console zijn handig voor diagnose, maar passen je bronbestanden niet aan.
Welke oplossing kies je?
Declareer de samengestelde waarde op de componentgrens
Het voorbeeld Local behoudt het herbruikbare randtoken en declareert het recept op hetzelfde element dat de overschrijving levert. Hier staat het relevante CSS-fragment uit het programma:
.sample-board .sample-local {
--sample-color: darkorange;
--sample-border: 6px solid var(--sample-color);
border: var(--sample-border);
}
Kies dit patroon als meerdere declaraties dezelfde samengestelde waarde nodig hebben. Plaats de primitieve standaardwaarden op een bovenliggend element en de declaratie van de samengestelde waarde op de component die de aanpassing beheert. Aangepaste eigenschappen kunnen op specifieke elementen worden gedeclareerd en worden geërfd door hun afstammelingen; ze hoeven niet op :root te staan. CSS-aangepaste eigenschappen gebruiken.
De plaatsing blijft verderop in de boomstructuur van belang. Als een kleinkind de primitieve waarde opnieuw overschrijft, weerspiegelt een overgeërfde samengestelde waarde van deze component nog steeds de berekening van de component. Declareer het recept opnieuw op elke grens van een afstammeling waar een ander resultaat moet worden samengesteld.
Stel de uiteindelijke eigenschap samen op de plek waar die wordt gebruikt
Het voorbeeld Direct verwijdert het tussenliggende token uit de randdeclaratie. Dit CSS-fragment is de essentiële regel:
.sample-board .sample-direct {
--sample-color: darkorange;
border: 6px solid var(--sample-color);
}
Kies dit wanneer maar één declaratie de combinatie nodig heeft. Je kunt de afzonderlijke tokens voor breedte, stijl en kleur nog steeds delen en ze vervolgens samenvoegen in de declaratie border van de component. MDN beschrijft dat var() de volledige waarde van een andere eigenschap of een deel ervan kan invullen. CSS-aangepaste eigenschappen gebruiken.
Overschrijf de volledige samengestelde waarde als dat de openbare insteloptie is
Soms is het de bedoeling dat de volledige rand van de component aanpasbaar is. Geef in dat geval een lokale vervanging voor --sample-border, zoals 6px solid darkorange, in plaats van alleen de eerdere invoer ervan te wijzigen.
Gebruik deze besliswijzer bij het kiezen van het componentcontract:
| Gewenste aanpassing | Geschikt patroon |
|---|---|
| Eén lokale kleur bepaalt één rand | Stel rechtstreeks samen in border |
| Meerdere declaraties delen één samengestelde waarde | Declareer de samengestelde waarde op de component |
| Een aanroeper levert de volledige rand aan | Overschrijf de samengestelde waarde zelf |
| Afstammelingen moeten precies de samengestelde waarde van het bovenliggende element gebruiken | Behoud de overgeërfde samengestelde waarde |
Waarom stellen specificiteit, een terugvalwaarde of overervingssleutelwoorden de waarde niet opnieuw samen?
Controleer eerst of de overschrijving van de primitieve waarde daadwerkelijk is toegepast. Als de opgeloste --sample-color van het onderliggende element al darkorange is, verandert het specifieker maken van diezelfde declaratie niets aan de afzonderlijke overgeërfde --sample-border. Beide eigenschappen hebben al een waarde; het probleem is waar de samengestelde waarde is samengesteld.
Evenzo neemt --sample-border: inherit de berekende waarde van het bovenliggende element over. Bij gewone overerving worden berekende waarden overgedragen; de geschreven declaratie van het bovenliggende element wordt niet opnieuw uitgevoerd in de context van het onderliggende element. Overerving.
Een terugvalwaarde zoals var(--sample-border, 6px solid darkorange) laat een geldige overgeërfde turkooizen rand ook ongemoeid. Een terugvalwaarde voor var() wordt gebruikt als een aangepaste eigenschap geen bruikbare waarde heeft; hiermee wordt de waarde niet vergeleken met de gewenste invoer van een afstammeling. CSS-functie var().
Houd ongeldige waarden gescheiden van dit overervingsprobleem. Een niet-geregistreerd token met 12px kan bijvoorbeeld als waarde voor een aangepaste eigenschap bestaan, maar een ongeldig resultaat opleveren wanneer het wordt ingevuld in border-color. De terugvalwaarde binnen die aanroep van var() is geen algemeen alternatief voor typecontrole. MDN legt uit waarom het invullen van aangepaste eigenschappen declaraties kan opleveren die op het moment dat de berekende waarde wordt bepaald ongeldig worden. CSS-aangepaste eigenschappen gebruiken.
Lost het registreren van de variabele met @property dit op?
Met @property kun je de syntaxis, beginwaarde en overervingsinstelling van een aangepaste eigenschap opgeven. Hierdoor wordt een samengestelde waarde van een bovenliggend element niet opnieuw geëvalueerd op basis van invoerwaarden die op een onderliggend element zijn overschreven. Als je de primitieve eigenschap registreert met inherits: false, verandert dat hoe die primitieve waarde wordt verkregen; als je de samengestelde eigenschap op die manier registreert, stopt de normale overerving ervan. Geen van beide levert het ontbrekende lokale recept. CSS-at-regel @property.
Registratie heeft ook een andere compatibiliteitsgrens. Volgens MDN worden gewone aangepaste eigenschappen sinds april 2017 breed ondersteund in browsers, terwijl @property in juli 2024 Baseline-beschikbaarheid bereikte en mogelijk niet beschikbaar is in oudere browsers. Voor de twee getoonde oplossingen is registratie niet nodig. Aangepaste eigenschappen: CSS-variabelen, CSS-at-regel @property.
Hoe spoor je hetzelfde probleem op in je stylesheet?
Gebruik de vergelijking met drie kolommen uit de oefening voor het element waarvan het uiterlijk niet klopt:
- Lees het primitieve token uit, zoals
--sample-color. - Lees het samengestelde token uit, zoals
--sample-border. - Lees de weergegeven eigenschap uit, zoals
border-top-color. - Zoek het element waarop de declaratie van de samengestelde waarde van toepassing is.
- Verplaats die declaratie naar de beoogde aanpassingsgrens of herhaal haar daar, of stel de uiteindelijke eigenschap rechtstreeks samen.
Als je de relevante regels in Chrome wilt vinden, klik je met de rechtermuisknop op de vorm en kies je Inspect. DevTools selecteert het element in Elements, en het tabblad Styles toont de toegepaste CSS-regels. Chrome DevTools openen.
Als de primitieve waarde de gewenste lokale waarde toont, maar de samengestelde waarde nog steeds de waarde van een bovenliggend element bevat, controleer dan eerst waar de samengestelde waarde wordt gedeclareerd. Definieer het recept waar de invoerwaarden moeten worden gelezen en controleer vervolgens zowel het opgeloste token als het weergegeven resultaat. Zo krijgt de component een duidelijke, voorspelbare aanpassingsgrens.
Bronnen
- CSS Custom Properties for Cascading Variables Module Level 1 — W3C.
- Aangepaste eigenschappen (--*): CSS-variabelen — MDN Web Docs.
- CSS-aangepaste eigenschappen (variabelen) gebruiken — MDN Web Docs.
- Overerving — MDN Web Docs.
- CSS-functie var() — MDN Web Docs.
- CSS-at-regel @property — MDN Web Docs.
- Window: de methode getComputedStyle() — MDN Web Docs.
- Chrome DevTools openen — Chrome for Developers.