Model kolorów HSL
(barwa, nasycenie, jasność) daje deweloperom znacznie bardziej czytelny sposób pracy z kolorami w CSS niż RGB. Zamiast zgadywać, która kombinacja wartości czerwonego, zielonego i niebieskiego da pożądany odcień, HSL pozwala opisywać kolory tak, jak myśli o nich ludzki mózg: wybierasz kolor, decydujesz jak bardzo ma być żywy, a potem jak jasny lub ciemny. To właśnie ta zmiana podejścia sprawia, że coraz więcej deweloperów porzuca
rgb()
na rzecz
hsl()
.
Spis treści
RGB vs HSL - Podstawowa różnica
RGB definiuje kolor przez mieszanie trzech kanałów świetlnych: czerwonego, zielonego i niebieskiego, każdego w skali od 0 do 255. Problem polega na tym, że to sposób, w jaki ekrany renderują piksele, a nie sposób, w jaki ludzie postrzegają kolory. Jeśli chcesz uzyskać nieco jaśniejszy niebieski w RGB, musisz zwiększyć wszystkie trzy kanały w odpowiednich proporcjach - nie ma jednego prostego parametru do przestawienia.
HSL odwzorowuje to, jak ludzie opisują kolory w codziennej rozmowie:
- Barwa (Hue) - właściwy kolor, wyrażony jako stopień na kole barw o pełnym obrocie 360 stopni. Czerwony to 0, zielony to 120, niebieski to 240.
- Nasycenie (Saturation) - jak żywy lub wyblakły jest kolor, od 0% (czysty szary) do 100% (maksymalnie nasycony).
- Jasność (Lightness) - jak jasny lub ciemny jest kolor, od 0% (czarny) do 100% (biały), przy czym 50% to kolor "czysty".
Oto ten sam średni niebieski zapisany w obu formatach:
/* RGB - what do these numbers even mean at a glance? */
color: rgb(70, 130, 180);
/* HSL - instantly readable: blue hue, moderate saturation, medium lightness */
color: hsl(207, 44%, 49%);
Oba dają ten sam stalowy niebieski. Ale tylko wersja HSL mówi ci coś użytecznego na pierwszy rzut oka. Barwa wynosi 207 (niebieskawy odcień), nasycenie jest umiarkowane - 44%, a jasność plasuje się pośrodku na poziomie 49%. Możesz to przeanalizować bez otwierania próbnika kolorów.
| Właściwość | RGB | HSL |
|---|---|---|
| Czytelność dla człowieka | Rzadko | Tak |
| Rozjaśnienie/przyciemnienie koloru | Zmiana 3 wartości | Zmiana tylko jasności |
| Zmiana nasycenia | Przeliczenie wszystkich 3 | Zmiana tylko nasycenia |
| Tworzenie palety kolorów | Metodą prób i błędów | Obrót barwy o stopnie |
| Motywy z CSS custom properties | Nieczytelne | Czyste i przewidywalne |
Składnia HSL w CSS
Funkcja CSS
hsl()
jest obsługiwana od CSS3. Nowoczesna składnia (CSS Color Level 4) pozwala też na podanie czwartego parametru alfa bezpośrednio wewnątrz
hsl()
, co sprawia, że
hsla()
jest dziś w dużej mierze zbędne:
/* Classic syntax */
color: hsl(207, 44%, 49%);
/* With alpha (transparency) - old way */
color: hsla(207, 44%, 49%, 0.8);
/* Modern CSS Color Level 4 syntax - commas optional, alpha with slash */
color: hsl(207 44% 49%);
color: hsl(207 44% 49% / 0.8);
color: hsl(207 44% 49% / 80%);
Wszystkie główne przeglądarki obsługują obie składnie. Wersja bez przecinków to kierunek, w którym zmierza CSS, ale wersja z przecinkami działa wszędzie, włącznie z Internet Explorer 9+.
Dlaczego HSL wygrywa w tworzeniu UI
Prawdziwa siła HSL ujawnia się w momencie, gdy potrzebujesz wygenerować warianty koloru - a to w pracy nad interfejsem zdarza się nieustannie.
Budowanie palety kolorów w kilka sekund
Powiedzmy, że kolor marki to żywa zieleń przy
hsl(140, 70%, 45%)
. Potrzebujesz stanu hover, stanu nieaktywnego i jasnego tła. W HSL za każdym razem zmieniasz tylko jedną wartość:
--color-base: hsl(140, 70%, 45%); /* base green */
--color-hover: hsl(140, 70%, 38%); /* darker - just lower lightness */
--color-disabled: hsl(140, 20%, 65%); /* washed out - lower saturation */
--color-tint: hsl(140, 70%, 92%); /* very light background tint */
Spróbuj zrobić to samo przewidywalnie w RGB bez otwartego próbnika kolorów. To naprawdę trudne, bo nie ma izolowanej osi do regulacji.
Kolory analogiczne i dopełniające
Ponieważ barwa to stopień na kole barw, generowanie harmonijnych palet to zwykła arytmetyka. Kolory analogiczne są w odległości do 30 stopni od siebie. Kolory dopełniające dzieli 180 stopni:
--primary: hsl(210, 80%, 50%); /* blue */
--analogous-1: hsl(180, 80%, 50%); /* cyan - 30 degrees left */
--analogous-2: hsl(240, 80%, 50%); /* purple - 30 degrees right */
--complementary: hsl(30, 80%, 50%); /* orange - 180 degrees opposite */
Nasycenie i jasność pozostają identyczne, więc kolory tworzą spójną rodzinę. Dokładnie w ten sposób systemy projektowe takie jak Tailwind CSS i Material Design generują swoje skale kolorów programowo.
Praktyczne przykłady w CSS
CSS custom properties z komponentami HSL
Jednym z najpotężniejszych wzorców w HSL jest rozdzielenie trzech wartości na osobne CSS custom properties. Dzięki temu możesz je składać w dowolnym miejscu i na bieżąco modyfikować poszczególne kanały:
:root {
--brand-h: 210;
--brand-s: 80%;
--brand-l: 50%;
--brand-color: hsl(var(--brand-h), var(--brand-s), var(--brand-l));
}
.button {
background-color: var(--brand-color);
}
.button:hover {
/* Just override lightness - no need to redefine the whole color */
background-color: hsl(var(--brand-h), var(--brand-s), 40%);
}
.button:disabled {
background-color: hsl(var(--brand-h), 20%, 70%);
}
hsl()
wymagane są przecinki:
hsl(var(--h), var(--s), var(--l))
. Nowoczesna składnia bez przecinków nie działa jeszcze z
var()
wewnątrz
hsl()
we wszystkich przeglądarkach.
Generowanie pełnej skali tonalnej
Systemy projektowe często potrzebują 9-10 odcieni jednego koloru (jak skala od 50 do 950 w Tailwind). Z HSL możesz wygenerować całą skalę, stopniując jasność w równych odstępach przy stałej barwie i nasyceniu:
:root {
--blue-50: hsl(210, 80%, 95%);
--blue-100: hsl(210, 80%, 87%);
--blue-200: hsl(210, 80%, 76%);
--blue-300: hsl(210, 80%, 65%);
--blue-400: hsl(210, 80%, 55%);
--blue-500: hsl(210, 80%, 50%); /* base */
--blue-600: hsl(210, 80%, 43%);
--blue-700: hsl(210, 80%, 36%);
--blue-800: hsl(210, 80%, 26%);
--blue-900: hsl(210, 80%, 16%);
}
Jeśli chcesz lepiej zrozumieć, jak formaty kolorów odnoszą się do siebie nawzajem, przewodnik po konwersji HEX na RGB przedstawia pełny obraz formatów kolorów CSS, w tym kiedy każdy z nich jest właściwym narzędziem.
Stany hover, motywy i tryb ciemny
Stany hover i focus
HSL sprawia, że stany hover stają się banalne. Zamiast definiować zupełnie osobny kolor, wystarczy przesunąć jasność:
.btn-primary {
background: hsl(210, 80%, 50%);
transition: background 0.2s ease;
}
.btn-primary:hover { background: hsl(210, 80%, 43%); }
.btn-primary:active { background: hsl(210, 80%, 36%); }
.btn-primary:focus-visible {
outline: 3px solid hsl(210, 80%, 70%);
}
Każdy stan jest wyraźnie powiązany z kolorem bazowym. Kolega czytający ten kod od razu rozumie zależności między stanami.
Motywy z zmiennymi HSL
HSL stanowi fundament nowoczesnych motywów CSS. Wystawiając samą barwę jako zmienną, możesz pozwolić użytkownikom lub administratorom zmienić cały schemat kolorystyczny aplikacji przez modyfikację jednej liczby:
/* Default theme: blue */
:root {
--theme-hue: 210;
}
/* Green theme - just swap the hue */
[data-theme="green"] {
--theme-hue: 140;
}
/* Purple theme */
[data-theme="purple"] {
--theme-hue: 270;
}
/* All components use the same hue variable */
.button { background: hsl(var(--theme-hue), 75%, 50%); }
.link { color: hsl(var(--theme-hue), 75%, 40%); }
.badge { background: hsl(var(--theme-hue), 75%, 92%); color: hsl(var(--theme-hue), 75%, 25%); }
.focus-ring { outline-color: hsl(var(--theme-hue), 75%, 65%); }
Tryb ciemny z HSL
Tryb ciemny to miejsce, gdzie HSL naprawdę błyszczy. Zamiast utrzymywać dwie zupełnie osobne palety kolorów, odwracasz wartości jasności w obrębie tej samej barwy:
:root {
--bg: hsl(210, 20%, 98%); /* near-white background */
--text: hsl(210, 20%, 15%); /* near-black text */
--card: hsl(210, 20%, 93%); /* slightly darker card */
}
@media (prefers-color-scheme: dark) {
:root {
--bg: hsl(210, 20%, 10%); /* flip: near-black background */
--text: hsl(210, 20%, 90%); /* flip: near-white text */
--card: hsl(210, 20%, 15%); /* slightly lighter card in dark */
}
}
Zwróć uwagę, że barwa (210) i nasycenie (20%) nigdy się nie zmieniają. Odwraca się tylko jasność. Dzięki temu tryb ciemny wygląda jak ten sam projekt, tylko odwrócony - a właśnie tak powinien wyglądać dobry tryb ciemny.
Wsparcie przeglądarek i kompatybilność
HSL cieszy się doskonałym wsparciem przeglądarek. Funkcja
hsl()
jest dostępna od:
- Chrome 1 (2008)
- Firefox 1 (2004)
- Safari 3.1 (2008)
- Internet Explorer 9 (2011)
- Edge 12 (2015)
Nowoczesna składnia bez przecinków (
hsl(210 80% 50%)
) oraz składnia ze slash dla kanału alfa (
hsl(210 80% 50% / 0.5)
) są częścią specyfikacji
CSS Color Level 4
i są obsługiwane przez wszystkie nowoczesne przeglądarki od 2023 roku. Jeśli musisz wspierać IE11 (co jest dziś rzadkością), trzymaj się składni z przecinkami.
hsl()
z przecinkami działa w każdej przeglądarce, z której korzystają twoi użytkownicy. Nowoczesna składnia z separatorami spacjami działa w Chrome 90+, Firefox 89+ i Safari 14.1+, obejmując ponad 95% globalnego ruchu przeglądarek.
Możesz zawsze skorzystać z próbnika kolorów , aby konwertować między formatami HSL, RGB i HEX, gdy potrzebujesz skrzyżować wartości lub przekazać kolory do narzędzi obsługujących tylko jeden format.
HSL vs OKLCH - Co dalej?
Jeśli chcesz wyjść poza HSL, OKLCH jest wart uwagi. To percepcyjnie jednolita przestrzeń kolorów, co oznacza, że równe kroki numeryczne w jasności lub chrominancji naprawdę wyglądają jak równe kroki dla ludzkiego oka - czego HSL nie gwarantuje w pełni.
Problem z HSL polega na tym, że dwa kolory o tej samej wartości jasności mogą wyglądać bardzo różnie pod względem postrzeganej jasności. Na przykład
hsl(60, 100%, 50%)
(żółty) wygląda znacznie jaśniej niż
hsl(240, 100%, 50%)
(niebieski), mimo że oba mają 50% jasności. OKLCH koryguje ten problem.
/* HSL - same lightness, different perceived brightness */
color: hsl(60, 100%, 50%); /* yellow - looks very bright */
color: hsl(240, 100%, 50%); /* blue - looks much darker */
/* OKLCH - same lightness, actually looks the same to the eye */
color: oklch(0.75 0.18 90); /* yellow-ish */
color: oklch(0.75 0.18 260); /* blue-ish - genuinely similar perceived brightness */
OKLCH obsługuje również
kolory szerokiej gamy (wide-gamut)
(kolory wyświetlaczy P3) wykraczające poza zakres sRGB, do którego ograniczone jest HSL. Wsparcie przeglądarek dla
oklch()
jest solidne w 2024 roku: Chrome 111+, Firefox 113+, Safari 15.4+.
W przypadku większości projektów HSL jest dziś praktycznym złotym środkiem: czytelny, łatwy w utrzymaniu, powszechnie obsługiwany i ogromnie lepszy od RGB. OKLCH to właściwy wybór, gdy budujesz system projektowy wymagający matematycznie spójnych współczynników kontrastu lub chcesz celować w wyświetlacze szerokiej gamy.
Jeśli chcesz wizualnie eksplorować zależności kolorów podczas budowania palety, narzędzie do eksploracji kolorów pozwala eksperymentować z wartościami HSL i obserwować w czasie rzeczywistym, jak wzajemnie oddziałują obroty barwy, zmiany nasycenia i przesunięcia jasności.
Dobieraj kolory HSL bez zgadywania
Nasz próbnik kolorów pozwala wizualnie ustawiać wartości barwy, nasycenia i jasności, a następnie skopiować gotowy wynik modelu kolorów HSL bezpośrednio do CSS - bez żadnych obliczeń w głowie.
Wypróbuj próbnik kolorów →
Nie musisz robić pełnego przepisania, ale warto przechodzić na HSL przy każdej nowej definicji koloru, szczególnie gdy używasz CSS custom properties. Największe korzyści pojawiają się przy budowaniu lub utrzymywaniu systemu projektowego, tworzeniu stanów hover albo wdrażaniu trybu ciemnego. Mieszanie RGB i HSL w tym samym projekcie to całkowicie poprawny CSS - przeglądarki obsługują oba formaty bez żadnej różnicy w wydajności.
Nie, nie ma żadnej istotnej różnicy w wydajności. Przeglądarka konwertuje wszystkie formaty kolorów CSS do wewnętrznej reprezentacji podczas parsowania, więc bez względu na to, czy napiszesz
hsl(207, 44%, 49%)
czy
rgb(70, 130, 180)
, silnik renderujący traktuje je identycznie po tym początkowym kroku parsowania. Wybór formatu dotyczy wyłącznie wygody dewelopera i łatwości utrzymania kodu, a nie wydajności w czasie wykonania.
Tak, i to jedno z najmocniejszych zastosowań HSL w JavaScript. Możesz przechowywać barwę, nasycenie i jasność jako osobne liczby, a następnie dynamicznie konstruować string koloru:
element.style.color = `hsl(${hue}, ${saturation}%, ${lightness}%)`
. Dzięki temu animacje, przełączanie motywów i interaktywne kontrolki kolorów są znacznie prostsze do zaimplementowania niż przy pracy z kanałami RGB, gdzie do osiągnięcia tych samych efektów potrzebowałbyś matematyki konwersji.
HSL (barwa, nasycenie, jasność) i HSB/HSV (barwa, nasycenie, jasność/wartość) to różne modele kolorów, mimo że mają wspólną oś barwy. W HSL jasność na poziomie 50% daje czysty, w pełni nasycony kolor. W HSB jasność na poziomie 100% daje czysty kolor. Oba modele dają różne wyniki dla tych samych wartości nasycenia i jasności. CSS używa konkretnie HSL - HSB/HSV jest powszechny w narzędziach projektowych takich jak Photoshop i Figma, ale nie jest natywnym formatem CSS.
Konwersja z HEX na HSL przebiega przez pośredni krok RGB: najpierw konwertujesz pary HEX na wartości RGB (0-255), normalizujesz je do zakresu 0-1, a następnie stosujesz wzór konwersji HSL. W praktyce większość deweloperów używa do tego próbnika kolorów, narzędzia projektowego jak Figma lub próbnika kolorów w DevTools przeglądarki, zamiast liczyć ręcznie. DevTools przeglądarki pozwalają kliknąć dowolną próbkę koloru i przełączać się między reprezentacjami HEX, RGB i HSL.
Tak, OKLCH jest bardziej niezawodny w pracy nad dostępnością, ponieważ jest percepcyjnie jednolity - równe kroki w kanale jasności odpowiadają równym zmianom postrzeganej jasności. Dzięki temu łatwiej budować palety kolorów, w których współczynniki kontrastu są przewidywalne dla różnych barw. W HSL żółty przy 50% jasności wygląda znacznie jaśniej niż niebieski przy 50% jasności, co może prowadzić do nieoczekiwanych problemów z dostępnością. Przy zapewnianiu zgodności z WCAG, OKLCH daje bardziej przewidywalne wyniki podczas budowania dostępnych skal kolorów.