Обзор на браузерные 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 RGB

  • prophoto-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%); }
Jдин и тот же розовый разный в разных цветовых пространствах
Jдин и тот же розовый разный в разных цветовых пространствах

Именно поэтому 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% (или 01).

  • 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 года после праздников. До встречи!