Дайджесты новостей
Сюрреалистический натюрморт с фотокарточками Polaroid под органичными случайными углами поворота и идеальным квадратом по правилам CSS random().

Контролируемый хаос в CSS: возможности и ограничения новой функции random()

Посмотри на окружающий физический мир: в нем практически нет идеальных прямых линий и математически стерильных поверхностей. Листья на ветру колышутся с разной частотой, снимки Polaroid на рабочем столе ложатся под произвольными углами, а в классической типографской печати литеры букв всегда имеют микроскопический, едва уловимый наклон. Именно эти крошечные шероховатости делают аналоговый мир живым, теплым и осязаемым.

А теперь открой любой современный веб-интерфейс: пиксельная строгость, жесткие модульные сетки, одинаковые карточки и параллельные бегущие строки. Веб долгие годы страдал от математической стерильности. Когда же фронтенд-инженеры пытались добавить в верстку немного «живого несовершенства» (playful imperfection), им приходилось выбирать между двумя одинаково плохими компромиссами:

  1. Вызывать Math.random() в JavaScript. Это приводило к дерганию интерфейса при гидратации, ухудшало метрику Cumulative Layout Shift (CLS) и нагружало процессор устройства.
  2. Использовать препроцессоры вроде Sass, генерируя сотни строк громоздкого CSS с жестко прописанными псевдоклассами :nth-child(n) для псевдослучайных поворотов.

В спецификации CSS Values and Units Module Level 5 рабочая группа W3C наконец-то предложила нативное браузерное решение: функцию random(). В большом исследовании на страницах Smashing Magazine бельгийский дизайнер и разработчик Брехт Де Рюйте подробно исследовал ее возможности на реальных примерах. Давай разберем, как устроена эта магия, почему случайность в CSS обязана быть детерминированной и как подготовить свои стили к новой эпохе.

Анатомия синтаксиса: границы, размерности и шаги сетки

Базовый синтаксис функции выглядит обманчиво просто:

random( <random-key>?, <min>, <max> [, by <step>]? )

Однако за этой лаконичностью скрываются строгие правила типизации движка рендеринга.

Первое фундаментальное требование спецификации: аргументы <min> и <max> обязаны иметь абсолютно одинаковую размерность единиц измерения. Ты можешь передавать:

  • Углы: random(-4deg, 4deg) для легкого наклона элементов;
  • Временные интервалы: random(0.2s, 1.5s) для рассинхронизации фаз анимации;
  • Линейные размеры: random(100px, 300px) для вариации ширины колонок;
  • Безразмерные числа: random(0.5, 1.0) для прозрачности opacity.

Но ты не имеешь права напрямую смешивать разные единицы: выражение вида random(10px, 2rem) является синтаксической ошибкой и будет проигнорировано браузером. Если тебе действительно необходимо связать пиксели и относительные единицы, их придется предварительно приводить к единому знаменателю через calc().

Второе мощное свойство — параметр шага дискретизации (step). Без него функция генерирует непрерывную дробную величину. Но в реальных дизайн-системах отступы и размеры почти всегда кратны определенному модулю (например, 4 или 8 пикселей). Параметр шага позволяет удерживать случайность в строгих рамках:

.ticket-badge {
  /* Случайный отступ строго с шагом по 4 пикселя: 8px, 12px, 16px... */
  padding-inline: random(8px, 24px, 4px);
  /* Случайная задержка анимации с шагом в 100 миллисекунд */
  animation-delay: random(0s, 1s, 0.1s);
}

В нашем обзоре того, как устроены случайности в чистом CSS и что они изменят в верстке, мы подробно касались влияния шага на рендеринг. Это идеальный мостик между хаосом и порядком.

Проблема независимости: как ключи спасают квадраты

Что произойдет, если ты решишь сделать карточку случайного размера и напишешь:

.card {
  width: random(100px, 200px);
  height: random(100px, 200px);
}

По умолчанию каждый вызов функции random() вычисляется абсолютно независимо! Браузер сгенерирует для ширины, например, 184px, а для высоты — 112px. Твоя карточка превратится в случайный вытянутый прямоугольник. А если ты хотел сохранить идеальные пропорции квадрата 1:1?

Для решения этой задачи в спецификацию введен механизм именованных ключей (shared keys). Ключ работает как общий сид (seed): если двум разным CSS-свойствам передан одинаковый идентификатор ключа, они получат в точности одно и то же псевдослучайное значение:

.square-card {
  /* Одинаковый ключ --box гарантирует, что ширина будет равна высоте */
  inline-size: random(--box element-scoped, 100px, 200px);
  block-size: random(--box element-scoped, 100px, 200px);
}

Обрати внимание на модификатор element-scoped. Без него глобальный ключ --box вычислил бы одно число для всей страницы целиком (все карточки на сайте стали бы одинаковыми). Модификатор element-scoped указывает движку: «изолируй генератор в пределах каждого конкретного DOM-элемента». Каждая карточка получит свой уникальный случайный размер, но останется безупречным квадратом!

Статус поддержки и безопасный прогрессивный фолбэк

На момент конца октября 2026 года функция random() находится на острие браузерной стандартизации:

  • WebKit (Safari): экспериментальная реализация доступна в сборках Safari Technology Preview;
  • Blink (Chrome / Chromium): функция внедрена в Chrome 156 Canary за флагом экспериментальных веб-платформенных функций;
  • Gecko (Firefox): реализация тестируется в ветке Nightly за настройкой layout.css.random-function.enabled.

Поскольку стабильные версии браузеров еще готовятся к повсеместному включению, использовать random() в продакшене необходимо по канонам прогрессивного улучшения (Progressive Enhancement).

Посмотрим на боевой пример оформления галереи фотокарточек со стилизацией под Polaroid:

/* Базовые стили для всех браузеров: аккуратное статическое отображение */
.polaroid-item {
  rotate: 0deg;
  transition: transform 0.3s ease;
}

/* Прогрессивное улучшение для современных браузеров с поддержкой random() */
@supports (rotate: random(0deg, 1deg)) {
  .polaroid-item {
    /* Легкий органический наклон каждой карточки от -3 до +3 градусов */
    rotate: random(--photo-tilt element-scoped, -3deg, 3deg);
  }

  .polaroid-item:hover {
    /* При наведении карточка встает строго ровно */
    rotate: 0deg;
    transform: scale(1.05);
  }
}

В нашем исследовании о том, как 12 возможностей современного CSS вытесняют препроцессоры и JavaScript-хаки, мы отмечали: будущее веб-стилизации за переносом сложных динамических вычислений непосредственно в движок рендеринга.

Безопасный прогрессивный фолбэк

Всегда оборачивайте правила с функцией random() в директиву @supports. Это гарантирует, что старые браузеры просто отобразят стандартный ровный макет без сбоев разбора CSS и без поломки соседних стилей.

Как только функция random() перейдет в разряд общедоступного Baseline, веб окончательно избавится от искусственной пластиковой стерильности, сделав интерфейсы по-настоящему живыми и органичными.