Reputation: 26791
According to the Animation Spec:
If a ‘0%’ or ‘from’ keyframe is not specified, then the user agent constructs a ‘0%’ keyframe using the computed values of the properties being animated. If a ‘100%’ or ‘to’ keyframe is not specified, then the user agent constructs a ‘100%’ keyframe using the computed values of the properties being animated.
This can lead to two different interpretations:
A) Declare the property in the class and not in the 0%
or from
keyframe.
B) Declare the property in the class and in the 0%
or from
keyframe.
p:first-of-type {
opacity: 0;
animation: a 3s linear infinite alternate;
}
@keyframes a {
100% {
opacity: 1;
}
}
p:last-of-type {
opacity: 0;
animation: b 3s linear infinite alternate;
}
@keyframes b {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<p>
A) Declare the property in the class <strong>and not</strong> in the `0%` or `from` keyframe.
</p>
<p>
B) Declare the property in the class <strong>and </strong> in the `0%` or `from` keyframe.
</p>
While both have the same end result, following the Don't Repeat Yourself (DRY) principle, A) could vastly reduce code for all the animations that use more than one property.
/*
Layout
*/
* {
box-sizing: border-box;
}
body {
margin: 0;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-around;
counter-reset: list-item;
}
.container > li {
position: relative;
counter-increment: list-item;
}
.container > li::before {
content: counter(list-item, upper-alpha);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: flex-end;
align-items: flex-end;
font-size: 1.5em;
background-color: moccasin;
}
.container > li::after {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 100%;
transform: translateY(-50%);
height: 2px;
background-color: gold;
}
/*
SVG
*/
.svg-spritesheet {
display: none;
}
.svg__icon {
display: inline-block;
vertical-align: middle;
width: 1em;
height: 1em;
}
.svg__icon--square {
font-size: 5em;
color: dodgerblue;
}
/*
Question Related
*/
.container > li:first-of-type .svg__icon--square {
opacity: 0;
transform: scale(.5) rotate(45deg);
animation: animationA 5s linear infinite alternate;
}
.container > li:nth-child(2) .svg__icon--square {
opacity: 0;
transform: scale(.5) rotate(45deg);
animation: animationB 5s linear infinite alternate;
}
@keyframes animationA {
to {
opacity: 1;
transform: translateX(500px) scale(1) rotate(90deg);
}
}
@keyframes animationB {
from {
opacity: 0;
transform: scale(.5) rotate(45deg);
}
to {
opacity: 1;
transform: translateX(500px) scale(1) rotate(90deg);
}
}
<ul class="container">
<li>
<svg class="svg__icon svg__icon--square">
<use xlink:href="#svg-icon-square"></use>
</svg>
</li>
<li>
<svg class="svg__icon svg__icon--square">
<use xlink:href="#svg-icon-square"></use>
</svg>
</li>
</ul>
<svg class="svg-spritesheet">
<symbol id="svg-icon-square" viewBox="0 0 32 32">
<title>Demo Square</title>
<rect width="32" height="32" fill="currentColor" />
</symbol>
</svg>
Is it safe to remove a property from the 0%
keyframe of a CSS animation if it is already declared in the class the animation is applied to?
Is doing this:
.el {
opacity: 0;
animation: example 1s;
}
@keyframes example {
100% {
opacity: 1;
}
}
considered safe across browsers? Or is it to be expected that user agents render different results or performance?
Rendering the same result:
Windows 10 / 64-bit
Upvotes: 9
Views: 1475
Reputation: 724342
The computed value of a property can vary depending on what CSS rules are applying to a given element, the specificity of these rules, whether the element has an inline style declaration for that property, whether a script is modifying the value of that property at runtime, etc.
If you want an animation to start from a predictable, and fixed, value, you will need to specify this value in the 0% keyframe so that it doesn't start animating from what the computed value happens to be at the time the animation starts instead.
You can leave out the 0% keyframe if you can guarantee that the computed value for that element at the time the animation is started is always a constant value. You must leave out the 0% keyframe if you want the animation to always start from whatever the computed value happens to be at the time, if it can change.
Similar rules apply to the 100% keyframe: if the animation needs to end with a fixed value regardless of what the computed value may be, you will need to specify the 100% keyframe; otherwise, if it needs to end with the same value as the computed value, you will need to leave it out.
Upvotes: 4
Reputation: 73988
It can work in both way, as the specification point out.
Regarding safeness, this should be ok in the following browsers:
IE 11
Edge 14
Firefox from 47 to 52
Chrome from 49 to 57
Safari from 9.1 to 10
Keeping the 0%
in my opinion could make your code more readable specially if you have complex animation, but in case you want avoid repetition you could use some CSS pre-processor, for example LESS using animation keyframes mixin or other techniques.
Upvotes: 2