Elf treden van 50 tot 950, gestapt in OKLCH zodat elke trede landt waar je oog hem legt in plaats van waar het sRGB-rekenwerk hem legt. Je kleur wordt exact weergegeven op de trede waar zijn eigen lichtheid hoort, en dat is vaak niet de 500. Alles draait in je browser, en de basiskleur, de variabelenaam en beide instellingen staan in de query string, dus een link geeft precies deze schaal terug.
Een toonschaal is een belofte over lichtheid, en HSL kan die niet nakomen
Als een designsysteem blue-500 en amber-500 aanbiedt, belooft het dat die twee hetzelfde visuele gewicht dragen, zodat een badge op de een leest als dezelfde badge op de ander. Die belofte gaat over waargenomen lichtheid, en die meet HSL niet: zijn L is het midden van het grootste en het kleinste sRGB-kanaal. hsl(60 80% 50%) komt terug op OKLCH-lichtheid 0,894 en hsl(264 80% 50%) op 0,491, terwijl allebei dezelfde nominale 50% claimen. Gelijke stappen in HSL zijn ook niet gelijk. hsl(264 80% L) met tientallen omlaag lopen vanaf 95% geeft 0,944, 0,831, 0,720, 0,615, 0,525, 0,455, 0,381: de eerste stap is 0,113 aan waargenomen lichtheid waard en de stap van 55% naar 45% maar 0,070. OKLab, waar OKLCH de polaire vorm van is, is juist op perceptuele data afgestemd zodat gelijke numerieke stappen er gelijk uitzien, en de kleurformaatconverter leest de OKLCH-lichtheid van elke kleur voor je terug.
Waar 50 tot 950 voor is, en waar de getallen vandaan komen
Het uiteinde bij 50 is vlakken en het uiteinde bij 950 is inkt. In de praktijk zijn 50 en 100 de achtergronden van pagina en kaart, 200 en 300 randen en scheidingslijnen, 400 tot 600 de plek van een gevulde knop of een link, en 700 en hoger tekst, hoverstatus en donkere vlakken. De nummering stopt voor 0 en 1000 omdat beide uiteinden te onderscheiden moeten blijven van wit en zwart in plaats van ze te raken.
De lichtheid van elke trede is hier niet verzonnen. Elke trede is de gemiddelde OKLCH-lichtheid van de 25 ingebouwde kleurschalen van Tailwind v4 op die stap, genomen uit tailwindcss/theme.css: 0,979 op 50, 0,642 op 500, 0,235 op 950. Een gegenereerde brand-500 leest daarom op hetzelfde gewicht als de ingebouwde blue-500 ernaast in een mock-up. Let op hoe ongelijk de ladder is, met 0,024 tussen 50 en 100 tegenover 0,102 tussen 900 en 950. Dat is met opzet: het lichte uiteinde is een reeks bijna witte vlakken die uit elkaar moeten blijven, en het donkere uiteinde moet wegblijven van zwart.
Chroma is niet constant te houden, en doen alsof valt op
"Constante chroma" beschrijft de methode overal goed behalve aan de twee uiteinden, waar het ronduit misgaat. Het sRGB-gamut is geen cilinder. Het loopt bij wit en bij zwart taps toe naar een punt, en geen van beide heeft ook maar enige chroma, dus de chroma van je basiskleur vragen bij lichtheid 0,979 is om een kleur vragen die niet bestaat. Deze tool laat de chroma naar beide uiteinden aflopen op een curve die is afgestemd op de gemiddelde chroma per stap van Tailwind zelf, en geeft hem aan de lichte kant sneller op dan aan de donkere, want een 50 hoort een vleugje kleur te zijn terwijl een 900 een tekstkleur is die dood leest zodra de tint eruit gebleekt is. Wat dan nog buiten sRGB valt, wordt omgezet zoals CSS Color 4 beschrijft: lichtheid en tint vast, chroma omlaag tot de kleur past, nooit door de drie kanalen apart af te kappen, want dat verschuift ze verschillend en dus ook de tint. Die stappen zijn gemarkeerd, en de statusbalk telt ze. Zet het aflopen uit om te zien wat constante chroma aan de uiteinden echt oplevert.
Constante tint is het deel dat je kunt zien
De strook onder de schaal is je basiskleur twee keer: één keer gestapt in OKLCH, één keer gemengd naar wit en zwart in sRGB, op dezelfde stap verankerd zodat de vergelijking eerlijk is. De sRGB-methode is geen stroman. Het is wat lighten() en darken() in Sass deden en wat de meeste "tint en shade" snippets nog steeds doen, en het gaat op twee manieren mis die allebei op het scherm staan. De tint verschuift: begin bij oklch(0.55 0.15 57), een middenbruin, en de donkerste sRGB-stap komt 33 graden verderop op het tintwiel terug. Loop alle 360 tinten bij die lichtheid en chroma af en de OKLCH-schaal blijft op elk daarvan binnen 0,013 graden van de basis. En de chroma loopt leeg: #2563eb voor 90% naar zwart gemengd landt op #040a18, oftewel lichtheid 0,145 waar de ladder 0,235 vraagt en chroma 0,032 tegen 0,109. Het donkere uiteinde van een sRGB-menging is geen diepe versie van je kleur, het is een bijna zwart met een spoortje ervan erin.
Veelvoorkomende problemen
- De 500 is niet mijn merkkleur. Dat wordt hij ook niet, tenzij je kleur al rond lichtheid 0,642 zit. De tool markeert de stap waar de eigen lichtheid van je kleur hem legt en geeft hem daar exact weer, in plaats van stiekem een andere kleur terug te geven onder het label dat je vroeg.
- De schaal komt niet overeen met de canonieke lichtheid van Tailwind. De ladder wordt uitgerekt zodat jouw kleur precies op zijn eigen stap landt, en hoe verder je kleur van die trede zit, hoe verder de hele schaal meeschuift. Die verschuiving blijft binnen een halve stap. Je basis richting een trede duwen trekt de hele schaal strakker.
- Elke stap ziet eruit als hetzelfde grijs. Je basis heeft vrijwel geen chroma, en in een grijs zit geen tint om over een schaal mee te nemen. Dat is een prima neutrale schaal, alleen geen gekleurde. Zet de chroma van de basis hoger als je kleur wilde.
- Het Tailwind-blok doet niets.
@themeis v4-syntaxis en het blok gaat direct onder je regel@import "tailwindcss";. Een v3-project negeert het volledig en wil de waarden intheme.extend.colorsintailwind.config.js. Neem daarvoor de JSON-export. - De variabelenaam is niet die je typte. Het veld wordt geslugificeerd, dus
Acme Bluewordtacme-blue, en een naam die met een cijfer begint krijgt er een letter voor, want$500-50is een parsefout in Sass en geen waarschuwing.
Veelgestelde vragen
Waarom landde mijn kleur op 600 in plaats van 500?
Omdat zijn lichtheid hem daar legt. De pagina opent op #2563eb, het blauw dat Tailwind tot en met v3 als blue-600 leverde: zijn OKLCH-lichtheid is 0,546 en de trede 600 van de ladder ligt op 0,549, dus hem een 500 noemen zou er een hele stap naast zitten. De meeste merkkleuren zijn gekozen om als knop of link te werken, en dat zet ze in de band van 500 tot 700 in plaats van op een bepaald getal.
Exporteer ik hex of OKLCH?
OKLCH voor alles wat je later nog bewerkt, hex voor alles dat moet draaien in een browser van voor mei 2023. Elke waarde hier valt binnen sRGB, dus de twee notaties benoemen dezelfde pixel. Het verschil zit in het bewerken: het eerste getal in oklch(0.6397 0.1925 262.88) aanpassen verandert de lichtheid en verder niets, terwijl een byte in een hexwaarde aanpassen lichtheid, chroma en tint tegelijk verandert. oklch() zit in Chrome 111, Safari 15.4 en Firefox 113, en is waar het palet van Tailwind zelf in geschreven is.
Welke tekstkleur kan ik op elke stap zetten?
Elk staal draagt een badge die de inkt noemt die er WCAG 2.1 AA op haalt, bij 4,5:1 voor gewone tekst, plus de verhouding waarmee hij dat haalt. Zwart of wit slaagt altijd, want de twee verhoudingen vermenigvuldigen voor elke kleur tot precies 21 en 4,5 keer 4,5 is 20,25. De badge zegt dus niet of het slaagt of zakt, maar aan welke van de twee je vastzit. Contrast is symmetrisch, dus een stap waarvan de badge zwart zegt, is ook een stap die je niet voor lopende tekst op een witte pagina kunt gebruiken. De contrastchecker rekent dezelfde getallen door voor een specifiek paar.
Kan ik hier een neutrale grijsschaal mee bouwen?
Ja, en het loont om dat bewust te doen. Voer er een bijna-grijs in met een spoor van je merktint, rond 0,01 tot 0,02 chroma, in plaats van een echt grijs. Het aflopen schaalt dat spoor mee met de chroma die het gamut op elke lichtheid werkelijk heeft, dus op 950 zit er nog een vleugje tint in, in plaats van dat het wegloopt zoals bij een sRGB-menging, en een neutraal met een spoor van de merktint is precies wat voorkomt dat een interface op een wireframe lijkt.
Wat kan deze tool niet?
Het levert een startpunt op, geen afgemaakt merkpalet. Het kent één kleur en het rekenwerk van lichtheid; het weet niet dat je 100 onder een bepaalde foto moet liggen, dat de juridische afdeling één exacte hex voor het logo heeft goedgekeurd, of dat je 700 ook de uitgeschakelde status is en het in één oogopslag van de 600 moet verliezen. Echte systemen stellen na het genereren nog twee of drie stappen met de hand bij, en de kleurschalen van Tailwind zelf zijn zo ver met de hand bijgesteld dat geen enkele formule hun 300 en 400 reproduceert. Genereer eerst, en toets daarna de uiteinden tegen de vlakken waar ze echt op komen te liggen. Combineer het met de paletgenerator als je de andere kleuren nodig hebt die hierbij passen.