Я пытаюсь построить программируемый отсчет только css. Десятки секунд работают хорошо, но некоторые из них работают не так, как я ожидал.
*:after{
animation-direction: reverse;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear; /* Safari 4.0 - 8.0 */
animation-timing-function: linear;
}
.secondsTen:after{
content:'';
animation-name: tenBased;
animation-duration: 10s;
}
.secondsSix:after{
content:'';
animation-name: sixBased;
animation-duration: 60s;
}
@keyframes tenBased {
0% { content: '0';}
10% { content: '1';}
20% { content: '2';}
30% { content: '3';}
40% { content: '4';}
50% { content: '5';}
60% { content: '6';}
70% { content: '7';}
80% { content: '8';}
90% { content: '9';}
100% { content: '0';}
}
@keyframes sixBased {
0% {content: '0';}
16.66667% {content: '1';}
33.33333% {content: '2';}
50% {content: '3';}
66.66667% {content: '4';}
83.33333% {content: '5';}
100% {content: '0';}
}
<span class='secondsSix'></span>
<span class='secondsTen'></span>
Как вы можете видеть, одна секунда уменьшается через 5 секунд. Но оно должно уменьшиться через 10 секунд до 5.
2 ответа
Объяснение наблюдаемого поведения
Анимация ключевого кадра выполняет переход между заданными состояниями. В вашем примере вы анимируете значение свойства content
псевдоэлемента, которое полностью допустимо, но вы должны помнить, что между двумя ключевыми кадрами нет промежуточных шагов, которые можно визуализировать в этом случае.
Таким образом, на самом деле переход от 100% {content: '0';}
к 83.33333% {content: '5';}
завершится через 10 секунд (как и ожидалось), но в какой-то момент между значением свойства изменится. При установке animation-timing-function: linear;
он находится точно между двумя ключевыми кадрами - в этом примере через 5 секунд это выглядит так, как будто начинается с задержкой.
*:after{
animation-direction: reverse;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear; /* Safari 4.0 - 8.0 */
animation-timing-function: linear;
}
.secondsSix:after{
content:'';
animation-name: sixBased;
animation-duration: 60s;
position: absolute;
}
@keyframes sixBased {
0% {content: '0'; left: 100%}
16.66667% {content: '1';}
33.33333% {content: '2';}
50% {content: '3';}
66.66667% {content: '4';}
83.33333% {content: '5';}
100% {content: '0'; left: 0%}
}
.timeline {
border: solid grey;
border-width: 1px 0;
background: white;
position: absolute;
width: 100%;
left: 0;
top: 2em;
}
.timeline span {
display: inline-block;
float: left;
margin-right: 8.33%;
width: 0;
}
<div class='secondsSix'></div>
<div class='timeline'>
<span>0</span><span>5</span><span>10</span><span>15</span><span>20</span><span>25</span>
<span>30</span><span>35</span><span>40</span><span>45</span><span>50</span><span>55</span>
</div>
Я проанализировал поведение с помощью приведенного выше фрагмента и посмотрел, что произойдет, если я удалю отдельные ключевые кадры (по одному за раз, представленные пробелом в следующей таблице).
Content 0 5 4 3 2 1 0
Time 0 5 15 25 35 45 55
Time 0 10 25 35 45 55
Time 0 5 20 35 45 55
Time 0 5 15 30 45 55 // change from '4' to '2' at second 30
Time 0 5 15 25 40 55
Time 0 5 15 25 35 50
Как видите, содержимое всегда меняется точно между двумя заданными ключевыми кадрами. То же самое можно наблюдать в следующей демонстрации, где я изменил вашу анимацию tenBase:
*:after {
animation-direction: reverse;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear; /* Safari 4.0 - 8.0 */
animation-timing-function: linear;
animation-duration: 10s;
}
.secondsTen:after {
content: '';
animation-name: tenBased;
}
.secondsTenTwoSteps:after {
content: '';
animation-name: tenBasedTwoSteps;
}
@keyframes tenBased {
0% { content: '0' }
10% { content: '1'; }
20% { content: '2'; }
30% { content: '3'; }
40% { content: '4'; }
50% { content: '5'; }
60% { content: '6'; }
70% { content: '7'; }
80% { content: '8'; }
90% { content: '9'; }
100% { content: '10' }
}
@keyframes tenBasedTwoSteps {
0% { content: '0' }
100% { content: '10' }
}
<div class='secondsTen'></div>
<div class='secondsTenTwoSteps'></div>
Решение № 1
Первый способ решения проблемы прост, но не очень красив. Вам нужно изменить свойство в CSS-анимации внезапно без анимации и то, что ОП описывает как хакерский способ в связанном вопросе будет выглядеть так:
*:after{
animation-direction: reverse;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear; /* Safari 4.0 - 8.0 */
animation-timing-function: linear;
}
.secondsSix:after{
content:'';
animation-name: sixBased;
animation-duration: 60s;
position: absolute;
}
@keyframes sixBased {
0% {content: '0'; left: 100%}
0.1% {content: '0';}
16.66667% {content: '1';}
16.7% {content: '1';}
33.3% {content: '2';}
33.33333% {content: '2';}
33.4% {content: '3';}
50% {content: '3';}
50.1% {content: '4';}
66.66667% {content: '4';}
66.7% {content: '5';}
83.33333% {content: '5';}
83.4% {content: '0';}
100% {content: '0'; left: 0%}
}
.timeline {
border: solid grey;
border-width: 1px 0;
background: white;
position: absolute;
width: 100%;
left: 0;
top: 2em;
}
.timeline span {
display: inline-block;
float: left;
margin-right: 8.33%;
width: 0;
}
<div class='secondsSix'></div>
<div class='timeline'>
<span>0</span><span>5</span><span>10</span><span>15</span><span>20</span><span>25</span>
<span>30</span><span>35</span><span>40</span><span>45</span><span>50</span><span>55</span>
</div>
Решение № 2
Есть и другое решение. Вы увидите, что изменение animation-timing-function: linear;
на что-то другое, например animation-timing-function: ease-out;
, меняет момент времени, когда содержание резко меняется. Мы заметили, что контент меняется точно посередине при использовании функции линейного хронирования, поэтому я предполагаю, что он будет меняться на 50% прогресса между двумя ключевыми кадрами.
Как разрешено определять cubic-bezier
мы можем сдвинуть этот момент времени, когда прогресс приближается к концу на 50%. Помните, что направление анимации меняется на противоположное, поэтому вам нужно отразить кривую (см. cubic-bezier.com/#0,1,0,1 ) .
*:after{
animation-direction: reverse;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear; /* Safari 4.0 - 8.0 */
}
.secondsSix:after{
content:'';
animation-name: sixBased;
animation-duration: 60s;
position: absolute;
}
@keyframes sixBased {
0% {content: '0'; left: 100%}
16.66667% {content: '1'; animation-timing-function: cubic-bezier(0,1,0,1);}
33.33333% {content: '2'; animation-timing-function: cubic-bezier(0,1,0,1);}
50% {content: '3'; animation-timing-function: cubic-bezier(0,1,0,1);}
66.66667% {content: '4'; animation-timing-function: cubic-bezier(0,1,0,1);}
83.33333% {content: '5'; animation-timing-function: cubic-bezier(0,1,0,1);}
100% {content: '0'; left: 0%}
}
.timeline {
border: solid grey;
border-width: 1px 0;
background: white;
position: absolute;
width: 100%;
left: 0;
top: 2em;
}
.timeline span {
display: inline-block;
float: left;
margin-right: 8.33%;
width: 0;
}
<div class='secondsSix'></div>
<div class='timeline'>
<span>0</span><span>5</span><span>10</span><span>15</span><span>20</span><span>25</span>
<span>30</span><span>35</span><span>40</span><span>45</span><span>50</span><span>55</span>
</div>
Хотите попробовать это
.secondsTen:before {
content: '9876543210';
width:1ch;
overflow:hidden;
animation:tenBased 10s steps(10) infinite;
float:left;
}
.secondsSix:before{
content: '543210';
width:1ch;
overflow:hidden;
float:left;
animation:sixBased 60s steps(6) infinite;
}
@keyframes tenBased {
0% {text-indent:0}
100% {text-indent:-10ch;}
}
@keyframes sixBased {
0% {text-indent:0}
100% {text-indent:-6ch;}
}
<span class='secondsSix'></span>
<span class='secondsTen'></span>
Новые вопросы
css
CSS (каскадные таблицы стилей) - это язык таблиц стилей представления, используемый для описания внешнего вида и форматирования документов HTML (язык разметки гипертекста), XML (расширяемый язык разметки) и элементов SVG, включая (но не ограничиваясь) цвета, макет, шрифты, и анимации. Также описывается, как элементы должны отображаться на экране, на бумаге, в речи или на других носителях.