eduardweb.
UI / UX & CSSIntermediar#dark-mode#css#accessibility#wcag

Dark mode accesibil: dincolo de #000 și contrastul pervers de 21:1

De Cosmin Rotaru, 5 oct. 2026 · 9 vizualizări · 2 like-uri

Postat 5 oct. 2026
css
:root {
  --surface-base: #ffffff;
  --surface-raised: #f4f4f5;
  --text-primary: #18181b;     /* Contrast: ~16:1 */
  --text-muted: #71717a;       /* Contrast: ~4.6:1 (WCAG AA pass) */
  --status-danger: #dc2626;
}

[data-theme="dark"] {
  --surface-base: #121214;
  --surface-raised: #1e1e22;   /* Elevație prin lumină, nu umbră */
  --text-primary: #f4f4f5;     /* Nu folosi #fff pur */
  --text-muted: #a1a1aa;       /* Contrast: ~5.8:1 față de #121214 */
  --status-danger: #f87171;    /* Aceeași alertă, dar desaturată */
}

Mulți developeri cred că dark mode înseamnă să dai un background-color: #000 pe body, să pui textul #fff și să declari tichetul rezolvat. Am făcut și eu mizeria asta acum vreo cinci ani la o platformă B2B cu vreo 14k utilizatori zilnici, până când am început să primim tichete de la oameni din suport care stăteau 8 ore cu ochii în ecran: după o oră de dark mode îi dureau ochii fizic.

Problema se numește halation effect. Când trântești alb pur pe negru pur, rația de contrast ajunge la maximul de 21:1. Pentru un om cu astigmatism ușor (și statistic aproape 40% din populație are o formă de astigmatism), textul ăla pare că vibrează sau că are o aură blurată în jur. WCAG AA cere un contrast minim de 4.5:1 pentru text normal și 3:1 pentru elemente mari sau componente de UI. Nu cere nicăieri 21:1.

Griuri calde și text off-white

Prima regulă de bun-simț: uită de #000000 pentru fundalul principal. Un gri închis neutru spre rece, cum ar fi #121212 sau #18181b (zinc-ul din Tailwind), e infinit mai relaxant pentru retină.

Pentru text, cel mai sigur e să folosești un alb spart. Personal, merg pe o scală de trei nivele de vizibilitate folosind opacități sau culori HEX dedicate:

  • Text primar (titluri, labels critice): #f4f4f5 sau alb cu 90% opacitate (rație în jur de 12:1 față de fundal);
  • Text secundar (metadate, timestamps, descrieri): alb cu 60-70% opacitate (trebuie să rămână peste pragul de 4.5:1);
  • Text disabled sau placeholders: minim 3:1 dacă vrei să fie vizibil legal, deși WCAG e mai permisiv cu controalele inactive.

Ai grijă uriașă la culorile semantice. Roșul de eroare #dc2626 pe care îl folosești pe light mode arată agresiv și e greu de citit pe fundal închis. Pe dark mode trebuie să desaturezi culorile de accent: urcă-le luminozitatea (L-ul din HSL) cu 10-15% și scade-le saturația.

Elevația: adio box-shadow clasic

În light mode, adâncimea unei interfețe e dictată de umbre: dai un drop-shadow difuz pe un card și creierul înțelege că e deasupra paginii. În dark mode, pe un fundal aproape negru, o umbră neagră pur și simplu nu există.

Soluția este să folosești elevație prin iluminare. Principiul de la Material Design funcționează brici aici: cu cât un element e mai sus în axa Z (modale, dropdown-uri, carduri), cu atât fundalul lui devine mai deschis. Cardul tău nu primește umbră, ci un background cu 3-5% mai deschis decât body-ul. Modala devine și mai deschisă.

Trade-off-ul e că te obligă să gândești un sistem strict de tokens semantici (--surface-base, --surface-raised, --surface-overlay). Dacă ai un codebase moștenit unde cineva a aruncat HEX-uri direct în componente, conversia la dark mode te va costa două sprinturi bune doar curățând manual mizeria.

Cum testezi fără să ghicești

Nu te baza pe ochiul tău obosit la 7 seara pe un monitor IPS de 400 de niți. Ce testezi tu arată complet diferit pe ecranul unui laptop ieftin la birou sub neon.

  1. Chrome DevTools are picker cu WCAG integrat: când dai inspect pe un text și deschizi paleta de culoare, îți desenează direct liniile de contrast AA și AAA. E cel mai rapid sanity check pe care îl poți face în 2 secunde.
  2. Axe DevTools sau Pa11y: rulează un audit rapid în pagină. Axe prinde imediat stările de hover sau disabled care pică sub 4.5:1.
  3. Testul de alb-negru: setează rendering-ul din DevTools pe grayscale (Emulate CSS media feature prefers-contrast sau filtre SVG). Dacă interfața își pierde ierarhia când o privești fără culori, înseamnă că te-ai bazat prea mult pe nuanțe și deloc pe contrast de luminozitate.

Voi cum gestionați paleta de dark mode în proiectele mari: tokens semantici construiți de la zero sau vă lăsați la mila temei implicite din Tailwind / Chakra?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.