Als je herbruikbare UI-componenten (zoals badges of knoppen) maakt of dynamische thema's ondersteunt, kan het een uitdaging zijn om te zorgen dat tekst leesbaar is tegen een onvoorspelbare achtergrondkleur. De CSS-functie contrast-color() wordt omgezet in black of white, waardoor de contrastverhouding met de opgegeven achtergrondkleur wordt gemaximaliseerd.
Bepaal de optimale tekstkleur
Als een element een variabele of dynamisch geïnjecteerde achtergrondkleur heeft, kun je de browser de veiligste tekstkleur laten berekenen.
VERPLICHT: Stel de eigenschap color in met de functie contrast-color() en geef de achtergrondkleur (of de aangepaste eigenschap) door als argument.
.badge {
/* Define the background color as a custom property */
--badge-bg: #e02424;
background-color: var(--badge-bg);
/* MANDATORY: Dynamic contrasting color */
color: contrast-color(var(--badge-bg));
}
NIET DOEN: contrast-color() gebruiken voor background-color. Het is speciaal ontworpen voor voorgrondkleuren (zoals tekst of randen) om te contrasteren met een bepaalde achtergrondkleur.
Integreren met thema's
Omdat contrast-color() elke geldige <color>-waarde accepteert, waaronder aangepaste CSS-eigenschappen, is deze functie vooral krachtig binnen ontwerpsystemen. Door je achtergrondthema's te centraliseren als variabelen, zorg je dat het contrast van de content op de voorgrond automatisch wordt geüpdatet als het thema verandert, zelfs naar door de gebruiker opgegeven kleuren.
DO: Reference shared background variables inside contrast-color() to guarantee synchronization across your application.
.theme-card {
background-color: var(--theme-surface-color);
color: contrast-color(var(--theme-surface-color));
}
.theme-container[data-theme="light"] {
--theme-surface-color: #f4f4f4;
}
.theme-container[data-theme="dark"] {
--theme-surface-color: #1a1a1a;
}
.theme-container[data-theme="custom"] {
--theme-surface-color: var(--user-custom-theme);
}
NIET DOEN: Een afzonderlijke tekstkleur hardcoderen voor elke interactiestatus als de achtergrond dynamisch is. Als u dat doet, introduceert u opnieuw de onjuiste overeenkomst die contrast-color() juist probeert te voorkomen.
Reservestrategieën
Als je browsers zonder contrast-color() wilt ondersteunen, moet je een fallback bieden. Als de achtergrondkleur bekend en vast is, gebruik je een hardgecodeerde contrasterende kleur. Kies voor dynamische achtergronden waarvan de kleur onbekend is een strategie uit de tabel hieronder op basis van uw UI-vereisten en doelen voor browserondersteuning.
| Strategie | Meest geschikt voor... | Aandachtspunten |
|---|---|---|
| Relatieve kleursyntaxis | Geautomatiseerde, hoogwaardige contrastberekening alleen voor CSS. | Terugvaloptie met alleen CSS van de hoogste kwaliteit. |
| Tekstschaduw | Snelle verbetering van de leesbaarheid op elke achtergrond. | Kan er 'vies' of 'gloeiend' uitzien en past misschien niet bij alle ontwerpen. |
| Tekststreek | Het lettertypegewicht behouden en tegelijkertijd het randcontrast waarborgen. | Gebruik paint-order om te voorkomen dat lettervormen dunner worden, indien beschikbaar. |
| Doorschijnende overlay | Zorg voor een minimaal contrastgebied achter de tekst. | Hiermee wijzig je de look van de achtergrondkleur onder de tekst. Hiervoor is een afzonderlijk tekstelement vereist. |
| SVG-filters | Reactief contrast dat wordt geüpdatet als de achtergrond verandert. | Vereist een afzonderlijk tekstelement; onhandige implementatie. |
Aanbevolen: Relative Color Syntax (RCS)
Voor browsers die dit ondersteunen, biedt RCS de meest robuuste geautomatiseerde fallback voor dynamische kleuren.
@supports (color: oklch(from red l c h)) {
.badge {
/* Highest threshold that passes WCAG. Higher values may be more legible. */
--threshold: 0.623;
--l: max(0, sign(var(--threshold) - l));
color: oklch(from var(--badge-bg) var(--l) 0 h);
}
}
@supports (color: contrast-color(red)) {
.badge {
color: contrast-color(var(--badge-bg));
}
}
Alternatieve CSS-fallbacks
DO: Selecteer de reserveoptie die het best bij je ontwerpbeperkingen past als RCS niet voldoende is of niet wordt ondersteund.
Optie 1: Tekststreek
.badge--stroke {
-webkit-text-stroke: 4px black;
}
Optie 2: Tekststreep met paint-order om lettervormen te behouden
.badge--stroke {
-webkit-text-stroke: 4px black;
paint-order: stroke fill;
}
Optie 3: Doorschijnende achtergrondoverlay
.badge--overlay {
position: relative;
color: #fff;
overflow: hidden;
}
.badge--overlay::before {
content: "";
position: absolute;
inset: 0;
background-color: rgb(0 0 0 / 0.4);
z-index: 0;
}
.badge--overlay span {
position: relative;
z-index: 1;
}
Optie 4: Tekstschaduw
.badge--shadow {
text-shadow: 0 1px 3px rgb(0 0 0 / 0.8);
}
Optie 5: SVG-filters
Laad deze svg-filterdefinitie. Je moet het rechtstreeks aan het HTML-document toevoegen als je Safari-versies wilt ondersteunen die worden beïnvloed door deze WebKit-bug, waardoor externe en gegevens-URL-verwijzingen voor filters worden voorkomen. Anders moet het worden geladen vanuit een extern bestand, een svg-bestand of inline in css.
<!-- Technique from https://miunau.com/posts/dynamic-text-contrast-in-css/ --> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="0" style="display: none;"> <defs> <filter id="contrast-filter" color-interpolation-filters="sRGB"> <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/> <feMorphology operator="dilate" radius="2"/> <feComponentTransfer> <feFuncR type="linear" slope="-255" intercept="128"/> <feFuncG type="linear" slope="-255" intercept="128"/> <feFuncB type="linear" slope="-255" intercept="128"/> </feComponentTransfer> <feComposite operator="in" in2="SourceGraphic"/> </filter> </defs> </svg>Zet de tekst in een
<span>.<div class="badge--svg"> <span>Badge content</span> </div>Pas het filter toe op de
<span>.
.badge--svg span{
color: var(--badge-bg);
filter: url(#contrast-filter);
}