Используй перцептивные цветовые пространства, относительный синтаксис цвета и типизированные математические функции, чтобы строить дизайн-системы, которые браузер считает за тебя.
Открыть этот урок в KodokonСтруктурный изъян hsl(): его светлота не перцептивна. hsl(60 100% 50%) (жёлтый) выглядит ослепительным, а hsl(240 100% 50%) (синий) - тёмным, при одинаковой L. oklch это чинит: компонент L (от 0 до 1) измеряет воспринимаемую светлоту, C - это цветность (абсолютная насыщенность, от 0 примерно до 0.37), а H - угол тона. Изменение H при постоянной L сохраняет воспринимаемую яркость: вариации твоей палитры наконец становятся предсказуемыми. В связке с относительным синтаксисом цвета (from) браузер сам выводит твои варианты для hover, приглушённые или тёмные.
:root {
--brand: oklch(0.65 0.19 255);
--dark: oklch(from var(--brand) calc(l - 0.15) c h);
--muted: oklch(from var(--brand) l calc(c / 2) h);
--accent: oklch(from var(--brand) l c calc(h + 180));
}oklch умеет описывать цвета вне охвата sRGB и даже вне Display-P3. Что делает браузер, когда экран не может их показать? Не грубое обрезание по каналам: спецификация предписывает приведение к охвату (gamut mapping), которое постепенно снижает цветность, сохраняя светлоту и тон, пока цвет не поместится в целевой охват. Экраны с широким охватом можно адресовать явно через @media (color-gamut: p3). Ещё один инструмент смешивания: color-mix(), чей первый аргумент - пространство интерполяции - действительно меняет результат: смесь синего и жёлтого in srgb даёт серый, а in oklch проходит через яркие тона.
.badge {
background: color-mix(in oklch, crimson 70%, white);
border-color: color-mix(
in oklch,
var(--brand),
transparent 60%
);
}min(), max() и clamp() - это типизированные математические функции: они принимают смесь единиц, несовместимых на этапе разбора (rem + vw), потому что разрешение происходит на этапе используемого значения, когда вьюпорт уже известен. clamp(MIN, VAL, MAX) строго эквивалентен max(MIN, min(VAL, MAX)) - отсюда следствие из спецификации: если MIN превышает MAX, побеждает MIN. Для плавной типографики всегда включай составляющую в rem в среднее значение: font-size: clamp(1rem, 2.5vw, 3rem) без rem проигнорирует пользовательское увеличение текста, а это настоящая проблема доступности.
h1 {
font-size: clamp(1.5rem, 1.1rem + 2vw, 3rem);
}
.sidebar {
width: min(30%, 20rem);
padding-left: max(1rem, env(safe-area-inset-left));
}