CSS: Animation vs. Transition

Viewed 54204

So, I understand how to perform both CSS3 transitions and animations. What is not clear, and I've googled, is when to use which.

For example, if I want to make a ball bounce, it is clear that animation is the way to go. I could provide keyframes and the browser would do the intermediates frames and I'll have a nice animation going.

However, there are cases when a said effect can be achieved either way. A simple and common example would be implement the facebook style sliding drawer menu:

This effect can be achieved through transitions like so:

.sf-page {
    -webkit-transition: -webkit-transform .2s ease-out;
}

.sf-page.out {
    -webkit-transform: translateX(240px);
}

http://jsfiddle.net/NwEGz/

Or, through animations like so:

.sf-page {
    -webkit-animation-duration: .4s;
    -webkit-transition-timing-function: ease-out;
}

.sf-page.in {
    -webkit-animation-name: sf-slidein;
    -webkit-transform: translate3d(0, 0, 0);
}

.sf-page.out {
    -webkit-animation-name: sf-slideout;
    -webkit-transform: translateX(240px);
}

@-webkit-keyframes sf-slideout {
    from { -webkit-transform: translate3d(0, 0, 0); }
    to { -webkit-transform: translate3d(240px, 0, 0); }
}
 
@-webkit-keyframes sf-slidein {
    from { -webkit-transform: translate3d(240px, 0, 0); }
    to { -webkit-transform: translate3d(0, 0, 0); }
}

http://jsfiddle.net/4Z5Mr/

With HTML that looks like so:

<div class="sf-container">
    <div class="sf-page in" id="content-container">
        <button type="button">Click Me</button>
    </div>
    <div class="sf-drawer">
    </div>
</div>

And, this accompanying jQuery script:

$("#content-container").click(function(){
    $("#content-container").toggleClass("out");
    // below is only required for css animation route
    $("#content-container").toggleClass("in");
});

What I'd like to understand is what are the pros and cons of these approaches.

  1. One obvious difference is that animating is taking a whole lot more code.
  2. Animation gives better flexibility. I can have different animation for sliding out and in
  3. Is there something that can be said about performance. Do both take advantage of h/w acceleration?
  4. Which is more modern and the way going forward
  5. Anything else you could add?
11 Answers

A shorter answer, straight on point:

Transition:

  1. Needs a triggering element (:hover, :focus etc.)
  2. Only 2 animation states (start and end)
  3. Used for simpler animations (buttons, dropdown menus and so on)
  4. Easier to create but not so many animation/effect possibilities

Animation @keyframes:

  1. It can be used for endless animations
  2. Can set more than 2 states
  3. No boundaries

Both use CPU acceleration for a much smoother effect.

Is there something that can be said about performance. Do both take advantage of h/w acceleration?

In modern browsers, h/w acceleration occurs for the properties filter, opacity and transform. This is for both CSS Animations and CSS Transitions.

.yourClass {
    transition: all 0.5s;
color: #00f;
margin: 50px;
font-size: 20px;
cursor: pointer;
}

.yourClass:hover {
    color: #f00;
}
<p class="yourClass"> Hover me </p>

CSS3 Transitions brought frontend developers a significant ability to modify the appearance and behavior of an element as relative to a change in his state. CSS3 animations extends this ability and allow to modify the appearance and behavior of an element in multiple keyframes, so transitions provides us the ability to change from one state to another, while that animations can set multiple points of transition within different keyframes.

So, let's look at this transition sample where applied a transition with 2 points, start point at left: 0 and an end point at left: 500px

.container {
  background: gainsboro;
  border-radius: 6px;
  height: 300px;
  position: relative;
}

.ball {
  transition: left 2s linear;
  background: green;
  border-radius: 50%;
  height: 50px;
  position: absolute;
  width: 50px;
  left: 0px;
}

.container:hover .ball{
  left: 500px;
}
<div class="container">
  <figure class="ball"></figure>
</div>

The above can be also created via animation like so:

@keyframes slide {
  0% {
    left: 0;
  }
  100% {
    left: 500px;
  }
}

.container {
  background: gainsboro;
  border-radius: 6px;
  height: 200px;
  position: relative;
}

.ball {
  background: green;
  border-radius: 50%;
  height: 50px;
  position: absolute;
  width: 50px;
}

.container:hover .ball {
  animation: slide 2s linear;
}
<div class="container">
  <figure class="ball"></figure>
</div>

And if we would like another in-between point, it would be possible to achieve only via animation, we can add another keyFrame to achieve this and this is the real power of animation over transition:

@keyframes slide {
  0% {
    left: 0;
  }
  50% {
    left: 250px;
    top: 100px;
  }
  100% {
    left: 500px;
  }
}

.container {
  background: gainsboro;
  border-radius: 6px;
  height: 200px;
  position: relative;
}

.ball {
  background: green;
  border-radius: 50%;
  height: 50px;
  position: absolute;
  width: 50px;
}

.container:hover .ball {
   animation: slide 2s linear;
}
<div class="container">
  <figure class="ball"></figure>
</div>

transition can go reverse from middle of the way, but animation replay the keyframes from start to end.

const transContainer = document.querySelector(".trans");

transContainer.onclick = () => {
  transContainer.classList.toggle("trans-active");
}


const animContainer = document.querySelector(".anim");
animContainer.onclick = () => {
  if(animContainer.classList.contains("anim-open")){
    animContainer.classList.remove("anim-open");
    animContainer.classList.add("anim-close");
  }else{
    animContainer.classList.remove("anim-close");
    animContainer.classList.add("anim-open");
  }
}
*{
  font: 16px sans-serif;
}

p{
  width: 100%;
  background-color: #ff0;
}
.sq{
  width: 80px;
  height: 80px;
  margin: 10px;
  background-color: #f00;
  display: flex;
  justify-content: center;
  align-items: center;
}

.trans{
  transition: width 3s;
}
.trans-active{
  width: 200px;
}

.anim-close{
  animation: closingAnimation 3s forwards;
}
.anim-open{
  animation: openingAnimation 3s forwards;
}

@keyframes openingAnimation {
  from{width: 80px}
  to{width: 200px}
}
@keyframes closingAnimation {
  from{width: 200px}
  to{width: 80px}
}
<p>Try click them before reaching end of movement:</p>
<div class="sq trans">Transition</div>
<div class="sq anim">Animation</div>

in addition, if you want the javascript to listen for end of transition, you'll get one event for each property that you change. for example transition: width 0.5s, height 0.5s. the transitionend event will trigger two times, one for width and one for height.

Don't bother yourself which is better. My give away is that, if you can solve your problem with just one or two lines of code then just do it rather than writing bunch of codes that will result to similar behavior. Anyway, transition is like a subset of animation. It simply means transition can solve certain problems while animation on the other hand can solve all problems. Animation enables you to have control of each stage starting from 0% all the way to 100% which is something transition cannot really do. Animation require you writing bunch of codes while transition uses one or two lines of code to perform the same result depending on what you are working on. Coming from the point of JavaScript, it is best to use transition. Anything that involve just two phase i.e. start and finish use transition. Summary, if it is stressful don't use it since both can produce similar result

Related