:root {
/* Light Mode */
--bg-base: #ffffff;
--bg-surface: #f8fafc;
--text-main: #0f172a; /* Contrast 19:1 */
--text-muted: #475569; /* Contrast 7.1:1 - Pass AA */
--primary: #0284c7; /* Contrast 4.6:1 - Pass AA */
}
@media (prefers-color-scheme: dark) {
:root {
/* Dark Mode - Fără #000000 pur */
--bg-base: #0f172a;
--bg-surface: #1e293b;
--text-main: #f8fafc; /* Contrast 15.8:1 */
--text-muted: #94a3b8; /* Contrast 6.5:1 - Pass AA */
--primary: #38bdf8; /* Deschis pentru vizibilitate pe închis: 9.3:1 */
}
}Anul trecut am refăcut interfața pentru un dashboard SaaS cu peste 12k utilizatori activi zilnic. Toți cereau Dark Mode pe forumul intern, dar la 48 de ore după lansare ne-am trezit cu zeci de tichete în Jira: ba că textul e obositor, ba că butoanele secundare sunt invizibile. Am învățat pe pielea mea că Dark Mode nu înseamnă un simplu invert() sau fundal #000000 cu text #FFFFFF.
Negru pur (#000000) e inamicul ochilor
Prima greșeală pe care am făcut-o a fost să folosim #000000 pentru fundal și #FFFFFF pentru text. Contrastul rezultat e de 21:1 — maximul posibil. Sună bine teoretic, dar pe un ecran OLED sau chiar pe un IPS ieftin, reflexia textului alb pur pe fundal negru creează un efect numit halation (halou vizual).
Liniile de text par că vibrează, iar după 20 de minute de citit cod sau grafice, te doare capul. Material Design recomandă un fundal de bază #121212, dar mie personal îmi place mai mult o tentă de albastru/slate foarte închis, cum ar fi #0f172a (Slate 900 din Tailwind). Reduce oboseala vizuală și permite suprapunerea de carduri cu umbre sau borduri fine fără să arate totul plat.
Regula WCAG AA: raportul de 4.5:1 nu e opțional
Pentru text normal (sub 18pt sau 24px ne-ingroșat), standardul WCAG AA cere un raport de contrast de minim 4.5:1 față de fundal. Pentru text mare sau elemente de UI (borduri de input, iconițe), limita coboară la 3:1.
Trade-off-ul sincer aici este că un brand albastru închis care arată superb pe fundal alb (de exemplu #0284c7) devine complet ilizibil pe Dark Mode. A trebuit să deschidem nuanța de albastru la #38bdf8 pentru varianta de noapte.
Asta înseamnă că nu poți folosi aceleași culori de brand în ambele teme. Trebuie să ai o paletă duală, unde varianta de dark mode folosește culori mai puțin saturate. Culorile foarte saturate pe fundal închis generează aberații cromatice.
Cum automatizezi testarea de contrast
Să verifici fiecare stare de :hover, :focus sau :disabled cu color picker-ul din Figma e o pierdere absurdă de timp. În proiectul nostru am rezolvat problema pe trei niveluri:
- Chrome DevTools Inspector: Dai Inspect pe element, iar la secțiunea de Color îți arată direct raportul WCAG și dacă trece nivelul AA sau AAA.
- Plugin de Figma (Stark sau Able): Designerii verifică contrastul înainte să trimită token-urile în cod.
- Testare E2E cu Playwright & axe-core: Avem un test automatizat care randează paginile principale în dark mode și eșuează build-ul din CI/CD dacă găsește elemente cu contrast sub 4.5:1.
Cum gestionați voi culorile de brand când treceți aplicația pe Dark Mode? Ajustați nuanțele manual sau folosiți un sistem de derivare automată din CSS?