Kortversionen
- Ett tema med CSS-variabler fungerar bäst i två lager: palettvariabler som rymmer råa färger och semantiska variabler som beskriver vad varje färg är till för.
- Komponenter ska bara läsa semantiska variabler som --color-text eller --color-surface, aldrig palettvärden direkt.
- Mörkt läge blir då en fråga om att peka de semantiska variablerna mot andra palettvärden, under en mediefråga eller ett dataattribut.
- Funktionen light-dark() och egenskapen color-scheme låter en deklaration rymma båda lägena i aktuella webbläsare.
- Ett litet inbäddat skript i head som sätter det sparade temat innan sidan ritas förhindrar blixten av fel tema.
På den här sidan
Ett tema med CSS-variabler är en uppsättning anpassade egenskaper, som --color-surface och --color-text, som varje komponent läser i stället för hårdkodade färger. För att byta tema ändrar du variablerna, oftast på :root eller på ett data-theme-attribut, och hela gränssnittet följer. Knepet som får det att skala är att dela variablerna i två lager: en palett av råa färger och semantiska roller som pekar mot den paletten.
Två lager: palett och roller
Palettvariabler namnges efter vad de är: --violet-600, --ink-900. Semantiska variabler namnges efter vad de gör: --color-accent, --color-text-muted. Komponenter läser bara den andra sorten. När mörkt läge kommer pekar du om rollerna och lämnar varje komponent orörd. Det är samma idé som designtokens, uttryckt direkt i CSS.
--violet-600: #7c3aedVem som läser det
Ändras när
--color-accent: var(--violet-600)Vem som läser det
Ändras när
Exempel
--button-bg: var(--color-accent)Vem som läser det
Ändras när
:root {
/* Palette: raw values, named for what they are */
--paper-50: #faf8f5;
--paper-100: #f1ede6;
--ink-900: #14121f;
--ink-700: #3d3a4f;
--ink-500: #6b6880;
--violet-600: #6d28d9;
--violet-300: #c4b5fd;
--night-950: #0d0b16;
--night-900: #17142a;
--night-800: #221e3a;
/* Roles: what each colour is for (light mode) */
--color-bg: var(--paper-50);
--color-surface: var(--paper-100);
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-border: color-mix(in oklab, var(--ink-900) 12%, transparent);
--color-accent: var(--violet-600);
--color-on-accent: #ffffff;
}
body { background: var(--color-bg); color: var(--color-text); }
.card { background: var(--color-surface); border: 1px solid var(--color-border); }
.button { background: var(--color-accent); color: var(--color-on-accent); }Namnge roller som överlever en omdesign
Ett rollnamn ska fortfarande vara sant när färgerna ändras. --light-grey slutar vara ljus i mörkt läge, och --blue ljuger den dag varumärket blir grönt. Namnge jobbet och paret i stället, så att den som läser stilmallen härnäst vet vilken färg som hör ihop med vilken.
Namn som går sönder
--blue,--purple-button--light-grey-bg--white-text--dark-border
Namn som håller
--color-accent,--color-on-accent--color-surface--color-text--color-border
Lägg till mörkt läge med CSS-variabler
Mörkt läge pekar om rollerna. Respektera operativsystemets inställning som standard och låt ett data-theme-attribut åsidosätta den när läsaren väljer. Sätt också color-scheme, så att rullningslister, formulärkontroller och standardduken matchar.
:root { color-scheme: light; }
/* Follow the system unless the reader picked light */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
color-scheme: dark;
--color-bg: var(--night-950);
--color-surface: var(--night-900);
--color-text: #f2f0fa;
--color-text-muted: #a5a1bd;
--color-border: color-mix(in oklab, #ffffff 12%, transparent);
--color-accent: var(--violet-300);
--color-on-accent: var(--ink-900);
}
}
/* The reader picked dark explicitly */
:root[data-theme="dark"] {
color-scheme: dark;
--color-bg: var(--night-950);
--color-surface: var(--night-900);
--color-text: #f2f0fa;
--color-text-muted: #a5a1bd;
--color-border: color-mix(in oklab, #ffffff 12%, transparent);
--color-accent: var(--violet-300);
--color-on-accent: var(--ink-900);
}light-dark() tar bort upprepningen.Mörkt läge är inte ett inverterat ljust läge. Ytor blir ljusare ju högre de ligger, accenter ljusnar och skuggor viker för kantlinjer. Design för mörkt läge och gradienter för mörkt läge tar upp den visuella sidan.
Genvägen light-dark()
Aktuella webbläsare stöder light-dark(), som tar ett ljust värde och ett mörkt värde och väljer ett utifrån elementets color-scheme. Sätt color-scheme: light dark på roten för att följa systemet, eller tvinga ett med attributet, så blir varje roll en enda rad: --color-bg: light-dark(var(--paper-50), var(--night-950)). Behåll den längre formen om du måste stödja webbläsare från före 2024.
En temaväxlare som inte blinkar
Om det sparade valet tillämpas efter att sidan ritats ser läsare som valt mörkt en vit blixt vid varje laddning. Sätt attributet i ett pyttelitet inbäddat skript i head, innan någon stilmall målar kroppen.
<head>
<script>
(function () {
var saved = localStorage.getItem("theme");
if (saved === "light" || saved === "dark") {
document.documentElement.dataset.theme = saved;
}
})();
</script>
<link rel="stylesheet" href="/styles.css">
</head>dataset.theme och spara värdet i localStorage.- 1
Erbjud tre val
Ljust, mörkt och system. Att ta bort attributet ger kontrollen tillbaka till
prefers-color-scheme. - 2
Spara bara uttryckliga val
Lagra
lightellerdark; ta bort nyckeln för system, så att en senare ändring i operativsystemet respekteras. - 3
Undvik övergångar vid laddning
Om färger har övergångar, aktivera övergången först efter första ritningen, annars animeras sidan från ljus till mörk medan den laddas.
Varumärkesteman bortom ljust och mörkt
Samma två lager hanterar flera varumärken i en kodbas. Varje varumärke ger sina egna palett- och rollvärden under ett data-brand-attribut, och lägena fungerar fortfarande ovanpå. Med color-mix() kan du härleda hovringslägen och toner från en accent per varumärke, som visas i color-mix() i CSS.
[data-brand="harbour"] {
--color-accent: #0f766e;
--gradient-hero: linear-gradient(150deg, #042f2e 0%, #0f766e 55%, #5eead4 100%);
}
[data-brand="ember"] {
--color-accent: #c2410c;
--gradient-hero: linear-gradient(150deg, #431407 0%, #c2410c 55%, #fdba74 100%);
}
.button:hover { background: color-mix(in oklab, var(--color-accent), black 12%); }
.hero { background: var(--gradient-hero); }Eftersom anpassade egenskaper ärvs behöver ett tema inte täcka hela sidan. Lägg data-theme="dark" på en sektion, som ett kampanjband eller en sidfot, så läser allt inuti den de mörka rollerna medan resten av sidan förblir ljus. Skriv den mörka väljaren som [data-theme="dark"] i stället för :root[data-theme="dark"] om du vill att det ska fungera, och sätt color-scheme på sektionen också.
Håll webben och dina designer på en palett
Ett tema i CSS är bara halva ett varumärke. Samma färger ska finnas i dina sociala inlägg, presentationer och e-postmeddelanden. Gradiently varumärkeskit rymmer dina paletter, logotyper och rubrik- och brödtypsnitt, och Designer tillämpar det när den lägger ut en design, så att inlägget du gör på måndagen använder samma accent som din webbplats. Om du fortfarande väljer färgerna, börja med hur du väljer varumärkesfärger.
Vanliga frågor
Hur gör jag ett tema med CSS-variabler?
Definiera palettvariabler med råa färger och sedan semantiska variabler som --color-bg som pekar mot dem. Komponenter läser bara de semantiska, och teman pekar om dem.
Hur lägger jag till mörkt läge med CSS-variabler?
Åsidosätt de semantiska variablerna inuti @media (prefers-color-scheme: dark) och under en [data-theme="dark"]-väljare för läsare som väljer det.
Hur stoppar jag att temat blinkar vid sidladdning?
Läs det sparade temat i ett litet inbäddat skript i head och sätt attributet innan stilmallen ritar sidan.
Vad gör light-dark() i CSS?
Den returnerar sitt första värde i ljust läge och sitt andra i mörkt läge, utifrån elementets color-scheme. Den fungerar i aktuella större webbläsare.
Kan jag lagra en gradient i en CSS-variabel?
Ja. Lagra hela gradienten som värde och använd den i background. För att animera mellan gradienter, registrera stoppen med @property.
Skriven av Gradiently
Teamet bakom Gradiently, ett designverktyg byggt kring Marks: levande gradienter som får allt du gör att kännas som ditt.
Se vår profil