Podczas tworzenia komponentów interfejsu wielokrotnego użytku (takich jak plakietki lub przyciski) lub obsługi motywów dynamicznych zapewnienie czytelności tekstu na nieprzewidywalnym kolorze tła może być trudne. Funkcja CSS contrast-color() przyjmuje wartość black lub white, maksymalizując współczynnik kontrastu w stosunku do określonego koloru tła.
Określanie optymalnego koloru tekstu
Gdy element ma zmienny lub dynamicznie wstawiany kolor tła, możesz polegać na przeglądarce, która obliczy najbezpieczniejszy kolor tekstu.
OBOWIĄZKOWE: ustaw właściwość color za pomocą funkcji contrast-color(), przekazując kolor tła (lub jego właściwość niestandardową) jako 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));
}
NIE: używaj contrast-color() do background-color. Została zaprojektowana specjalnie do kolorów pierwszego planu (takich jak tekst lub obramowanie), aby kontrastowały z danym kolorem tła.
Integracja z motywami
contrast-color() akceptuje dowolną prawidłową wartość <color>, w tym właściwości niestandardowe CSS, dlatego jest szczególnie przydatna w systemach projektowania. Dzięki scentralizowaniu motywów tła jako zmiennych kontrast treści na pierwszym planie jest automatycznie aktualizowany przy każdej zmianie motywu, nawet w przypadku kolorów określonych przez użytkownika.
ZALECANE: odwołuj się do udostępnionych zmiennych tła w funkcji contrast-color(), aby zapewnić synchronizację w aplikacji.
.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);
}
NIE: nie koduj na stałe osobnego koloru tekstu dla każdego stanu interakcji, gdy tło jest dynamiczne. Spowoduje to ponowne wystąpienie niezgodności, której zapobiega contrast-color().
Strategie zastępcze
Aby obsługiwać przeglądarki bez contrast-color(), musisz podać kreację zastępczą. Jeśli kolor tła jest znany i stały, użyj zakodowanego na stałe koloru kontrastującego. W przypadku dynamicznych teł, których kolor jest nieznany, wybierz strategię z tabeli poniżej na podstawie wymagań interfejsu i docelowych przeglądarek.
| Strategia | Najlepsze zastosowanie | Uwagi |
|---|---|---|
| Względna składnia kolorów | Automatyczne, wysokiej jakości obliczanie kontrastu tylko za pomocą CSS. | Najwyższej jakości kreacja zastępcza tylko w CSS. |
| Cień tekstu | Szybka poprawa czytelności na dowolnym tle. | Może wyglądać na „brudny” lub „świecący” i nie pasować do wszystkich projektów. |
| Obrys tekstu | Zachowanie grubości czcionki przy jednoczesnym zapewnieniu kontrastu krawędzi. | Aby uniknąć pocieniania kształtów liter, użyj właściwości paint-order, jeśli jest dostępna. |
| Półprzezroczysta nakładka | Zapewnienie minimalnego obszaru kontrastu za tekstem. | Zmienia wygląd koloru tła pod tekstem, wymaga osobnego elementu tekstowego. |
| Filtry SVG | Reaktywny kontrast, który aktualizuje się wraz ze zmianą tła. | Wymaga osobnego elementu tekstowego; nieoptymalne wdrożenie. |
Zalecane: składnia względnych kolorów (RCS)
W przypadku przeglądarek, które obsługują tę funkcję, RCS zapewnia najbardziej niezawodne automatyczne zastępowanie kolorów dynamicznych.
@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));
}
}
Alternatywne usługi porównywania cen
ZALECANE: wybierz kreację zastępczą, która najlepiej pasuje do ograniczeń projektowych, jeśli RCS nie jest wystarczający lub obsługiwany.
Opcja 1. Obrys tekstu
.badge--stroke {
-webkit-text-stroke: 4px black;
}
Opcja 2. Obrys tekstu o szerokości paint-order, aby zachować kształt liter
.badge--stroke {
-webkit-text-stroke: 4px black;
paint-order: stroke fill;
}
Opcja 3. Półprzezroczysta nakładka tła
.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;
}
Opcja 4. Cień tekstu
.badge--shadow {
text-shadow: 0 1px 3px rgb(0 0 0 / 0.8);
}
Opcja 5. Filtry SVG
Wczytaj tę definicję filtra SVG. Jeśli chcesz obsługiwać wersje Safari, których dotyczy ten błąd WebKit, który uniemożliwia stosowanie zewnętrznych odwołań i odwołań do adresów URL danych w przypadku filtrów, musisz dodać go bezpośrednio do dokumentu HTML. W przeciwnym razie należy go wczytać z pliku zewnętrznego, czyli pliku SVG lub wbudowanego w 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>Zawijaj tekst w
<span>.<div class="badge--svg"> <span>Badge content</span> </div>Zastosuj filtr do
<span>.
.badge--svg span{
color: var(--badge-bg);
filter: url(#contrast-filter);
}