Ten sam kolor, cztery zapisy — HEX, RGB, HSL i oklch

16 lip 2026·11 min czytania·1820 słów
Świecąca szmaragdowa próbka koloru rozszczepiająca się jak przez pryzmat na cztery zapisy — HEX, RGB, HSL i oklch — na tle kosmicznej mgławicy w fiolecie i magencie

Weź czerwień — najzwyklejszą, pełną czerwień. Możesz ją zapisać na cztery sposoby: #FF0000, rgb(255, 0, 0), hsl(0, 100%, 50%) albo oklch(0.628 0.258 29.2). To wciąż ten sam kolor, ten sam strumień światła z ekranu — zmienia się tylko język, w jakim o nim mówimy. Ale te cztery języki nie są równe. Dwa z nich są matematycznie ścisłe i wzajemnie przeliczalne co do bitu. Jeden udaje, że rozumie, jak widzisz — i kłamie. A jeden, najmłodszy, wreszcie zgadza się z twoim okiem. Oto opowieść o tym, czym się różnią.

Jak ekran w ogóle robi kolor

Ekran nie miesza farb. Miesza światło — i to metodą addytywną, przez sumowanie. Każdy piksel to trzy niezależne subpiksele: czerwony (R), zielony (G) i niebieski (B). Zaświeć wszystkie trzy na maksa i dostaniesz biel; zgaś wszystkie — czerń. To odwrotność malowania, gdzie każda kolejna warstwa pigmentu odejmuje część światła i im więcej farby, tym bliżej czerni.

W najpowszechniejszej architekturze każdy z trzech kanałów kodujemy jednym bajtem — a bajt mieści 2⁸ = 256 poziomów jasności, od 0 do 255. Trzy kanały po 256 poziomów dają 256³ = 16 777 216 kombinacji, czyli owe „16 milionów kolorów" z ulotek monitorów. Do tego dochodzi czwarty kanał, alfa (α), opisujący krycie — od 0 (pełna przezroczystość) do 1 (pełne krycie).

Warto od razu rozdzielić dwie warstwy, bo ich mylenie jest źródłem większości nieporozumień o kolorze. Podział sygnału na 256 poziomów i dodawanie strumieni światła to fakt ścisły, fizyczny. Ale wybór akurat czerwieni, zieleni i błękitu jako barw podstawowych jest umowny — to inżynieryjny kompromis, który ma pobudzać trzy typy czopków w ludzkim oku (długo-, średnio- i krótkofalowe) tak, by udawać naturalne widzenie, choć ekran nie emituje pełnego widma słońca. Ta granica — co jest ścisłe, a co tylko wygodną umową — przewija się przez całą resztę tej historii.

HEX i RGB: ten sam kolor, inny alfabet

Zapisy RGB i HEX to bezpośrednie odbicie tego, co ekran robi na najniższym poziomie. rgb(255, 0, 0) znaczy: kanał czerwony na maksa, dwa pozostałe zgaszone. #FF0000 mówi dokładnie to samo — tyle że po szesnastkowemu. Każda para znaków HEX to jeden bajt: FF w systemie o podstawie 16 to 255 w dziesiętnym, 00 to zero. Stąd wzór #RRGGBB. Dodaj kanał alfa i masz #RRGGBBAA: zapis #FF000080 to czerwień z kryciem około 50%, bo szesnastkowe 80 to 128, czyli mniej więcej połowa z 255.

Przejście HEX ↔ RGB jest całkowicie ścisłe — to bezstratna zamiana tej samej liczby między systemem o podstawie 16 a dziesiętnym, bez cienia interpretacji. Dlaczego więc programiści tak lubią HEX? Z powodów czysto praktycznych: jest krótszy (sześć znaków zamiast rgb(…)), obsługiwany od zarania HTML-a i wygodnie eksportuje się z narzędzi projektowych. To decyzja o ergonomii kodu, nie o fizyce światła — sama barwa jest jej głęboko obojętna.

HSL: kolor opisany po ludzku

Nikt nie myśli „chcę 124 czerwonego, 58 zielonego i 237 niebieskiego". Myślimy raczej: „fiolet, mocno nasycony, średnio jasny". Właśnie tę intuicję próbował ująć model HSL, opracowany w latach 70.: trzy współrzędne to Hue (barwa), Saturation (nasycenie) i Lightness (jasność).

  • Hue to kąt na kole barw, od 0° do 360°: 0° czerwony, 120° zielony, 240° niebieski.
  • Saturation to czystość barwy, od 0% (szarość) do 100% (najpełniejszy kolor).
  • Lightness to jasność, od 0% (czerń) przez 50% (najbardziej wyrazisty odcień) po 100% (biel).

HSL zrobił zawrotną karierę w projektowaniu interfejsów, bo pozwala manipulować kolorem intuicyjnie. Chcesz ciemniejszy wariant przycisku na najechanie myszą? W HSL zmniejszasz jeden parametr — L. W RGB czy HEX musiałbyś jednocześnie przeliczyć trzy niezależne kanały. Matematycznie HSL to nadal tylko przekształcenie geometryczne sześcianu RGB w walec — ścisłe i w pełni odwracalne. Problem w tym, że ta geometria nic nie wie o twoim oku.

Kłamstwo jasności

Oto pułapka. Weź żółty hsl(60, 100%, 50%) i niebieski hsl(240, 100%, 50%). Według HSL oba mają identyczną jasność: 50%. Ale spójrz na nie — żółty jest jaskrawy i niemal świetlisty, niebieski głęboki i ciemny. Twoje oko nie ma wątpliwości, że jeden jest znacznie jaśniejszy od drugiego, choć liczba mówi, że są równe.

To nie złudzenie, tylko wada konstrukcyjna HSL: „lightness" jest tam czysto geometryczną średnią kanałów, a ludzkie oko nie reaguje na różne długości fali jednakowo — na zielono-żółte jesteśmy dużo czulsi niż na błękit. Widać to jak na dłoni, gdy te same barwy zapiszemy w percepcyjnym oklch (o nim za chwilę): żółty ma tam jasność 0.968, a niebieski zaledwie 0.452 — ponad dwukrotnie mniej. HSL twierdzi „równe", oko i oklch mówią „nic podobnego".

Dla estetyki to niewygoda; dla dostępności — poważny błąd. Automatyczne generowanie kontrastów pod kątem osób słabowidzących (wytyczne WCAG) w oparciu o HSL-owe L jest metodologiczną wpadką, bo zmiana samej barwy przy stałym L potrafi drastycznie zmienić realny, postrzegany kontrast tekstu względem tła. Rachunki czytelności muszą operować na jasności percepcyjnej, nie geometrycznej.

Światło nie jest liniowe

Jest jeszcze jeden powód, dla którego naiwna matematyka na kolorach zawodzi. Wartości w zapisie sRGB (a więc w HEX i RGB) nie są wprost proporcjonalne do fizycznej ilości światła. Między nimi siedzi tzw. korekcja gamma — nieliniowa krzywa, która ściska jasności tak, by 256 dostępnych poziomów lepiej odpowiadało temu, jak oko rozróżnia ciemne i jasne tony (jesteśmy znacznie czulsi na subtelne różnice w cieniach). Formalnie kanał sRGB przelicza się na światło liniowe wzorem: dla wartości V ≤ 0.04045 jest to V / 12.92, a powyżej — ((V + 0.055) / 1.055)^2.4.

Konsekwencja jest namacalna. Uśrednij „w połowie" czerwień rgb(255, 0, 0) i zieleń rgb(0, 255, 0) wprost na wartościach sRGB, a w środku gradientu wyjdzie ci brudna, brunatna szarość zamiast jasnego, świetlistego przejścia. Dopiero przeliczenie do przestrzeni liniowej (albo, jeszcze lepiej, do percepcyjnej), uśrednienie tam i powrót daje naturalny wynik. Ten sam błąd przez lata popełniały silniki przeglądarek, mieszając kolory w złej przestrzeni.

oklch: kolor, który myśli jak oko

W grudniu 2020 roku szwedzki inżynier Björn Ottosson opublikował przestrzeń barwną OKLab — odpowiedź na wady i starych modeli percepcyjnych (CIELAB z 1976 potrafił „fioletowieć" przy rozjaśnianiu błękitów), i technicznych sRGB/HSL. W codziennym kodzie używamy jej wygodniejszej, cylindrycznej postaci: oklch, o zapisie oklch(L C h / a):

  • L — jasność percepcyjna, od 0 do 1. Kluczowa różnica wobec HSL: ta sama wartość L to naprawdę ten sam odczuwany blask, niezależnie od barwy.
  • C — chroma, czyli nasycenie liczone jako odległość od szarości. Zaczyna się od 0 i formalnie nie ma górnego limitu.
  • h — kąt barwy w stopniach. Zorientowany inaczej niż w HSL: w naszym konwerterze czerwień wypada przy ~29°, żółty ~110°, zielony ~142°, a niebieski ~264°.

Historycznie oklch to spadkobierca systemu Munsella z 1905 roku, który jako pierwszy uporządkował barwy na podstawie eksperymentów z obserwatorami. Standard rozszedł się błyskawicznie: trafił do specyfikacji CSS Color 4, Adobe zrobił z niego domyślny model interpolacji gradientów w Photoshopie, a Tailwind v4 oparł na nim generowanie palet. Powód jest prosty — skoro L odpowiada realnej jasności, budowanie spójnych, dostępnych zestawów kolorów przestaje być zgadywaniem.

Warto docenić, jak ładnie splata się tu ścisłość z umownością. Same przeliczenia — sRGB → światło liniowe → OKLab → oklch — to twarda algebra: mnożenie macierzy i pierwiastkowanie, bez miejsca na uznaniowość. Ale projekt tej przestrzeni, dobór wag i decyzja o „wyprostowaniu" jasności to czysta percepcja: numeryczne dopasowanie do eksperymentalnych baz danych ludzkiego widzenia. To inżynieria w służbie oka.

Gamut: kolory, których ekran nie pokaże

Przez ponad dwie dekady punktem odniesienia był sRGB (standard z 1996 roku), pokrywający tylko część barw widzialnych dla oka. Nowoczesne ekrany OLED i mini-LED sięgają dalej — do przestrzeni Display P3, która oferuje wyraźnie większą objętość barw: głębsze czerwienie, jaskrawsze zielenie i turkusy, jakich sRGB w ogóle nie potrafi wyświetlić.

I tu ujawnia się przewaga oklch. Kody HEX i funkcja rgb() są konstrukcyjnie zamknięte w granicach sRGB — nie zapiszesz nimi barwy spoza tego zakresu. Ale ponieważ chroma w oklch nie ma sztywnego sufitu, ta sama funkcja oklch() opisze i przygaszoną barwę sRGB, i super-nasyconą barwę P3 — wystarczy podnieść C. Gdy taki kolor trzeba pokazać na starszym ekranie, przeglądarka mapuje gamut właśnie w oklch: trzyma jasność (L) i barwę (h) na stałe, a zmniejsza tylko nasycenie (C), aż kolor zmieści się w sRGB. Dzięki temu barwa lekko blednie, ale zachowuje swój charakter — inaczej niż prymitywne przycinanie kanałów RGB, które potrafi zamienić jaskrawy turkus w zwykłą zieleń. Nasz konwerter robi dokładnie to: barwę spoza sRGB pokazuje w oklch dokładnie, a w HEX/RGB/HSL — przyciętą, z wyraźnym znacznikiem „poza gamut sRGB".

Ta sama barwa, cztery zapisy

Poniższa tabela to nie teoria — to dokładne wartości z konwertera kolorów na tej stronie. Zwróć uwagę na kolumnę oklch: przy żółtym i niebieskim HSL-owa jasność jest identyczna (50%), a percepcyjne L rozjeżdża się ponad dwukrotnie.

BarwaHEXRGBHSLoklch
Czerwony#FF0000rgb(255, 0, 0)hsl(0, 100%, 50%)oklch(0.628 0.258 29.2)
Żółty#FFFF00rgb(255, 255, 0)hsl(60, 100%, 50%)oklch(0.968 0.211 109.8)
Zielony#00FF00rgb(0, 255, 0)hsl(120, 100%, 50%)oklch(0.866 0.295 142.5)
Niebieski#0000FFrgb(0, 0, 255)hsl(240, 100%, 50%)oklch(0.452 0.313 264.1)
Głęboki fiolet#7F00FFrgb(127, 0, 255)hsl(270, 100%, 50%)oklch(0.529 0.293 293.6)
Czerwień 50% α#FF000080rgba(255, 0, 0, 0.5)hsla(0, 100%, 50%, 0.5)oklch(0.628 0.258 29.2 / 0.5)

Wszystkie sześć możesz przekleić do konwertera i zobaczyć na żywo — łącznie z podglądem krycia na szachownicy dla ostatniego wiersza.

Cztery języki, jeden kolor

Kolor na ekranie jest jeden. To my mamy cztery sposoby, żeby o nim opowiedzieć — i każdy z nich mówi co innego nie o barwie, lecz o nas. HEX i RGB są najbliżej maszyny: ścisłe, wzajemnie przeliczalne, obojętne na to, jak widzisz. HSL próbuje mówić po ludzku i za tę wygodę płaci rozminięciem się z okiem tam, gdzie liczy się jasność. oklch nadrabia ten dług — jest tak samo ścisły w rachunkach, a jednocześnie zbudowany wokół tego, jak naprawdę odbieramy światło.

Cała sztuka pracy z kolorem sprowadza się do jednego rozróżnienia, które przewijało się przez cały ten tekst: co jest matematycznie ścisłe (zamiana zapisów, bajty, przeliczenia), a co tylko umowne i percepcyjne (wybór barw podstawowych, kształt krzywej gamma, projekt oklch). Zapis możesz zmieniać do woli — kolor się nie zmienia. Ale wybór zapisu decyduje, czy matematyka będzie po twojej stronie, czy przeciw oku.

Dalsza lektura

  • Björn Ottosson, A perceptual color space for image processing (2020) — źródłowy artykuł o OKLab, z całą matematyką: bottosson.github.io/posts/oklab.
  • W3C, CSS Color Module Level 4 — oficjalna specyfikacja zapisu i mapowania barw szerokogamutowych: w3.org/TR/css-color-4.
  • MDN Web Docs, oklch() — praktyczny przewodnik po funkcji w CSS: developer.mozilla.org.
  • Evil Martians, OKLCH in CSS: why we moved from RGB and HSL — wdrożeniowa perspektywa i przykłady.
Wypróbuj

Konwerter — Kolory

Otwórz konwerter