Случайные числа в CSS

Случайные числа в CSS

От автора: на днях я столкнулся с интересной проблемой. Я хотел анимировать элемент со случайным значением 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!

Автор: Robin Rendle

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree