Naar de inhoud
HexSlate

CSS Gradient Generator

StoppositiesKlik op de balk om een stop toe te voegen, sleep om te verplaatsen
Dezelfde gradient, twee kleurruimtes

Het getal onder elke balk is het chroma van de kleur op de helft, gemeten in OKLCH. Een middelpunt dat zijn chroma kwijt is, is de grijze dode zone.

in oklchchroma op het middelpunt 0.124
geen hint (sRGB)chroma op het middelpunt 0.000
CSS
.gradient {
  background-image: linear-gradient(90deg, #0000ff 0%, #ffff00 100%);
  background-image: linear-gradient(90deg in oklch, #0000ff 0%, #ffff00 100%);
}
Tailwind v4
bg-[linear-gradient(90deg_in_oklch,_#0000ff_0%,_#ffff00_100%)]

Plak beide CSS-declaraties, in die volgorde. Eén Tailwind-utility is één declaratie, dus de class draagt de vorm met hint en geen fallback.

Lineair in OKLCH2 stopschroma op het middelpunt 0.124 OKLCH, 0.000 sRGB162 tekens CSS

De interpolatieruimte van een verloop is een hint die in de functie zelf staat, en hem weglaten is niet neutraal: elk verloop in CSS zonder hint mengt in sRGB, en daar loopt blauw naar geel door grijs. Deze pagina levert twee background-image-declaraties op en je hebt ze allebei nodig, in de volgorde waarin ze geschreven staan.

Wat in oklch is, en wanneer het in CSS landde

De kleurinterpolatiemethode van een verloop is de ruimte waarin de browser de stops mengt, geschreven in de functie na de geometrie: linear-gradient(90deg in oklch, #0000ff, #ffff00). Laat hem weg en elk verloop in CSS interpoleert in sRGB, wat browsers altijd al deden. De syntaxis komt uit CSS Color 4 en verscheen in Safari 16.2 in december 2022, Chrome en Edge 111 in maart 2023, en Firefox 127 in juni 2024.

Eén verwarrende naam even ophelderen: de images-spec noemt een kaal percentage tussen twee stops, zoals in linear-gradient(red, 30%, blue), een colour interpolation hint, en het enige wat dat doet is het punt halverwege de menging langs de lijn verschuiven. Dat is een aparte en veel oudere functie, in browsers sinds Firefox 36 en Chrome 40, en die zegt niets over de ruimte waarin gemengd wordt.

Waarom sRGB blauw naar geel door dood grijs laat lopen

In sRGB zijn de drie coördinaten de waarden waarmee een scherm wordt aangestuurd, en #0000ff en #ffff00 liggen in tegenovergestelde hoeken van die kubus: (0, 0, 255) en (255, 255, 0). Een rechte lijn tussen tegenovergestelde hoeken gaat precies door het midden, dus het middelpunt is (128, 128, 128), oftewel #808080. Dat is geen browserbug, en de uiteinden verschuiven lost het niet op. Verzadiging is geen van de drie coördinaten, dus niets in het rekenwerk houdt het vast, en de kleur loopt uit het midden van het verloop weg.

De coördinaten van OKLCH zijn lichtheid, chroma en tint, op assen die Björn Ottosson in 2020 op perceptuele data heeft afgestemd. Interpolatie beweegt de drie apart, dus chroma gaat helemaal mee en de tint loopt langs de cirkel in plaats van door het neutrale punt in het midden. Datzelfde blauw naar geel gaat door een turkoois op tint 187, met zijn chroma intact. De aflezing onder elke vergelijkingsbalk is dat verschil als getal: de chroma van de kleur halverwege, in beide gevallen gemeten in OKLCH.

in hsl geeft weer een derde antwoord

HSL is ook polair, dus in hsl draait de tint in plaats van door het midden te snijden, maar zijn assen zijn meetkunde en geen waarneming, en de route is anders. Blauw is hsl(240) en geel is hsl(60): precies een halve slag uit elkaar, en dat is het ene geval waarin "de kortste weg" geen antwoord heeft. De spec laat het verschil met teken staan, dus browsers lopen omlaag vanaf 240 en het midden van het verloop is het groen op 150. Vraag om longer hue en dezelfde twee stops gaan de andere kant op, door magenta en rood. HSL houdt de verzadiging de hele weg vast, dus geen van beide routes wordt grijs, maar de lichtheid van HSL is het midden van het grootste en het kleinste kanaal in plaats van iets perceptueels, dus het verloop krijgt een lichte band waar de tint door geelgroen loopt.

shorter hue en longer hue op een conisch verloop

De tintmethodes kiezen welke boog van de tintcirkel de menging aflegt, en op een conisch verloop is die keuze het verschil tussen een taartpunt uit het kleurenwiel en bijna het hele wiel. shorter hue is de standaard en neemt de kleinste boog; longer hue neemt de andere. Twee stops met bijna dezelfde tint plus longer hue bestrijken bijna een volle 360 graden, en dat is de kortste manier om een kleurenwiel in CSS te schrijven.

increasing hue en decreasing hue benoemen de richting direct in plaats van te meten welke boog korter is, en die wil je zodra twee tinten ongeveer een halve slag uit elkaar liggen. Daar wordt "korter" door een afrondingsverschil beslist en kan het naar de andere kant van het wiel omslaan als je een stop één eenheid verschuift. De richting benoemen maakt het resultaat stabiel. Alle vier gelden alleen in een polaire ruimte: in oklab longer hue is een parsefout, want OKLab heeft geen tintas om over te lopen, en deze tool verbergt de knop in plaats van een declaratie te leveren die een browser weggooit.

De fallbackdeclaratie moet als eerste komen

Een browser die in oklch niet begrijpt valt niet stilletjes terug op sRGB. De waarde is niet te parsen, dus de hele background-image-declaratie wordt weggegooid en het element krijgt helemaal geen verloop. Niets in CSS kan zeggen "gebruik deze hint als je hem kent", dus het enige beschikbare mechanisme is de cascade: schrijf de declaratie zonder hint eerst, die met hint als tweede, en elke engine houdt de laatste die hij kon parsen. Oudere engines stoppen bij de eerste, huidige nemen de tweede, en een @supports-blok is niet nodig. De volgorde omdraaien is de enige manier om dit fout te doen, en dat gaat stil mis doordat de fallback overal wint.

Wat het voorbeeld je wel en niet kan vertellen

Het voorbeeld is je eigen browser die dezelfde CSS tekent die je op het punt staat te kopiëren, geen nabouw ervan, dus wat je ziet is wat er naar een browser als de jouwe gaat. Het is niet wat iedereen ziet. Een browser zonder interpolatiemethodes krijgt de eerste declaratie, en dat is echt een ander plaatje: blauw naar geel door grijs in plaats van door turkoois. De twee vergelijkingsbalken zijn die twee plaatjes naast elkaar, en dat is het dichtste wat deze pagina bij allebei tegelijk komt. Een scherm met een breed gamut voegt een tweede verschil toe, want de browser brengt kleuren naar het scherm in plaats van naar sRGB, dus een verzadigd verloop kan er op jouw machine feller uitzien dan de hexwaarden suggereren.

Veelvoorkomende problemen

  • Het element heeft in een oudere browser helemaal geen verloop. Alleen de declaratie met hint is meegegaan. Een waarde die niet parst maakt alleen zijn eigen declaratie ongeldig, dus die zonder hint moet er staan, erboven, om bewaard te blijven.
  • Een stop die je aanklikt is niet de kleur die onder de muis lag. De sampler loopt de kortste weg om de tintcirkel, dus onder longer, increasing of decreasing hue nam het tekenen een andere route dan de meting. Het gebeurt ook bij in hsl tussen twee tinten die precies een halve slag uit elkaar liggen, waar de sampler en de browser de knoop elk de andere kant op doorhakken. Zet de kleur van de stop op wat je wilde; verder verandert er niets aan het verloop.
  • Een conisch verloop heeft een harde naad. De rondgang komt terug waar hij begon, dus tenzij de laatste stop dezelfde kleur is als de eerste zit er een zichtbare rand bij de starthoek. Dat is de meetkunde, geen bug. Zet een sluitende stop op 100% die gelijk is aan die op 0%.
  • Het verloop vertoont banden in plaats van een vloeiende overgang. Een verloop dat over een groot vlak wordt uitgerekt legt minder dan één 8-bits stap per kolom af, en de vlakke banden zijn wat er overblijft. Browsers ditheren om het te verbergen en slagen daar meestal in. Maak het verloop korter, of leg er een vage ruistextuur overheen, wat de bandvrije verlopen in designsystemen doen.

Veelgestelde vragen

Welke interpolatieruimte moet ik gebruiken?

OKLCH voor alles wat nieuw is: het houdt chroma door het midden vast en zijn lichtheid komt overeen met wat je ziet. OKLab als je liever hebt dat de tint je nooit verrast, want dat interpoleert op rechthoekige assen en kan niet om het wiel heen draaien. sRGB als je een verloop reproduceert dat al bestaat, waar een mooier verloop het verkeerde antwoord is. HSL alleen om iets na te doen dat erin gebouwd is.

Verandert de ruimte de kleuren aan de uiteinden?

Nee. Beide uiteinden zijn precies de kleuren die je schreef, in elke ruimte. De interpolatiemethode bepaalt alleen het pad ertussen, en daarom mogen de declaraties met en zonder hint gerust van elkaar afwijken: elke browser toont de stops die je koos, en ze verschillen alleen in wat er tussen die stops gebeurt.

Waarom wordt vervagen naar transparent niet meer grijs?

Omdat verlopen interpoleren in premultiplied alpha. transparent is gedefinieerd als transparant zwart, en zijn kanalen direct interpoleren trok het midden van een fade vroeger naar een donker grijs. Daardoor doet de kleur van een volledig transparante stop niet meer mee, dus #0000ff naar transparent en #0000ff naar #0000ff00 geven nu hetzelfde verloop. Die correctie zit sinds Chrome 29, Firefox 36 en Safari 15 in de browsers.

Kan ik een verloop op tekst of op een rand zetten?

Op tekst zet je het verloop als background-image, en daarna background-clip: text en color: transparent. Geef het element eerst een leesbare terugvalwaarde voor color, want de tekst verdwijnt als de clip mislukt. Een rand vraagt border-image, en dat volgt border-radius niet; leg voor een afgeronde verlooprand in plaats daarvan twee achtergronden over elkaar met background-clip: padding-box, border-box.

Verlaat hier iets mijn browser?

Nee. De stops, de meting, de gamut-omzetting en de CSS worden allemaal in de pagina berekend, en het voorbeeld is je eigen browser die het resultaat tekent. Er gaat geen enkel verzoek uit. Het enige dat vertrekt is de URL, als je die deelt, en daar staat niets in behalve de stops, de geometrie, de ruimte en het tintpad.