Miroslav Holec
Premium

Jak si rychle vytvořit dark mode webu

Miroslav Holec   24. července 2024

Před pár dny jsem dostal zpětnou vazbu k mému Premium a k webu. Součástí byl i zajímavý podnět, že by nebylo špatné přidat do Premium účtu dark mode (tedy tmavý režim). U videa to pochopitelně už nezměním, protože je natočené ve světlém schématu, ale změnit barvy na webu kupodivu tak složité není.

Pro lepší demonstraci jsem celý tento článek utopil do tmavého režimu

Proč používat dark mode

Objektivně neexistuje žádný vědecky smysluplný důvod, proč by byl dark mode lepší než světlý mód. Dark mode ušetří trochu baterie na telefonu, ale vzhledem ke krátké návštěvě webu to moc velký význam nemá. Navíc se tato úspora se týká především OLED a AMOLED displejů. V případě LCD displejů "svítí" i černé pixely a tudíž je úspora baterie mizivá.

Co se týče kvality spánku, pět nezávislých studií neprokázalo vliv modrého světla na spánek a to v celé řadě kontextů, včetně porovnání četby z iPadu a klasické knihy. Jedna studie (vzhledem k ostatním rozsáhlá co to počtu účastníků) dokonce došla k závěru, že expozice bílému světlu obohacenému o modrou barvu během denní pracovní doby zlepšuje subjektivní bdělost, výkonnost a večerní únavu. Kvalitní spánek si lze nicméně zajistit tím, že před ulehnutím nebudeme koukat na žádné obrazovky bez ohledu na to, co z nich svítí.

V zásadě tak jediný důvod zůstává šetrnost k očím při sledování a čtení ve tmě. Tmavému módu se někteří vývojáři (jako já) záměrně vyhýbají. Tmavý mód nevypadá dobře a text se špatně čte.

Přesto jsem se rozhodl dark mode experimentálně přidat.

Instantní technické řešení

Standardní řešení je zkrátka o tom, že efektivním způsobem vytvoříme dodatečné CSS, které změní "kabátek" webu do jiných barev. Tím efektivním způsobem bývá zpravidla použití proměnných. Samotná realizace pak bývá kombinace přepínacího tlačítka a uložení předvolby do cookie.

Já jsem chtěl jít minimalistickou cestou, kterou zvládnu naprogramovat za 60 minut a poté v případě úspěchu vymyslím něco více "cool". Protože mám v DB tabulku s uživateli, tak pro začátek umožňuji nastavit dark mode jen přihlášeným uživatelům. Mám tedy jednoduchý formulář v Blazoru:

image-20240723115716327

Při renderování webu už jen zbývá zjistit, zda je uživatel přihlášený a má zapnutý dark mode. Pokud ano, vygeneruji do HTML dodatečné CSS styly, které web utopí do tmy.

@if (IsDarkMode)
{
    <style>
    </style>
}

CSS styly

Abych ušetřil čas, hledal jsem něco, co bude maximálně rychlé. A našel jsem to. V CSS existují filtry, které umí na HTML elementy aplikovat různé grafické efekty. Já jsem pro mé účely použil dva z nich:

Krok 1: invert(100%)

V první řadě jsem použil filter s nastavením invert(1) nebo také jinak invert(100%).

html {filter: invert(100%);}

Toto nastavení invertuje barvy. Výsledek není moc dokonalý, protože se tím otočí barvy i u obrázků a iframes (např. videa). Zároveň samotné barvy vypadají divně:

image-20240723120413373

Krok 2: další invert(100%)

Proto jsem udělal další invert na těch elementech, kde jsem se chtěl vrátit k původním barvám. Jsou to typicky právě obrázky a iframes.

html img, html iframe {filter: invert(100%);}

image-20240723120639012

Krok 3: hue-rotate()

Abych nakonec vylepšil barvy, které po inverzi vypadají divně, použil jsem funkci hue-rotate(), kterou aplikuji před inverzí. Touto funkcí dochází k rotaci barevného odstínu daného HTML prvku (u mě celého webu). Uvádí se ve stupních a já jsem postupným otáčením dospěl k nastavení 210 stupňů. Obě funkce jsem pak uvedl společně s inverzí barev. I zde platí, že jsem musel kolečkem u obrázků a iframes pootočit zpátky.

html {filter: hue-rotate(210deg) invert(1);}
html img, html iframe {filter: hue-rotate(-210deg) invert(1);}

image-20240723121203686

Zbytek už byl jen ladění drobností. Došel jsem například k následujícímu:

  • malé kontrasty jsem musel více zvýraznit, protože například #FFF a #DDD)nejsou v dark mode vidět
  • u odkazů jsem musel ručně změnit barvu
  • u obrázků jsem všude udělal kulaté barvy, protože vypadaly světlé divně
  • v patičce jsem některé prvky udělal černobíle filtrem grayscale(100%)
  • nakonec jsem si udělal CSS třídu .dm-inv, kterou inverzi ruším, protože někde to vypadalo blbě

Závěr

Vytvořit jednodušší podobu tmavého módu není složité. Nese to ale s sebou řadu důsledků. Mnoho obrázků s bílým pozadím vypadá v tmavém schématu špatně a ty s transparentním snad ještě hůře. Malé kontrasty viditelné ve světlém módu se v tmavém režimu ztrácí. Dle paretova principu jsem za krátký čas dosáhl 80% výsledků. Těch zbývajících 20% už by ale vyžadovalo cílenější práci, která by už nepřinesla mnoho ovoce. Máte-li Premium, můžete si změni vyzkoušet v sekci Můj účet.