Выражение CSS3 @keyframes с использованием секунд вместо процентов

Я изучил синтаксис CSS3 @keyframes в январе 2016 года, и, более чем через 2 года, я обнаружил, что использую анимацию @keyframes в немалой части своей работы (более сложный, чем transitions CSS3, и менее громоздкий, чем анимация на основе javascript).

Одна вещь, которой мне очень не хватает, - это возможность выражать @keyframes в секундах, а не в процентах. Есть ли какие-нибудь хаки для этого?

Я знаю, что могу использовать следующий прием на 100 секунд для циклического переключения цветов радуги с одним циклом каждые 3 секунды:

div {
    width: 120px;
    height: 120px;
    background-color: violet;
    animation: myAnimation 100s;
}

@keyframes myAnimation {
    0% {background-color: red;}
    3% {background-color: orange;}
    6% {background-color: yellow;}
    9% {background-color: green;}
   12% {background-color: cyan;}
   15% {background-color: blue;}
   18% {background-color: violet;}
  100% {background-color: violet;}
}
<div></div>

Но это означает, что анимация все еще выполняется (хотя и незаметно) еще 82 секунды после (эффективного) завершения. Помимо прочего, это делает невозможным выполнение нескольких итераций.

На самом деле я бы хотел написать просто:

@keyframes myAnimation {

  0s {background-color: red;}
  3s {background-color: orange;}
  6s {background-color: yellow;}
  9s {background-color: green;}
 12s {background-color: cyan;}
 15s {background-color: blue;}
 18s {background-color: violet;}
}

Есть ли лучший подход, чем тот, который я подробно описал в поле кода выше?


Добавление к изначальным условиям в вопросе:

Пример использования нескольких элементов

Оглядываясь назад, я понимаю, что, вероятно, сделал приведенный выше пример слишком простым, учитывая, что он включает в себя анимацию одного элемента, и мой вопрос изначально возникает из-за желания анимировать несколько элементов синхронно друг с другом.

Итак, вот немного более сложный пример, показывающий настройку, намного более близкую к той, которая в первую очередь породила мой вопрос:

div {
display: inline-block;
width: 48px;
height: 48px;
margin-right: 6px;
}

div:nth-of-type(1) {
background-color: red;
}

div:nth-of-type(2) {
background-color: orange;
animation: myAnimationOrange 100s;
}

div:nth-of-type(3) {
background-color: yellow;
animation: myAnimationYellow 100s;
}

div:nth-of-type(4) {
background-color: green;
animation: myAnimationGreen 100s;
}

div:nth-of-type(5) {
background-color: cyan;
animation: myAnimationCyan 100s;
}

div:nth-of-type(6) {
background-color: violet;
animation: myAnimationViolet 100s;
}

@keyframes myAnimationOrange {
    0% {background-color: white;}
    1% {background-color: white;}
    2% {background-color: orange;}
  100% {background-color: orange;}
}

@keyframes myAnimationYellow {
    0% {background-color: white;}
    2% {background-color: white;}
    3% {background-color: yellow;}
  100% {background-color: yellow;}
}

@keyframes myAnimationGreen {
    0% {background-color: white;}
    3% {background-color: white;}
    4% {background-color: green;}
  100% {background-color: green;}
}

@keyframes myAnimationCyan {
    0% {background-color: white;}
    4% {background-color: white;}
    5% {background-color: cyan;}
  100% {background-color: cyan;}
}

@keyframes myAnimationViolet {
    0% {background-color: white;}
    5% {background-color: white;}
    6% {background-color: violet;}
  100% {background-color: violet;}
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

Свободный перевод вопроса Expressing CSS3 @keyframes using seconds instead of percentages от участника @Rounin.


Ответы (1 шт):

Автор решения: Alexandr_TT

Не забывайте, что вы можете запускать несколько анимаций для одного и того же элемента, и что вы можете независимо устанавливать их продолжительность, задержку и все другие правила анимации.

Например, вы можете разделить все свои ключевые кадры на отдельные правила @keyframes. Тогда легко контролировать, когда они начнут действовать, и связать их в цепочки.

div {
    width: 120px;
    height: 120px;
    background-color: violet;
    animation-fill-mode: forwards;
    animation-name: orange, yellow, green, cyan, blue, violet;
    animation-delay: 0s, 3s, 6s, 9s, 12s, 15s, 18s;
    animation-duration: 3s; /* same for all */
}

@keyframes orange {
    to { background-color: orange; }
}
@keyframes yellow {
    to { background-color: yellow; }
}
@keyframes green {
    to { background-color: green; }
}
@keyframes cyan {
    to { background-color: cyan; }
}
@keyframes blue {
    to { background-color: blue; }
}
@keyframes violet {
    to { background-color: violet; }
}
<div></div>

Добавления вызванные редактированием вопроса

В этом случае вам даже не нужно комбинировать несколько анимаций в одном элементе, а просто установите соответствующую задержку анимации:

div {
 /* same for all */
    width: 60px;
    height: 60px;
    display: inline-block;
    background-color: white;
    animation-fill-mode: forwards;
    animation-duration: 3s;
}
div:nth-of-type(1) {
  animation-name: orange;
  animation-delay: 0s;
}
div:nth-of-type(2) {
  animation-name: yellow;
  animation-delay: 3s;
}
div:nth-of-type(3) {
  animation-name: green;
  animation-delay: 6s;
}
div:nth-of-type(4) {
  animation-name: cyan;
  animation-delay: 9s;
}
div:nth-of-type(5) {
  animation-name: blue;
  animation-delay: 12s;
}
div:nth-of-type(6) {
  animation-name: violet;
  animation-delay: 15s;
}

@keyframes orange {
    to { background-color: orange; }
}
@keyframes yellow {
    to { background-color: yellow; }
}
@keyframes green {
    to { background-color: green; }
}
@keyframes cyan {
    to { background-color: cyan; }
}
@keyframes blue {
    to { background-color: blue; }
}
@keyframes violet {
    to { background-color: violet; }
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

Но если вы хотите объединить и то, и другое, это тоже возможно:

div {
 /* same for all */
    width: 60px;
    height: 60px;
    display: inline-block;
    background-color: white;
    animation-fill-mode: forwards;
    animation-duration: 3s;
}
div:nth-of-type(1) {
  animation-name: orange, yellow, green, cyan, blue, violet;
  animation-delay: 0s, 3s, 6s, 9s, 12s, 15s;
}
div:nth-of-type(2) {
  animation-name: yellow, green, cyan, blue, violet;
  animation-delay: 3s, 6s, 9s, 12s, 15s;
}
div:nth-of-type(3) {
  animation-name: green, cyan, blue, violet;
  animation-delay: 6s, 9s, 12s, 15s;
}
div:nth-of-type(4) {
  animation-name: cyan, blue, violet;
  animation-delay: 9s, 12s, 15s;
}
div:nth-of-type(5) {
  animation-name: blue, violet;
  animation-delay: 12s, 15s;
}
div:nth-of-type(6) {
  animation-name: violet;
  animation-delay: 15s;
}

@keyframes orange {
    to { background-color: orange; }
}
@keyframes yellow {
    to { background-color: yellow; }
}
@keyframes green {
    to { background-color: green; }
}
@keyframes cyan {
    to { background-color: cyan; }
}
@keyframes blue {
    to { background-color: blue; }
}
@keyframes violet {
    to { background-color: violet; }
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

Свободный перевод ответа от участника @Kaiido.

→ Ссылка