Css-only countdown can't make numbers work together

I am trying to create programmable css just countdown. Tens of the second work well, but some of them do not work as I expected.

*: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>
      

Run codeHide result


As you can see, some of the latter shrink after 5 seconds. But it should decrease after 10 seconds to 5.

+3


source to share


2 answers


Explanation of Observed Behavior

Activating a key frame transitions between these states. In your example, you are animating the property value of a content

pseudo - element, which is fully valid, but you must bear in mind that there are no intermediate steps between the two keyframes that can be rendered in this case.

So the transition from 100% {content: '0';}

to 83.33333% {content: '5';}

completes after 10 seconds (as expected), but at some point between the property value changes. When set, animation-timing-function: linear;

this is exactly between two keyframes - after 5 seconds, this example gives the impression that it starts with a delay.

*: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>
      

Run codeHide result


I analyzed the behavior using the snippet above and looked at what happens if I remove individual keyframes (one at a time in the table).

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

      

As you can see, the content always changes exactly between the two given keyframes. The same can be seen in the following demo, where I changed your tenBase animation:

*: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>
      

Run codeHide result





Solution # 1

The first way to solve the problem is simple, but not very pretty. You want to change a property in a CSS animation without animation and what the OP describes as a hacky way in the linked question would look like this:

*: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>
      

Run codeHide result





Solution # 2

There is also another solution. You will see that changing animation-timing-function: linear;

to something else, like animation-timing-function: ease-out;

, changes the point in time when the content changes abruptly. We noticed that the content changes exactly in the middle when using the linear sync feature, so I'm guessing it changes 50% of the progress between the two keyframes.

As permitted to define cubic-bezier

, we can shift this point in time when the progress reaches 50% towards the end.Note that your animation direction is reversed, so you need to flip the curve (see 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>
      

Run codeHide result


+2


source


Would you like to try this



.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>
      

Run codeHide result


0


source







All Articles