Дайджесты новостей
Геометрическая композиция в стиле Баухаус с карточками разной высоты и наклона, иллюстрирующая CSS-функцию random() и кинетическую прокрутку scroll-snap.

Новинки Chrome 156 и веб-стандартов: случайные числа в CSS, :navigation-source и scroll-snap

Каждый релиз браузера Chromium — это заметное событие для фронтенд-сообщества. Но если минорные версии часто ограничиваются устранением мелких регрессий и внутренними оптимизациями компилятора V8, то вышедший Chrome 156 приносит сразу несколько долгожданных стандартов, которые кардинально упрощают жизнь верстальщикам и дизайнерам интерфейсов.

Главная звезда релиза — официальная имплементация математической функции random() из черновика спецификации CSS Values and Units Module Level 5. То, ради чего десятилетиями приходилось генерировать inline-стили на JavaScript или компилировать тысячи строк вспомогательного кода через SCSS-генераторы, теперь работает на уровне движка Blink прямо в таблицах стилей!

Давай подробно разберем все ключевые новшества Chrome 156, посмотрим на синтаксис и выясним, как они изменят наш подход к современной веб-верстке.

Нативная функция random() в CSS: живой хаос без JS

До сегодняшнего дня добавление легкого «живого несовершенства» в веб-интерфейс было настоящей головной болью. Представь типичную дизайнерскую задачу: ты верстаешь россыпь стикеров на интерактивной доске, частицы конфетти или сетку карточек в блоге, и хочешь, чтобы каждая карточка была слегка повернута на случайный угол от -4 до +4 градусов, а цвет фона слегка варьировался.

Раньше приходилось либо писать JavaScript-скрипт, который обходил DOM и навешивал inline-переменные: card.style.setProperty('--angle', Math.random() * 8 - 4 + 'deg'), либо генерировать через Sass-циклы тридцать классов-модификаторов .card--1, .card--2 с зашитыми значениями. Скрипт засорял разметку, ломал серверный рендеринг (SSR) и приводил к раздражающим скачкам при гидратации клиента. А SCSS-подход раздувал итоговый файл стилей на десятки килобайт.

В Chrome 156 функция random() решает эту задачу элегантно и декларативно:

/* Базовый синтаксис: случайное значение в заданном диапазоне */
.sticker {
  /* Случайный угол от -4deg до 4deg с шагом дискретизации 0.5deg */
  transform: rotate(random(-4deg, 4deg, by 0.5deg));
  
  /* Случайная длительность анимации покачивания */
  animation-duration: random(2s, 5s);
  
  /* Случайный оттенок в современном цветовом пространстве Oklch */
  background-color: oklch(0.85 0.12 random(0, 360));
}

/* Эффект праздничного конфетти на чистом CSS */
.confetti-particle {
  left: random(0vw, 100vw, by 5vw);
  animation-duration: random(1.5s, 4s);
  background-color: hsl(random(0, 360), 85%, 60%);
}
Как устроена модель кэширования: защита от вечных перерисовок

Первый логичный вопрос любого вдумчивого инженера: «Если в стилях написано random(), не начнет ли браузер судорожно дергать генератор псевдослучайных чисел на каждый кадр анимации или при наведении мыши (hover)? Не приведет ли это к бесконечному циклу Repaint/Reflow?».

Разработчики спецификации W3C и инженеры движка Blink предусмотрели эту опасность:

  • Вычисление на фазе Style Cascade: случайное значение генерируется один раз в момент применения каскада стилей к конкретному элементу DOM.
  • Привязка к идентификаторам (Seed Keys): движок поддерживает специальный первый аргумент — идентификатор сида. Если передать кастомное имя или атрибут элемента, значение намертво фиксируется за данным ключом:
/* Использование пользовательского идентификатора для детерминированной случайности */
.gallery-card {
  --seed: attr(data-id type(<custom-ident>));
  width: random(--seed, 280px, 340px);
  transform: rotate(random(--seed, -3deg, 3deg));
}

Даже если пользователь многократно скроллит страницу, меняет размеры окна или вызывает пересчет соседних блоков, карточка с data-id="card-42" сохранит ровно тот угол и ширину, которые были вычислены при ее первом появлении.

Прогрессивное улучшение (Progressive Enhancement)

Поскольку Chrome 156 — первый браузер с нативной поддержкой random(), а движки WebKit (Safari) и Gecko (Firefox) еще работают над внедрением, в продакшене обязательно используй директиву @supports:

.sticker {
  transform: rotate(0deg); /* Базовое безопасное значение по умолчанию */
}

@supports (transform: rotate(random(0deg, 10deg))) {
  .sticker {
    transform: rotate(random(-4deg, 4deg, by 0.5deg));
  }
}

Псевдокласс :navigation-source: контекстные переходы

Второе фундаментальное нововведение релиза — псевдокласс :navigation-source.

Инфографика селекторов CSS псевдокласса :navigation-source: адаптивная стилизация веб-страницы в зависимости от источника перехода пользователя.

До сих пор веб-страница была слепа к тому, каким образом пользователь на нее попал. Перешел ли он по прямой ссылке из поисковой выдачи? Нажал ли кнопку «Назад» в панели инструментов браузера? Отправил ли форму методом POST? Или просто нажал комбинацию Ctrl+R для перезагрузки?

Теперь контекст навигации доступен непосредственно в селекторах CSS, открывая фантастические возможности для плавных переходов:

/* Анимации навигации в связке с View Transitions */
@media (prefers-reduced-motion: no-preference) {
  /* Пользователь вернулся назад через историю (BFCache / Back-Forward) */
  :root:navigation-source(traverse) .page-container {
    animation: slideInFromLeft 0.35s ease-out;
  }

  /* Обычный переход вперед по ссылке (Push navigation) */
  :root:navigation-source(push) .page-container {
    animation: slideInFromRight 0.35s ease-out;
  }

  /* Страницу принудительно обновили клавишей F5 или через reload */
  :root:navigation-source(reload) .status-toast {
    display: block;
    animation: fadeInOut 3s forwards;
  }
}

Селектор поддерживает значения push, replace, reload и traverse. Это позволяет избавиться от хрупких JavaScript-перехватчиков истории браузера и настраивать направление выезда экранов исключительно средствами стилей.

О том, как эволюционирует веб-платформа и средства плавной прокрутки, мы также рассказывали в обзоре кастомизации скролла в Chrome 154 и новшеств Chrome 155.

Оптимизация кинетической прокрутки в scroll-snap

Свойство scroll-snap-type стало стандартом для галерей и полноэкранных секций. Но на сенсорных экранах мобильных устройств при быстром и резком смахивании пальцем (инерционный кинетический скролл) пользователи регулярно сталкивались с неприятной проблемой: контейнер пролетал мимо целевого элемента, судорожно отскакивал назад или застревал ровно посередине между двумя слайдами.

В Chrome 156 математика инерционной прокрутки была переписана:

.story-carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  
  /* Жесткая фиксация в Chrome 156: запрет пролета нескольких слайдов за один свайп */
  scroll-snap-stop: always;
}

.story-card {
  flex: 0 0 100vw;
  scroll-snap-align: center;
}

Браузер теперь непрерывно рассчитывает вектор торможения и аккуратно «магнитит» ближайший слайд даже при самом резком движении руки, делая веб-карусели неотличимыми по отзывчивости от нативных экранов iOS и Android.

Что еще появилось в Chrome DevTools?

  • Инспектор диапазонов Scroll-driven Animations: во вкладке Elements появилась интерактивная шкала времени. Перетаскивая ползунок виртуального скролла, можно в миллиметрах видеть, как интерполируются свойства при достижении меток entry 0%, cover 50% и exit 100%.
  • Подсветка мертвого кода стилей в реальном времени: панель Styles теперь динамически маркирует серым цветом те селекторы, которые формально совпали с элементом, но были полностью перекрыты более специфичными правилами или не оказали никакого визуального эффекта на рендеринг.

Chrome 156 доказывает: современный CSS становится все более самостоятельным, мощным и умным языком программирования интерфейсов.