Ricky Ruiz
Ricky Ruiz

Reputation: 26791

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?

Context:

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:


Simplified Example:

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.


Complex Example:

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


Question:

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?


TESTS:

Rendering the same result:

Windows 10 / 64-bit

Upvotes: 9

Views: 1475

Answers (2)

BoltClock
BoltClock

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

GibboK
GibboK

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

Related Questions