Випадкові числа в CSS

37

Від автора: на днях я зіткнувся з цікавою проблемою. Я хотів анімувати елемент з випадковим значенням animation-duration. Почав я з звичайної версії.

CSS код анімації:

@keyframes flicker {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#red {
animation: flicker 2s ease alternate infinite;
}

В принципі, все добре працює. Але даний спосіб не рандомізованих, тут задані фіксовані 2 секунди. Я хотів зробити так, щоб тривалість анімації була довільною. По суті, я хотів написати так:

.element {
animation: flicker $randomNumber alternate infinite;
}

Де $randomNumber випадкове значення, обчислене програмно. В CSS препроцессорах типу Sass є функція random().

$randomNumber: random(5);
.thing {
animation-duration: $randomNumber + s;
}

Для вас, може бути, функція нормальна, проте не для мене. У цій функції є великий недолік. Іншими словами, як тільки обробляється CSS, рандомізація закінчується. Кількість обмежена цим значенням навіки (тобто поки наново не буде запущений препроцесор).

Тут принцип не як у генерації через JS (Math.random()), де генерується випадкове число при запуску JS.

Після громчайшего подиху я зрозумів, що це чудова можливість скористатися рідними CSS змінними (корисними властивостями)! Самі по собі змінні не спростять генерацію випадкових чисел, однак вони можуть допомогти нам, і ми в цьому переконаємося.

Якщо ви не чули про CSS змінні, не лякайтеся. За фактом, це рідні змінні, вбудовані в CSS, проте вони відрізняються від тих змінних, які ви знаєте в препроцессорах типу Sass і Less. Кріс навів багато переваг:

їх можна використовувати без препроцесора;

вони розподіляються. Щоб переписати поточне значення або задати його, можна створити змінну всередині будь-якого селектора;

при зміні значення (наприклад, через медіа запити або інші стани), браузер перемальовує елемент;

CSS змінними можна маніпулювати через JS.

Нам дуже важливий останній пункт. Ми будемо генерувати випадкове число в JS і переміщати його в CSS за допомогою користувацьких властивостей.

Задайте CSS змінну зі значенням за замовчуванням (зручно, якщо JS раптово не спрацює):

/* час переходу за замовчуванням */
:root {
—animation-time: 2s;
}

Тепер цю змінну можна використовувати в нашому CSS:

#red {
animation: flicker var(—animation-time) ease alternate infinite;
}

Ми прийшли рівно до того, з чого почали. Це демо візуально нічим не відрізняється від попереднього, однак у цей раз у SVG анімації використовуються CSS змінні. Перевірити, що все працює, можна, змінивши значення змінної в CSS. Анімація повинна оновитися.

Все готово для пошуку і маніпулювання користувальницьким властивістю через JS.

var time = Math.random();

Звідси ми можемо знайти червоний круг в SVG і змінити CSS змінну —animation-time за допомогою методу setProperty:

var red = document.querySelector(‘#red’);
red.style.setProperty(‘—animation-time’, time +’s’);

І от і все! Випадково згенероване число в CSS, використовуване в SVG анімації:

Вже краще, генерується випадкове число при запуску JS, тому воно завжди різне. Це майже те, що ми хотіли, але давайте ще трохи ускладнимо завдання: будемо періодично випадково animation-duration під час роботи.

На щастя, ми працюємо з JS, ми можемо оновлювати власну властивість, коли захочемо. Приклад з оновленням animation-duration кожну секунду:

var red = document.querySelector(‘#red’);
function setProperty(duration) {
red.style.setProperty(‘—animation-time’, duration +’s’);
}
function changeAnimationTime() {
var animationDuration = Math.random();
setProperty(animationDuration);
}
setInterval(changeAnimationTime, 1000);

Саме цього я і хотів домогтися:

Важливо знати, що підтримка CSS змінних (споживчих властивостей) все ще неоднорідна. До цієї анімації можна було застосувати техніку прогресивного поліпшення:

#red {
animation: flicker .5s ease alternate infinite;
animation: flicker var(—animation-time) ease alternate infinite;
}

Якщо підтримка CSS змінних відсутній, ми побачимо хоч якусь анімацію, нехай і не точно таку ж.

Потрібно сказати, що випадково animation-duration можна не тільки з допомогою CSS змінних. Можна також отримувати DOM елемент через JS і безпосередньо вставляти випадкове значення у style:

var red = document.querySelector(‘#red’);
red.style.animationDuration = Math.floor(Math.random() * 5 + 1) + «s»;

Можна навіть чекати, коли закінчиться анімація, і ставити нове значення тривалості:

var red = document.querySelector(‘#red’);
function setRandomAnimationDuration() {
red.style.animationDuration = Math.floor(Math.random() * 10 + 1) + «s»;
}
red.addEventListener. («animationiteration», setRandomAnimationDuration);

Покажу ще один спосіб. Можна генерувати випадкові числа з допомогою EQCSS.

@element ‘#animation’ {
.element {
animation-duration: eval(‘rand’)s;
}
}
var rand = Math.random();
EQCSS.apply();

А ви хочете, щоб генерація випадкових чисел була доступна прямо в CSS? Не впевнений, що на цю тему ведуться хоч якісь обговорення. Навіть якщо вони і були, нам доведеться почекати, перш ніж використовувати метод. Філіп Уолтон нещодавно писав про те, як складно написати хороший полифил для генерації випадкових чисел в CSS. Набагато простіше це робити в JS!