Kortversjonen
- Et tema med CSS-variabler fungerer best i to lag: palettvariabler med råfarger og semantiske variabler som beskriver hva hver farge brukes til.
- Komponenter bør bare lese semantiske variabler som --color-text eller --color-surface, aldri palettverdier direkte.
- Mørk modus handler da om å peke de semantiske variablene mot andre palettverdier, i en mediespørring eller et dataattributt.
- Funksjonen light-dark() og egenskapen color-scheme lar én deklarasjon romme begge moduser i nåværende nettlesere.
- Et lite innebygd skript i head som setter det lagrede temaet før siden tegnes, hindrer et blink av feil tema.
På denne siden
Et tema med CSS-variabler er et sett egendefinerte egenskaper, som --color-surface og --color-text, som alle komponenter leser fremfor hardkodede farger. For å endre temaet endrer du variablene, vanligvis på :root eller et data-theme-attributt, og hele grensesnittet følger. Grepet som gjør dette skalerbart, er å dele variablene i to lag: en palett med råfarger og semantiske roller som peker på den.
To lag: palett og roller
Palettvariabler navngis etter hva de er: --violet-600, --ink-900. Semantiske variabler navngis etter hva de gjør: --color-accent, --color-text-muted. Komponenter leser bare den andre typen. Når mørk modus kommer, kobler du om rollene og lar komponentene være urørt. Det er samme idé som designtokens, uttrykt direkte i CSS.
--violet-600: #7c3aedHvem leser det
Endres når
--color-accent: var(--violet-600)Hvem leser det
Endres når
Eksempel
--button-bg: var(--color-accent)Hvem leser det
Endres 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); }Rollenavn som tåler nytt design
Et rollenavn bør fortsatt være sant etter at fargene endres. --light-grey slutter å være lys i mørk modus, og --blue lyver den dagen merkevaren blir grønn. Navngi heller oppgaven og fargeparet, så neste person som leser stilarket, vet hvilken farge som skal på hvilken.
Navn som svikter
--blue,--purple-button--light-grey-bg--white-text--dark-border
Navn som varer
--color-accent,--color-on-accent--color-surface--color-text--color-border
Legg til mørk modus med CSS-variabler
Mørk modus kobler om rollene. Respekter operativsystemets innstilling som standard, og la et data-theme-attributt overstyre når leseren velger. Sett også color-scheme, så rullefelt, skjemakontroller og standardlerretet passer.
: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() fjerner gjentakelsen.Mørk modus er ikke invertert lys modus. Flater blir lysere jo høyere de ligger, aksenter lysner, og skygger erstattes av kanter. Design for mørk modus og gradienter for mørk modus dekker det visuelle.
Snarveien light-dark()
Nåværende nettlesere støtter light-dark(), som tar en lys og en mørk verdi og velger ut fra elementets color-scheme. Sett color-scheme: light dark på rotelementet for å følge systemet, eller tving én modus med attributtet. Hver rolle blir da én linje: --color-bg: light-dark(var(--paper-50), var(--night-950)). Behold den lengre formen hvis du må støtte nettlesere fra før 2024.
En temabryter som ikke blinker
Hvis det lagrede valget brukes etter at siden er rendret, ser lesere som valgte mørkt, et hvitt blink ved hver lasting. Sett attributtet i et lite innebygd skript i head, før noe stilark tegner innholdet.
<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 og lagre verdien i localStorage.- 1
Tilby tre valg
Lyst, mørkt og system. Fjerner du attributtet, får
prefers-color-schemekontrollen tilbake. - 2
Lagre bare eksplisitte valg
Lagre
lightellerdark. Slett nøkkelen for system, så en senere endring i operativsystemet respekteres. - 3
Unngå overganger ved lasting
Hvis farger har overganger, aktiver dem først etter første tegning. Ellers animeres siden fra lyst til mørkt under lasting.
Merkevaretemaer utover lyst og mørkt
De samme to lagene håndterer flere merkevarer i én kodebase. Hver merkevare gir sin egen palett og rolleverdier under et data-brand-attributt, og modusene fungerer fortsatt oppå. Med color-mix() kan du avlede pekertilstander og lyse nyanser fra én aksent per merkevare, som vist 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); }Fordi egendefinerte egenskaper arves, trenger ikke et tema å dekke hele siden. Sett data-theme="dark" på én seksjon, som et kampanjefelt eller en bunntekst. Alt inni leser de mørke rollene, mens resten av siden er lys. Skriv den mørke selektoren som [data-theme="dark"] fremfor :root[data-theme="dark"] hvis du vil at dette skal virke, og sett også color-scheme på seksjonen.
Hold nettsiden og designene på én palett
Et tema i CSS er bare halve merkevaren. Samme farger bør vises i sosiale innlegg, presentasjoner og e-poster. Merkevarepakken i Gradiently rommer paletter, logoer og overskrifts- og brødtekstskrifter. Designer bruker den når et design settes opp, så innlegget du lager mandag, får samme aksent som nettsiden. Hvis du fortsatt velger farger, start med slik velger du merkevarefarger.
Spørsmål folk stiller
Hvordan lager jeg et tema med CSS-variabler?
Definer palettvariabler med råfarger og deretter semantiske variabler som --color-bg som peker på dem. Komponenter leser bare de semantiske, og temaer kobler dem om.
Hvordan legger jeg til mørk modus med CSS-variabler?
Overstyr de semantiske variablene inni @media (prefers-color-scheme: dark) og under en [data-theme="dark"]-selektor for lesere som velger det.
Hvordan hindrer jeg at temaet blinker ved sidelasting?
Les det lagrede temaet i et lite innebygd skript i head og sett attributtet før stilarket tegner siden.
Hva gjør light-dark() i CSS?
Den returnerer første verdi i lys modus og andre i mørk modus, basert på elementets color-scheme. Den virker i nåværende store nettlesere.
Kan jeg lagre en gradient i en CSS-variabel?
Ja. Lagre hele gradienten som verdi og bruk den i background. For å animere mellom gradienter registrerer du stoppene med @property.
Skrevet av Gradiently
Teamet bak Gradiently, et designverktøy bygget rundt Marks: levende gradienter som gjør at alt du designer ser ut som ditt.
Se profilen vår