Анимируем CSS-градиенты

by Denis Tverdokhlebov

HTML

<h1>Анимируем CSS-градиенты</h1>
<p>Как известно, градиенты не любят анимироваться.
Если быть точным, положение и размер градиента анимируются успешно (как и любого другого фона):</p>

<div id="demo_2">
  <div class="box2"></div>
</div>

<p>Но попытка манипулировать цветами, составляющим градиент, терпит крах:</p>

<div id="demo_3">
  <div class="box3"></div>
</div>

<p>В FF цвета в примере не будут меняться вообще, в Хроме — будут, но резко, без плавного перехода.</p>

<b>UPD: В Webkit с помощью Sass можно сделать имитацию плавной смены цветов, но код получается неприличных размеров. Пример: codepen.io/yoksel/pen/gBDFj.
На момент правки демо не работает в Firefox (27.0.1), анимация просто игнорируется.</b>

<p>В некоторых случаях при необходимости сделать градиент с плавной сменой цветов можно использовать box-shadow, который прекрасно анимируется. Тест:</p>

<div id="demo_4">
  <div class="box4"></div>
</div>

<p>Фоновый цвет в данном случае является частью градиента.</p>

<p>Тень задается с параметром inset (внутреняя тень), с большим радиусом размытия (в примере 100px), чтобы сымитировать градиент, и с большими отрицательными отступами (-120px) — чтобы от обычной внутренней тени была видна только нижняя часть.</p>

<p>Сложные градиенты делаются несколькими тенями:</p>

<div id="demo_1">
  <div class="box1"></div>
</div>




<p>Код конечно получается большим и неудобным, но он вполне решает задачу.</p>

<p>Способ придумался когда мне захотелось сделать демо CSS-анимации, в котором надо было менять цвет неба в зависимости от времени суток:</p>

<div id="demo_5">
  <div class="box5">
    <div class="stage">
      <div class="sun"></div>
      <div class="grass"></div>
      <div class="square"></div>
      <div class="round"></div>
    </div>
  </div>
</div>

<p>Тени отлично справились. Я думаю, что способ может быть полезен в некоторых случах и вполне имеет право на сущестование.</p>

CSS

/* Helpers */

BODY {
  margin: 0;
  padding: 20px 50px;
  /* display: flex; */
  justify-content: center;
  align-items: center;
  background: #EEE;
  font-size: 16px;
  text-align: justify;
}

#demo_1,#demo_2,#demo_3,#demo_4,#demo_5 {
  width: 100%;
  min-width: 100%;
  margin: 0 auto;
}
/***********************************Пример №1************************************/

DIV.box1 {
  margin: 0 auto;
  width: 100%;
  max-width: 80%;
  height: 200px;
  background: crimson;
  box-shadow: 0 -150px 70px -120px teal inset, 0 -220px 70px -120px yellowgreen inset, 0 -280px 70px -120px gold inset;
  border-radius: 30px;
  border: 10px solid white;
  animation: background_1 4s infinite alternate;
}

@keyframes background_1 {
  50% {
    background: darkviolet;
    box-shadow: 0 -140px 70px -120px mediumorchid inset, 0 -210px 70px -120px teal inset, 0 -280px 70px -120px plum inset;
  }
}

/***********************************Пример №2************************************/

DIV.box2 {
  margin: 0 auto;
  width: 100%;
  max-width: 80%;
  height: 200px;
  background: linear-gradient(crimson, gold, yellowgreen, teal, crimson);
  background-position: 0 0;
  border-radius: 30px;
  border: 10px solid white;
  animation: background_2 2s infinite alternate;
}

@keyframes background_2 {
  100% {
    background-position: 0 200px;
  }
}

/***********************************Пример №3************************************/

DIV.box3 {
  margin: 0 auto;
  width: 100%;
  max-width: 80%;
  height: 200px;
  background: linear-gradient(crimson, gold);
  background-position: 0 0;
  border-radius: 30px;
  border: 10px solid white;
  animation: background_3 2s infinite alternate;
}

@keyframes background_3 {
  50% {
    background: linear-gradient(red, green);
    background-position: 0 100px;
  }
}

/***********************************Пример №4************************************/

DIV.box4 {
  margin: 0 auto;
  width: 100%;
  max-width: 80%;
  height: 200px;
  background: gold;
  box-shadow: 0...