Meaningful transitions tutorial basing on material design motion choreography
Some time ago I got inspired by Googles material design and meaningful transition concepts. Since CSS3 has allowed us to build beautiful transitions and seamless animations we must also be very careful in using them. It is our responsibility in front of our users and it can either help to better understand, read and grasp the information or do the opposite.
If a client would enter your restaurant, you would take proper care of him e.g. show him his table, present the menu etc. On the web we have other options to guide the user that has arrived – one of them being visual guidance using proper and logical information entrance animations. If a user does an action, we want to give him both the feedback of his action and display the following information so that he feels that it was connected to his action.
View the demo or Download source
Meaningful transition setup – CSS + Bootstrap + Animate.css
We are basing our example on Bootstrap in order to handle responsiveness and we use Animate.css because it is a great library for CSS based animations and transitions. Tutorial consists of 3 cards than can be opened via clicking on it. After the card has been clicked, additional information is shown and loaded dynamically using Ajax.
<div class="col-sm-4 card"> <div class="card-content"> <div class="left"> <a class="close-button hidden" href="#" title=""></a> <div class="background-color-filler"></div> <img class="animate-transition" src="images/meaningful-transition-design-1.svg"/> <div class="button-wrapper open-card"> <a href="#" title="">Open</a> </div> </div> </div> </div>
You can see that our card consists of a close button that we reveal when the card is open, background color, an icon for the card and a button that opens the card itself. Please note that we do have a class “left” defined here – I will explain why later on.
The magic of motion – jQuery + jQuery UI + Transform2d.js
After clicking on a card we want to show the user that the current card opens up and what better way to do that than to create the feeling that we are immersing in it zooming in a large circle right from the center of the card.
In order to do the zooming effect – we are using CSS scale property, but since it is not so stable and reliable across browsers, we are adding additional jQuery plugin Transform2d.js in combination with jQuery UI that consists of Effects components which is needed to create the animation of the circle. We will also need to include jQuery library in order to handle the opening and closing of cards.
//* //Function responsible for meaningful transitions //* $( ".open-card, .card img, .background-color-filler, .close-button" ).bind( "click", function(event) { event.preventDefault(); var body = $("body"); var row = $(this).parent().parent().parent().parent(); var card = $(this).parent().parent().parent(); var left = $(this).parent(); var background = $(this).parent().find(".background-color-filler"); var image = $(this).parent().find("img"); var closeButton = $(this).parent().find(".close-button"); var openButton = $(this).parent().find(".open-card"); var speed = 600; $(".open-card").removeClass("animated fadeInDown"); //Removes animation classes from all buttons if (card.hasClass('clicked')) { //If the card is open body.removeClass("card-is-open"); //Removes definition that the card is open card.removeClass('open'); //Removes class that shows that the card is open $("#dynamic-content").remove(); //Destroys dynamic content container closeButton.addClass("hidden"); //Hides close button image.removeClass("animated fadeOut").addClass("animated fadeIn"); //Reveal back the image openButton.removeClass("animated fadeOutUp").addClass("animated fadeInDown"); row.removeClass('row-open'); //Revealing back the hidden cards background.stop().animate({ transform: 'scale(1)' //Circle animation to the initial size }, speed, 'easeOutCubic', function(){ //These functions are fired after the animation card.removeClass('clicked'); //Removes class after a card is clicked body.removeClass("hide-overflow-x"); //Returns vertical scrollbar after the animation $('html, body').animate({ //Used to scroll down back to the card scrollTop: card.offset().top - 50 }, {"duration": speed}); }); } else { //If the card is not open card.addClass('clicked'); //Adds a class after a card is clicked body.addClass("hide-overflow-x"); //Adds a class in order to hide vertical scrollbars that appear after the animation is finished openButton.addClass("animated fadeOutUp"); //Hides the button on the card that is clicked image.addClass("animated fadeOut"); //Hides the image on the card that is clicked background.stop().animate({ transform: 'scale(300)' //Circle animation }, speed, 'easeInCubic', function(){ //These functions are fired after the animation body.addClass("card-is-open"); //Adds class to the body when the animation is finished and the circle is fully scaled row.addClass('row-open'); //Adds a class to the row that is open in order to hide the cards it holds using CSS left.after( "<div id='dynamic-content' class='right animated fadeInUp'>This is dynamic content</div>" ); //Loads dynamic content element for use with Ajax calls closeButton.removeClass("hidden").addClass('animated fadeInUp'); //Reveals close button card.addClass('open'); //Adds a class after the card is clicked and opened image.removeClass("animated fadeOut").addClass('animated fadeIn'); //Reveals back the image $("#dynamic-content").load('dynamic-content.html'); //Ajax call to load the dynamic content from a file or a link $('html, body').animate({ //Used to scroll down back to the card scrollTop: card.offset().top - 50 }, speed); }); } });
The JavaScript code above has got all of the comments and you can easily read what each line does and why is it there. This is the place where we are using Ajax to load the content of the open card and here we can see that we have class “right” to the dynamic content that is being loaded. This is why previously I mentioned we needed the class “left” defined – both these parts are loaded together and this is how we are aligning them side by side once they are visible.
Your thoughts