CSS Animated Content Switching

A trend I’m seeing for the coming year is the rise of Transitional Interfaces on the web. A fine example is the aforementioned Fluidbox, or this interface (extract from the post linked):



Sparked by the post linked — which you should read — I started goofing around with CSS transforms and transitions a bit. The result is something I call CSS Animated Content Switching, which you could use when switching content in tabs or something like that. A little demonstration is embedded in the pen below:

Check out this Pen!

Panels can enter and exit using several animation classes I’ve prepared: a panel can slide in/out to a given direction (up/down/left/right), scale up/down, and/or fade in/out. Just define the animations to use on the wrapper using data-* attributes and you’re good to go:

<div class="panelWrapper" data-enter="slideright" data-exit="slideright">…</div>

Animations can run in parallel, or sequential. Parallel is useful when the entering and exiting panel animate in the same direction (e.g. slide in and out to the right), resulting in one fluid animation. Sequential is useful when the entering and exiting animation are the opposite of each other.

<div class="panelWrapper" data-enter="slideright" data-exit="slideleft" data-sequential="true">…</div>

Above that some animations can be combined as they’re essentially classnames that are assigned. When scaling up/down it is suggested to also change the opacity along with that, using the predefined fade classname.

The clever aspect of the code is the animating classname: only when the wrapper element has that classname assigned will the CSS properties (transforms, opacity, etc.) of the children be transitioned from a starting position/state to an end position/state. This allows us to set starting positions without any transition, and then – once .animating is in place – transition to the end position. Using onTransitionEnd Using a JavaScript setTimeout (as Firefox has trouble consistently firing the onTransitionEnd event), the state of the animated panels is then updated, awaiting another animation.


Did this help you out? Like what you see?
Thank me with a coffee.

I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

BuymeaCoffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation


  1. Hi

    I’m trying to use this source code but i can’t seem to get the animation working. I really want the Horizontal slide (enter and exit animations running sequential) to work.

    Do you know what I’m doing wrong?


  2. Hello and thank you for this script. I do not understand why it does not work properly with Firefox?
    When I click on the links A B and C in the disorder in Firefox effects stop!
    Do you track the problem?

    Thank you in advance

    1. Hi Emmanuel,

      It looks like the transitionend event is not firing properly/constantly in all browsers. A (nasty) fix would be to use a setTimeout.


    2. Hi Manu,

      I’ve by now updated the example to use the (nasty) setTimeout I suggested before. I’ve also added support for #next and #prev links.


  3. Hi Bramus,

    I just came across your solution. After literally searching / trying other solutions found on the internet, yours is what finally helped me.

    I just felt the urge to post this message to thanking you, even after 7 years since posting this it’s still very helpful.

    Good day.


    1. Hi Danny,
      Must say I almost forgot about this post … thanks for bringing to my attention again. Since it’s 2021 now, I think it might be time for a vanilla-JS rewrite 😉

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.