Обзор на браузерные API, которые стали Widely available в ноябре 2025. Раз в месяц я буду вам напоминать, что вы уже можете использовать в проде.
Каждый месяц выходят новые CSS-свойства, HTML-атрибуты, JavaScript-методы и WebAPI, но применять в проде мы их конечно же не будем. 2.5 года назад также каждый месяц выходили новые фичи в браузере, а вот их уже пора начинать применять.
Как мы понимаем, что уже можно использовать в проде?
У каждой компании, да что уж там компании, у каждой команды в компании своя методика принятия решения о внедрении той или иной фичи в проекте.
Общий же сценарий выглядит так:
- Посмотрели в пользовательские метрики. Поняли какими браузерами и их версиями в основном пользуются пользователи проекта;
- Заглянули в caniuse и поняли, какие фичи уже поддерживаются большинством браузеров;
- Приняли решение о внедрении той или иной фичи в проект.
Какие-то команды позволяют себе указывать правило "последние три версии браузеров". У других специфика проекта, что проект работает исключительно на iPad с Safari. Сами понимаете, все мы разные и требования разные, и у каждого свой подход.
Baseline - позволяет немного упростить процесс принятия решения о внедрении той или иной фичи в проект. Если фича Widely available значит фича уже как минимум есть во всех основных браузерах как минимум стабильно используются последние 2.5 года.
Какие фичи в вебе стали Widely available в ноябре 2025?
color()— функция для работы с цветовыми пространствами (Display P3, Rec.2020 и др.)color-mix()— смешение цветов в заданном цветовом пространствеCompression Streams API — нативное сжатие и распаковка данных (gzip, deflate)
:nth-child(… of <selector>)— улучшенный псевдокласс для точного выбора элементовOklab и OkLCh — восприятие-ориентированные цветовые пространства
WebRTC:
RTCPeerConnection.sctp— доступ к информации о SCTP-транспортеLab и LCH — научно обоснованные цветовые пространства CIE
1. color()
Функция color() позволяет задавать цвет непосредственно в нужном цветовом пространстве, а не только в привычном srgb. Это особенно важно для современных дисплеев с широким цветовым охватом (wide-gamut).
Стандартное srgb охватывает лишь часть цветов, которые способен воспринимать человек — и тем более, часть цветов, которые способны отобразить современные экраны. Цветовые пространства вроде Display P3, Rec.2020 или ProPhoto RGB позволяют отображать более насыщенные, яркие и точные оттенки.
? Пример: в
srgbневозможно отобразить «реальный» красный цвет, который виден на дисплее с Display P3. Сcolor(display-p3 1 0 0)— можно.
Синтаксис
color(<colorspace> <coordinates>)
Поддерживаемые цветовые пространства включают:
srgb— стандартное RGB (0–1 или 0%–100%)srgb-linear— линейное RGB (для физически корректных вычислений)display-p3— широко используемое в Apple-устройствах и HDR-контентеrec2020— для Ultra HD и HDR видеоa98-rgb— Adobe RGBprophoto-rgb— для профессиональной цветокоррекцииxyz/xyz-d50/xyz-d65— CIE XYZ, базовое цветовое пространство
Примеры
/* Яркий красный в Display P3 */
.banner {
background-color: color(display-p3 1 0 0);
}
/* Мягкий серый в линейном sRGB */
.text {
color: color(srgb-linear 0.7 0.7 0.7);
}
/* Насыщенный зелёный в Rec.2020 */
.video-overlay {
border-color: color(rec2020 0 0.9 0);
}
Координаты указываются в диапазоне 0–1 (или в процентах, где 1 = 100%). В отличие от rgb(), здесь нет альфа-канала — если нужна прозрачность, используйте color(display-p3 1 0 0 / 0.8) (поддержка / для альфы зависит от браузера, но в Baseline 2025 — уже есть).
Практика: улучшение визуального восприятия на современных устройствах
Если ваш бренд использует насыщенные фирменные цвета (например, яркий синий или зелёный), они будут выглядеть тускло в sRGB, но восхитительно — на iPhone или MacBook с P3-дисплеем.
:root {
--brand-primary: color(display-p3 0 0.6 1); /* насыщенный синий */
}
.hero {
background-color: var(--brand-primary);
}
Практика: Создание HDR-совместимых интерфейсов
Для приложений, работающих с фотографиями, видео или творческими инструментами, точная цветопередача критична. color() даёт доступ к тем оттенкам, которые раньше были «заперты» в браузере.
Практика: Плавные градиенты и анимации в wide-gamut
Смешение цветов в Display P3 через color-mix() или градиенты с color() даёт более естественные переходы без «серых провалов», характерных для sRGB.
2. color-mix()
Функция color-mix() позволяет плавно смешивать два цвета в заданном цветовом пространстве — прямо в CSS, без препроцессоров или JavaScript. Это особенно ценно, потому что результат смешения зависит от выбранного цветового пространства: в srgb переходы могут выглядеть неестественно, а в Oklab, LCH или Display P3 — гладко и предсказуемо.
Раньше, чтобы получить оттенок цвета, приходилось вручную подбирать HEX/RGB-значения или использовать Sass-функции вроде mix() или darken(). Теперь браузер сам корректно смешает цвета — с учётом того, как человек воспринимает яркость и насыщенность.
? Пример: если смешать синий и чёрный в
srgb, получится тусклый, «грязный» оттенок. Вoklab— насыщенный тёмно-синий, сохраняющий чистоту тона.
Синтаксис
color-mix(in <colorspace>, <color> <percentage>, <color> <percentage>?)
<colorspace>— цветовое пространство, в котором происходит смешение (srgb,oklab,lch,display-p3и др.).Первый
<color>и<percentage>— первый цвет и его доля (например,70%).Второй цвет необязательно указывать с процентом: если не указан, берётся остаток до 100%.
Если процент не задан ни для одного цвета, по умолчанию используется 50/50.
Примеры
/* Смешать красный и белый в srgb (получим розовый) */
.button {
background-color: color-mix(in srgb, red, white 30%);
}
/* Осветлить фирменный синий на 20% в Oklch — без потери насыщенности */
.card {
border-top-color: color-mix(in oklch, var(--brand-blue) 80%, white);
}
/* Создать тёмный вариант фона для темной темы */
:root[data-theme="dark"] {
--surface: color-mix(in oklab, var(--brand-gray) 90%, black);
}
? Проценты можно указывать только для одного цвета — второй автоматически дополняет до 100%.
Например:
color-mix(in lch, blue 70%, white)= 70% синего + 30% белого.
Практика: динамические темы и оттенки без препроцессоров
С color-mix() вы можете генерировать всю палитру прямо в CSS:
светлые и тёмные варианты основных цветов,
hover-состояния кнопок,
градиенты с живыми переходами.
:root {
--primary: oklch(65% 0.25 260);
--primary-light: color-mix(in oklch, var(--primary), white 85%);
--primary-dark: color-mix(in oklch, var(--primary), black 90%);
}
Практика: адаптивные цвета для wide-gamut-дисплеев
Смешивайте цвета в display-p3, чтобы сохранить насыщенность даже в производных оттенках:
.hero-gradient {
background-image: linear-gradient(
to right,
color-mix(in display-p3, var(--vibrant-red) 90%, white),
color-mix(in display-p3, var(--vibrant-blue) 90%, white)
);
}
Практика: естественные градиенты и анимации
Поскольку color-mix() работает в восприятие-ориентированных цветовых пространствах (вроде Oklab или LCH), анимации и градиенты выглядят плавно, без «серых провалов» или неожиданного изменения яркости — чего нельзя добиться в rgb() или hsl().
Важно: цветовое пространство влияет на результат
Сравните:
/* В srgb — тусклый, «мыльный» розовый */
.pink-srgb { background-color: color-mix(in srgb, red, white 70%); }
/* В oklch — чистый, насыщенный пастельный розовый */
.pink-oklch { background-color: color-mix(in oklch, red, white 70%); }

Именно поэтому color-mix() особенно мощен в связке с современными цветовыми пространствами — oklab, lch, display-p3.
3. Compression Streams API
Compression Streams API — это встроенный в браузер инструмент для сжатия и распаковки данных с использованием алгоритмов gzip и deflate. Теперь вы можете обрабатывать объёмы данных в десятки и сотни мегабайт прямо в клиенте — без библиотек, без сервера и без блокировки основного потока.
Раньше для сжатия в браузере приходилось:
подключать тяжёлые библиотеки вроде
pakoилиfflate,жертвовать производительностью (всё происходило синхронно),
или отправлять данные на сервер только ради архивации.
Теперь всё это делается нативно, асинхронно и построчно, через потоки (Streams API).
? Пример: вы собираете логи работы приложения — 50 МБ текста. Вместо отправки «как есть», вы сжимаете их в gzip на лету и отправляете пакет в 5 МБ. Экономия трафика — 90%.
Синтаксис
API работает через два класса:
CompressionStream(format)— сжимает данныеDecompressionStream(format)— распаковывает
Поддерживаемые форматы:
'gzip''deflate'
Оба класса принимают поток на вход и возвращают преобразованный поток на выход, что позволяет легко встраивать их в цепочки обработки.
Практика: сжатие текста в gzip
async function compressText(text) {
const stream = new Blob([text]).stream();
const compressedStream = stream.pipeThrough(new CompressionStream('gzip'));
const compressedBlob = await new Response(compressedStream).blob();
return compressedBlob;
}
// Использование
const logData = 'User performed action X...'; // длинная строка
const compressed = await compressText(logData);
console.log('Original size:', logData.length);
console.log('Compressed size:', compressed.size);
Практика: распаковка полученного файла
async function decompressBlob(blob) {
const stream = blob.stream();
const decompressedStream = stream.pipeThrough(new DecompressionStream('gzip'));
const text = await new Response(decompressedStream).text();
return text;
}
? Всё работает через ReadableStream → TransformStream → ReadableStream, поэтому вы можете комбинировать сжатие с шифрованием, отправкой через
fetch, записью в IndexedDB и т.д.
Практика: отправка аналитики и логов с минимальным трафиком
Собираете события, ошибки, метрики производительности? Сжимайте их перед отправкой:
const events = JSON.stringify(collectedEvents);
const blob = await compressText(events);
await fetch('/api/logs', {
method: 'POST',
body: blob,
headers: { 'Content-Encoding': 'gzip' }
});
Сервер (например, Nginx или Cloudflare) может автоматически распаковать такие данные, если указан правильный заголовок.
Практика: Работа с большими файлами в веб-приложениях
Пользователь загрузил CSV или JSON-файл размером 100 МБ? Вы можете:
сжать его перед сохранением в
IndexedDB,позволить экспортировать «архив» без участия сервера,
предварительно обработать перед отправкой на бэкенд.
Практика: обработка данных в офлайне
В PWA или оффлайн-редакторе можно сжимать документы на лету и сохранять их компактно — особенно полезно на устройствах с ограниченным хранилищем.
Совместимость с существующими форматами
Файлы, сжатые через CompressionStream('gzip'), — это стандартные .gz-файлы. Их можно открыть любым архиватором или сервером. То же самое с deflate.
4. :nth-child(… of <selector>)
Псевдокласс :nth-child() получил долгожданное улучшение: теперь он может считать только те элементы, которые соответствуют заданному селектору, а не всех подряд. Это решает одну из самых раздражающих проблем CSS — невозможность точно выбрать «n-й элемент нужного типа» среди всех соседей.
Раньше :nth-child(2) означало «второй дочерний элемент вообще», даже если он не был нужного тега или класса. Чтобы выбрать, например, вторую кнопку среди множества других элементов, приходилось использовать костыли: обёртки, кастомные классы или JavaScript.
Теперь синтаксис :nth-child(An+B of S) позволяет писать точные, читаемые и семантически верные селекторы — прямо в CSS.
? Пример: у вас список из 10 элементов: чередуются
<div>,<button>,<span>. Вы хотите выделить вторую кнопку. Раньше — почти невозможно без классов. Теперь —button:nth-child(2 of button).
Синтаксис
:nth-child(An+B of <селектор>)
:nth-last-child(An+B of <селектор>)
An+B— стандартная формула (например,2,odd,3n+1).<селектор>— любой валидный CSS-селектор (класс, тег, атрибут и т.д.).Отсчёт ведётся только среди элементов, соответствующих селектору, но позиция проверяется в контексте всех соседей.
Аналогично работает :nth-last-child(… of …) — отсчёт с конца.
Примеры
/* Второй элемент с классом .item */
.item:nth-child(2 of .item) {
border-top: 2px solid red;
}
/* Каждая нечётная кнопка среди всех кнопок */
button:nth-child(odd of button) {
background-color: #f0f0f0;
}
/* Последний активный пункт меню */
.menu-item:nth-last-child(1 of .menu-item.active) {
margin-bottom: 0;
}
/* Третий <li> с атрибутом data-visible="true" */
li:nth-child(3 of [data-visible="true"]) {
font-weight: 700;
}
? Важно: элемент должен одновременно соответствовать селектору и занимать n-ю позицию среди таких же. Но сама проверка позиции учитывает всех соседей — это соответствует логике DOM.
Практика: стилизация динамических списков без JavaScript
В React, Vue или другом фреймворке часто рендерятся списки с условной логикой:
<ul>
<li class="ad">Реклама</li>
<li class="post">Пост 1</li>
<li class="ad">Реклама</li>
<li class="post">Пост 2</li>
<li class="post">Пост 3</li>
</ul>
Как выделить второй пост? Раньше — только через :nth-of-type() (не работает с классами) или кастомный data-index. Теперь:
.post:nth-child(2 of .post) {
border-left: 4px solid #007AFF;
}
Практика: гибкие таблицы и карточки
В адаптивных сетках или таблицах с условным отображением строк (например, «скрытые» или «заблокированные») можно точно стилизовать каждую n-ю видимую запись:
.row:nth-child(even of .row:not(.hidden)) {
background-color: #fafafa;
}
Чистые и поддерживаемые компоненты
Больше не нужно генерировать классы вроде .item--index-2 на стороне JS. Вся логика — в CSS, а структура остаётся семантичной.
5. Oklab и OkLCh
Oklab и OkLCh — это современные цветовые пространства, созданные не для машин, а для человеческого восприятия. В отличие от привычных rgb() или hsl(), они обеспечивают равномерные градиенты, предсказуемую яркость и естественное смешение цветов — без «серых провалов», неожиданной потери насыщенности или странного поведения при анимациях.
Раньше, чтобы добиться плавного перехода от тёмно-синего к светло-голубому, приходилось подбирать промежуточные цвета вручную или использовать сложные алгоритмы в JavaScript. Теперь всё это работает нативно в CSS через функции oklab() и oklch().
? Пример: если вы создадите градиент
linear-gradient(hsl(240, 100%, 30%), hsl(240, 100%, 80%)), в середине он станет неожиданно серым. Сoklch(50% 0.3 240)→oklch(80% 0.3 240)— переход будет гладким и насыщенным от начала до конца.
Что такое Oklab и OkLCh?
Oklab — трёхмерное цветовое пространство с координатами:
L — светлота (0% = чёрный, 100% = белый),
a — от зелёного (–) к красному (+),
b — от синего (–) к жёлтому (+).
OkLCh — та же система, но в полярных координатах (как HSL, но умный):
L — светлота,
C — хрома (насыщенность),
h — оттенок (hue) в градусах (0–360°).
Синтаксис
/* Oklab: L a b */
color: oklab(60% 0.1 -0.05);
/* OkLCh: L C h */
color: oklch(70% 0.25 260);
L — от
0%до100%(или0–1).a, b — обычно от
–0.4до+0.4(но могут выходить за пределы).C — хрома, чем выше, тем насыщеннее (максимум ≈
0.4для отображаемых цветов).h — оттенок в градусах, как в
hsl().
Поддерживается альфа-канал через /:
background-color: oklch(80% 0.15 120 / 0.9);
Примеры
/* Насыщенный фиолетовый */
.card-header {
background-color: oklch(65% 0.3 300);
}
/* Тёплый серый без цветового оттенка */
.text-muted {
color: oklab(50% 0 0);
}
/* Плавный акцентный цвет с контролируемой насыщенностью */
:root {
--accent: oklch(72% 0.22 45); /* золотисто-оранжевый */
}
Практика: создание гармоничных тем и палитр
Поскольку L (светлота) отделена от C (насыщенности), вы можете:
менять яркость темы, не трогая оттенок,
генерировать оттенки с одинаковой насыщенностью,
легко строить контрастные пары по WCAG.
:root {
--primary-hue: 260;
--primary-500: oklch(68% 0.25 var(--primary-hue));
--primary-300: oklch(82% 0.25 var(--primary-hue)); /* светлее, но той же насыщенности */
--primary-700: oklch(50% 0.25 var(--primary-hue)); /* темнее */
}
Практика: естественные градиенты и анимации
Градиенты в OkLCh не теряют насыщенность посередине:
.hero {
background-image: linear-gradient(
to right,
oklch(70% 0.25 220),
oklch(70% 0.25 300)
);
}
Анимация яркости или насыщенности теперь выглядит физически корректно:
.button:hover {
color: oklch(60% 0.28 260);
transition: color 0.2s ease;
}
Точные цветовые вычисления с color-mix()
Oklab и OkLCh — идеальные цветовые пространства для color-mix(), потому что смешение в них сохраняет воспринимаемую яркость:
/* Осветление без «побеления» */
.hover-bg {
background-color: color-mix(in oklch, var(--brand) 90%, white);
}
6. WebRTC: RTCPeerConnection.sctp
Свойство sctp в интерфейсе RTCPeerConnection наконец стало Widely available — и с ним в веб приходит прямой доступ к информации о SCTP-транспорте, лежащем в основе RTCDataChannel. Это не просто «ещё одно свойство», а важный шаг к отладке, мониторингу и управлению P2P-соединениями на уровне, который раньше был доступен только в нативных приложениях.
До появления pc.sctp разработчики WebRTC-приложений были «слепы» к состоянию канала данных: они могли отправлять и получать сообщения, но не видели, насколько велик буфер, поддерживается ли соединение, каков максимальный размер сообщения и работает ли транспорт вообще.
? Пример: вы отправляете 10 МБ данных через
RTCDataChannel, но соединение нестабильно. Безsctpвы не узнаете, почему — то ли сеть, то ли превышен лимит. Сpc.sctp.maxMessageSizeиpc.sctp.state— получаете точные метрики.
Что такое SCTP и зачем он нужен?
SCTP (Stream Control Transmission Protocol) — это транспортный протокол, используемый WebRTC для надёжной или частично надёжной передачи данных через RTCDataChannel. Он обеспечивает:
упорядоченную или неупорядоченную доставку,
управление потоками,
контроль перегрузки,
безопасность (через DTLS).
Хотя вы работаете с RTCDataChannel, «под капотом» всё это управляется SCTP — и теперь вы можете заглянуть «под капот».
Синтаксис и доступные данные
После установки соединения (обычно после negotiationneeded и iceconnectionstatechange) у RTCPeerConnection появляется объект sctp:
const pc = new RTCPeerConnection();
const channel = pc.createDataChannel('messaging');
// Позже, когда соединение установлено:
pc.addEventListener('connectionstatechange', () => {
if (pc.sctp) {
console.log('SCTP ready!');
console.log('Max message size:', pc.sctp.maxMessageSize);
console.log('State:', pc.sctp.state); // "connected", "closed" и т.д.
}
});
Основные свойства RTCSctpTransport:
maxMessageSize— максимальный размер одного сообщения в байтах (часто ~64 КБ, но зависит от реализации).state— состояние транспорта:"new","connecting","connected","closed".transport— ссылка на underlying DTLS-транспорт (для продвинутой диагностики).
?
maxMessageSizeособенно важен: если вы попытаетесь отправить сообщение больше этого значения — оно не будет доставлено, и ошибки в консоли может не быть!
Практика: безопасная отправка больших данных
Разбивайте большие сообщения на чанки, зная точный лимит:
function sendLargeMessage(channel, pc, data) {
const maxSize = pc.sctp?.maxMessageSize || 16384; // fallback
const chunks = splitIntoChunks(data, maxSize);
chunks.forEach(chunk => channel.send(chunk));
}
Практика: мониторинг и отладка в продакшене
Логируйте состояние соединения для анализа проблем:
if (pc.sctp) {
analytics.track('webrtc-sctp', {
state: pc.sctp.state,
maxMessageSize: pc.sctp.maxMessageSize,
browser: navigator.userAgent
});
}
Практика: улучшение UX в P2P-приложениях
Если pc.sctp.state === 'closed', вы можете:
показать уведомление «Соединение с коллегой потеряно»,
предложить переподключиться,
автоматически переключиться на резервный канал.
7. Lab и LCH
Lab и LCH — это научно обоснованные цветовые пространства, разработанные ещё в 1976 году Комитетом по освещению (CIE), но до недавнего времени недоступные в CSS. Теперь, став Widely available в Baseline (ноябрь 2025), они открывают веб-разработчикам доступ к точной, восприятие-ориентированной модели цвета, где яркость, насыщенность и оттенок ведут себя предсказуемо — в отличие от rgb() или hsl().
Если rgb() описывает, как смешать свет, а hsl() — попытка упростить это для человека, то Lab/LCH описывают, как человек видит цвет. Это разница между «технической инструкцией» и «психофизиологией».
? Пример: в
hsl(0, 100%, 50%)(красный) иhsl(60, 100%, 50%)(жёлтый) значение «lightness» одинаково — 50%. Но на глаз жёлтый выглядит гораздо светлее. В LCH светлота (L) соответствует реальному восприятию: жёлтый будет иметьL ≈ 97%, а красный —L ≈ 54%.
Синтаксис
/* Lab: L a b */
color: lab(54% 81 69); /* красный */
color: lab(97% -21 94); /* жёлтый */
/* LCH: L C H */
color: lch(54% 106 41); /* тот же красный */
color: lch(97% 96 100); /* тот же жёлтый */
L — от
0%до100%.a, b — обычно от
–100до+100(но могут быть и больше).C — хрома, теоретически до ~
130, но на практике ограничен отображаемыми цветами.H — оттенок в градусах, как в
hsl().
Поддержка прозрачности через /:
background-color: lch(70% 50 260 / 0.85);
Примеры
/* Точный нейтральный серый — без цветового оттенка */
.text {
color: lab(50% 0 0);
}
/* Яркий, но не «вырвиглазный» акцент */
.button {
background-color: lch(65% 60 320); /* насыщенный пурпурный */
}
/* Гармоничная палитра с фиксированной насыщенностью */
:root {
--hue: 180;
--primary-500: lch(70% 40 var(--hue));
--primary-300: lch(85% 40 var(--hue));
--primary-700: lch(50% 40 var(--hue));
}
Практика: семантические цветовые системы
Меняйте только оттенок или только яркость, не затрагивая остальное:
/* Все кнопки — разные оттенки, но одинаковой насыщенности и яркости */
.button--alarm { background: lch(68% 45 30); }
.button--green { background: lch(68% 45 140); }
.button--blue { background: lch(68% 45 260); }
Практика: точное смешение с color-mix()
LCH — отличное пространство для color-mix(), особенно если вы хотите сохранить воспринимаемую яркость:
.hover-bg {
background-color: color-mix(in lch, var(--brand) 90%, white);
}
Отличия от Oklab/Oklch
Lab/LCH и Oklab/Oklch похожи, но есть нюансы:
Lab/LCH — стандарт CIE, используется в полиграфии, фотографии, науке.
Oklab/Oklch — более новая модель, оптимизированная под отображаемые цвета и часто даёт чуть более насыщенные результаты в вебе.
Обе работают отлично, но LCH — «промышленный стандарт», а OkLCh — «оптимизирован для веба».
Выбор зависит от задачи. Для большинства UI — подойдёт Oklab/Oklch . Для точной цветопередачи (например, в дизайн-системах медицинских или печатных приложений) — предпочтителен LCH.
Следующий выпуск — в начале января 2026 года после праздников. До встречи!
JerryI
Это чё за хуйня?!
Прям совсем насрать на аудиторию?
nikolayshabalin Автор
Не думал, что нейрокартинки могут так задеть. Ради вас удалил
JerryI
Обзор то хороший.
Если совсем нет иллюстраций - это не страшно, кодовые вставки уже разбавляют текст.
nikolayshabalin Автор
А я в целом согласен с мыслью, что лучше уж без картинок, чем с такими. Я действительно на них потратил недостаточно времени. Могу лишь их оправдать тем, что они были декоративными, чем информативными. Поэтому без зазрения совести их удалил.
Проблема таких длинных, а в наше время такие тексты считаются длинными, в том, что у людей не хватает ресурсов на концентрацию, поэтому рекомендуют разбавлять тексты картиночками
Dartess
Ну вставьте котика.