Цвет · рецепт градиентаАнимированный градиент на CSS — плавный перелив
Фон втрое шире блока и медленно ездит туда-обратно. Для людей, отключивших анимацию в системе, перелив останавливается — это обязательная часть рецепта.
Растяните градиент шире блока — в кадре только треть.
02
@keyframes gradient-shift
Двигайте background-position от 0% до 100% и обратно.
03
animation: … 8s ease-in-out infinite
Медленный цикл 6–12 секунд выглядит спокойно и не отвлекает.
04
@media (prefers-reduced-motion: reduce)
Отключите анимацию для тех, кому движение мешает или вредит.
04
Частые ошибки
Нет prefers-reduced-motion
Бесконечная анимация без отключения нарушает WCAG 2.3.3 и может вызывать дискомфорт.
Рывок в конце цикла
Если первый и последний цвет разные, на стыке виден скачок. Повторите первый цвет в конце или используйте alternate.
Слишком быстро
Цикл короче 4 секунд воспринимается как мигание. Для фона лучше 8 секунд и больше.
05
Частые вопросы
Растяните фон шире блока через background-size: 300% 100% и опишите в @keyframes движение background-position от 0% до 100% и обратно. Свойство animation с infinite и ease-in-out повторяет цикл без остановки. Чтобы на стыке цикла не было рывка, первый цвет градиента повторяется в конце — код рецепта делает это сам. Длительность настраивается ползунком, по умолчанию восемь секунд.
Анимация background-position заставляет браузер перерисовывать блок в каждом кадре, а не просто сдвигать готовый слой. Для кнопки или карточки это незаметно, а вот фон на весь экран на слабом ноутбуке может греть процессор и сажать батарею. Тяжёлый случай облегчают так: кладут градиент на псевдоэлемент шире блока и двигают его через transform — такую анимацию видеокарта выполняет без перерисовки.
Это медиазапрос, который сообщает, что человек попросил систему уменьшить движение на экране: в Windows это «Эффекты анимации», в macOS и iOS — «Уменьшение движения», в Android — «Удалить анимацию». Так поступают люди с вестибулярными нарушениями, мигренью или просто уставшие от мельтешения. Блок @media (prefers-reduced-motion: reduce) с animation: none останавливает перелив, а градиент остаётся неподвижным фоном.
Возьмите conic-gradient и задайте его начальный угол переменной: from var(--angle). Саму переменную объявите через @property с syntax: '<angle>', иначе браузер не сможет её плавно анимировать. Затем в @keyframes меняйте --angle от 0deg до 360deg. Такой приём работает в Chrome 85+, Safari 16.4+ и Firefox 128+, а в остальных браузерах градиент просто стоит на месте.
Для фона — от шести до двенадцати секунд на цикл: движение заметно, но не отвлекает от текста. Цикл короче четырёх секунд воспринимается как мигание, особенно на контрастных цветах. Плавность ease-in-out лучше линейной: в крайних точках фон притормаживает, и разворот не выглядит рывком. Для акцентного элемента вроде кнопки допустимо быстрее, но только при наведении, а не постоянно.
Свойство animation-play-state: paused останавливает перелив на текущем кадре, а значение running запускает снова. Его можно включать при наведении, по кнопке или классом на корневом элементе. Пауза — не только удобство: если движение длится дольше пяти секунд рядом с другим содержимым, критерий WCAG 2.2.2 требует дать способ его остановить. Отключение через prefers-reduced-motion закрывает этот случай лишь отчасти.