One important thing, which jQuery offers, are the really easy way to create clean and smooth animations. But today, where you can already do some cool animated stuff using CSS 3, you don’t need a fat library to spice up your website. I will show you, how animations can be done with ease! I will also split this content into 2 parts, due to the length of this topic! So this Post just handles the basic methods, while the post on the next Saturday (as always @ 10:42) shows you how powerful it can be!

CSS 3 – Transition and Animations

As mentioned above: You can already use CSS 3 to animate your elements, which is the best way on days like these. Because even if JavaScript is disabled in the browser (due to a Script / Ad Blocker), the animation will still shown to your user. You are right, the CSS 3 possibilities are limited and you cannot handle EVERYTHING you may need. But I highly recommend to try out the CSS 3 “way”, before you going with JavaScript!

 

CSS 3 – Transitions

One method to handle cool and beautiful animations is called “CSS Transition”, which creates a transition between two different CSS properties. It is available since 4.0, 4.0, 3.1, 10.5 and 10.0. To use this you need one (or more) transitable or animatable CSS properties as well as the transition setting itself. Start with the original design of your element, and then create the resulting view using a pseudo-(class)-selector, like :hover. You can also use another class name and “toggle” this one with JavaScript, of course.

Here is a short demonstration. The “green circle” will went to the right, and changes his background color to red, when your mouse cursor is over the bordered container. It also breaks up directly, and returns to the default state (green and left), when the cursor leaves the main container. The complete animation takes exactly 1 second, take the time and test it out.

Example

HOVER ME
Show CSS Code
.example-transition-1{
    color: #c0c4c8;
    width: 100%;
    height: 52px;
    margin: 15px 0;
    padding: 5px;
    display: block;
    position: relative;
    font-size: 16px;
    text-align: center;
    font-weight: bold;
    line-height: 40px;
    border: 1px solid #c0c0c0;
    border-radius: 50px;
    -moz-border-radius: 50px;
    -webkit-border-radius: 50px;
    transition: color 1420ms linear, border 1420ms linear;
    -moz-transition: color 1420ms linear, border 1420ms linear;
    -webkit-transition: color 1420ms linear, border 1420ms linear;
}
.example-transition-1:hover{
    color: #4B82AA;
    border-color: #4B82AA;
    transition: color 142ms linear, border 142ms linear;
    -moz-transition: color 142ms linear, border 142ms linear;
    -webkit-transition: color 142ms linear, border 142ms linear;
}
.example-transition-1:before{
    left: 5px;
    width: 40px;
    height: 40px;
    margin: 0;
    padding: 0;
    content: "";
    display: inline-block;
    position: absolute;
    background-color: #64C85A;
    border-radius: 50%;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    transition: left 1s linear, margin 142ms linear, background 1s linear;
    -moz-transition: left 1s linear, margin 142ms linear, background 1s linear;
    -webkit-transition: left 1s linear, margin 142ms linear, background 1s linear;
}
.example-transition-1:hover:before{
    left: 100%;
    margin: 0 0 0 -45px;
    background-color: #DC4B46;
}
.example-transition-1:after{
    top: 50%;
    left: 5px;
    width: 10px;
    height: 10px;
    margin: -5px 0 0 15px;
    padding: 0;
    content: "";
    display: block;
    position: absolute;
    background-color: #fff;
    border-radius: 50%;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    transition: left 1s linear, margin 142ms linear;
    -moz-transition: left 1s linear, margin 142ms linear;
    -webkit-transition: left 1s linear, margin 142ms linear;
}
.example-transition-1:hover:after{
    left: 100%;
    margin-left: -30px;
}

 

CSS 3 – Animations

A bit more complex animations can also be written using “CSS Animations” and @keyframes, which are available since 4.0, 5.0, 4, 12.1 and 10.0 it works as follows: You need to write a named @keyframes block, which contains different “state” blocks. This states SHOULD contain animatable CSS properties only and MUST lead with the corresponding percentages of the animation (or by using from and to). Apply the animation name, which you gave the @keyframes block, to the respective element and look how beautiful it can be. Okay, its maybe a bit more complicated, because sometimes you need to define the center position of the element using transform-origin which is sometimes a bit tricky.

Example

Show CSS Code
@keyframes exampleSpin{
    0%{
        transform: rotate(0deg);
        -moz-transform: rotate(0deg);
        -webkit-transform: rotate(0deg);
    }
    100%{
        transform: rotate(359deg);
        -moz-transform: rotate(359deg);
        -webkit-transform: rotate(359deg);
    }
}
@-o-keyframes exampleSpin{
    0%{
        transform: rotate(0deg);
        -moz-transform: rotate(0deg);
        -webkit-transform: rotate(0deg);
    }
    100%{
        transform: rotate(359deg);
        -moz-transform: rotate(359deg);
        -webkit-transform: rotate(359deg);
    }
}
@-webkit-keyframes exampleSpin{
    0%{
        transform: rotate(0deg);
        -moz-transform: rotate(0deg);
        -webkit-transform: rotate(0deg);
    }
    100%{
        transform: rotate(359deg);
        -moz-transform: rotate(359deg);
        -webkit-transform: rotate(359deg);
    }
}
.example-animations{
    width: 100%;
    margin: 15px 0;
    padding: 0;
}
.example-animation{
    width: 50px;
    height: 50px;
    display: inline-block;
    font-size: 34px;
    text-align: center;
    line-height: 50px;
    animation-name: exampleSpin;
    animation-duration: 2s;
    animation-delay: 0.142s;
    animation-iteration-count: infinite;
}
.example-animation.ease{
    animation-timing-function: ease;
}
.example-animation.ease-in{
    animation-timing-function: ease-in;
}
.example-animation.ease-out{
    animation-timing-function: ease-out;
}
.example-animation.ease-in-out{
    animation-timing-function: ease-in-out;
}
.example-animation.linear{
    animation-timing-function: linear;
}
.example-animation.steps{
    animation-timing-function: steps(4, end);
}
.example-animation.cubic{
    animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);
}
.example-animation.frames{
    animation-timing-function: frames(10);
}

 

How to JavaScript

Sometimes CSS 3 Transitions and Animations aren’t enough, doesn’t work as desired or aren’t able to do such complex methods. In this case vanilla JavaScript will be your best friend. It may is a bit more text to write, but it’s worth compared with a fat library (which has way more lines and functions as you may need). But how does it work? Basically with a Loop (using setInterval() or setTimeout()) and a small function, which calculates the “new frame” until the animation is complete. First of all, let us write a small helper function like

var animate = function(element, callback, duration){
    var step = 0, steps = Math.ceil((duration || 500) / 25);
    (function animateLoop(){
        if(callback.call(element, ((step++*100)/steps)/100) === false){
            return false;
        }
        setTimeout(animateLoop, 25);
    })();
};

Our helper method creates a setTimeout() loop within a named factory function, which gets called every 25 milliseconds. This function calls the second parameter callback using element as “this” argument, and pass a calculated step interval value (0.0 = Start and 1.0 = Finish, as on the opacity property). You need to use this number within your animation calculation to achieve a smooth animation within the setted duration (which is 500 if you don’t pass a third parameter). To stop the animation loop, you need to return false within your very own callback function.

You may think That can go heavily wrong!, because the complete animation process and the stop procedure is completely up to you! And yeah, that is probably true. So it may can slow down or completely crash old browsers, when you start one animation after another one without “stopping” the finished loops. So why depends my function on your callback? Because sometimes it is important to break the loop BEFORE it may gets completed and sometimes it is necessary to go further as 100%. Of course, I could write an extensive function which may takes care of such situations, but we don’t want bloated function bodies! Prevent errors and crashes by programming your own code right, not by trying to “catch” each single error and faulty situation.

JavaScript Example

I’ll leave you today with the following really basic example. Just press the button inside the container below and the square will move around and change its own background color. You can also press again to pause and run the animation, where it last stopped. To achieve this we need to adapt our helper function to “store” the latest step in a global variable, which gets passed back to the helper function again.

 

Show Example Code
var sprite = document.querySelector(".example-sprite");

/*
 |  EXAMPLE :: ANIMATION HELPER
 |  @since  0.1.3
 */
var animate = function(element, callback, duration, defstep){
    var step = (defstep || 0), steps = Math.ceil((duration || 500) / 25);

    (function animateLoop(){
        animationStep = step++;
        if(callback.call(element, ((step*100)/steps)/100) === false){
            return false;
        }
        setTimeout(animateLoop, 25);
    })();
};
var fadeColor = function(from, to, step){
    var color = [];
    for(var i = 0; i < 3; i++){
        var diff = from[i] - to[i];
        color.push(from[i] - (diff * step));
    }
    return "rgb(" + color[0] + "," + color[1] + "," + color[2] + ")";
};

/*
 |  EXAMPLE :: FIRST ANIMATION
 |  @since  0.1.3
 */
var firstAnimation = function(){
    animationFunc = firstAnimation;

    animate(sprite, function(step){
        this.style.left = step * 100 + "%";
        this.style.marginLeft = -Math.abs(step * this.offsetWidth) + "px";
        this.style.background = fadeColor([75, 130, 170], [100, 200, 90], step);

        if(step >= 1 || !animationState){
            if(animationState){
                setTimeout(secondAnimation, 50);
                animationStep = 0;
            }
            return false;
        }
    }, 1000, animationStep);
}

/*
 |  EXAMPLE :: SECOND ANIMATION
 |  @since  0.1.3
 */
var secondAnimation = function(){
    animationFunc = secondAnimation;

    animate(sprite, function(step){
        this.style.top = step * 100 + "%";
        this.style.marginTop = -Math.abs(step * this.offsetHeight) + "px";
        this.style.background = fadeColor([100, 200, 90], [235, 165, 65], step);

        if(step >= 1 || !animationState){
            if(animationState){
                setTimeout(thirdAnimation, 50);
                animationStep = 0;
            }
            return false;
        }
    }, 500, animationStep);
}

/*
 |  EXAMPLE :: THIRD ANIMATION
 |  @since  0.1.3
 */
var thirdAnimation = function(){
    animationFunc = thirdAnimation;

    animate(sprite, function(step){
        this.style.left = 100 - (step * 100) + "%";
        this.style.marginLeft = -Math.abs(this.offsetWidth) + (step * this.offsetWidth) + "px";
        this.style.background = fadeColor([235, 165, 65], [220, 75, 70], step);

        if(step >= 1 || !animationState){
            if(animationState){
                setTimeout(fourthAnimation, 50);
                animationStep = 0;
            }
            return false;
        }
    }, 1000, animationStep);
}

/*
 |  EXAMPLE :: FOURTH ANIMATION
 |  @since  0.1.3
 */
var fourthAnimation = function(){
    animationFunc = fourthAnimation;

    animate(sprite, function(step){
        this.style.top = 100 - (step * 100) + "%";
        this.style.marginTop = -Math.abs(this.offsetHeight) + (step * this.offsetHeight) + "px";
        this.style.background = fadeColor([220, 75, 70], [75, 130, 170], step);

        if(step >= 1 || !animationState){
            if(animationState){
                setTimeout(firstAnimation, 50);
                animationStep = 0;
            }
            return false;
        }
    }, 500, animationStep);
}

/*
 |  EXAMPLE ANIMATION
 |  @since  0.1.3
 */
var animationStep = 0;
var animationFunc = firstAnimation;
var animationState = false;
d.querySelector("button#javascript-example-animation").addEventListener("click", function(event){
    event.preventDefault();

    if(animationState){
        animationState = false;
        this.innerText = "Start Animation";
        this.className = "button-master button-green";
    } else {
        animationState = true;
        animationFunc();
        this.innerText = "Stop Animation";
        this.className = "button-master button-red";
    }
});

 

Simple Enough?

This was just the first “How to animate stuff using Vanilla JavaScript only” part, even if we talked more about CSS 3 Animations and Transitions (within a JavaScript Blog series!). But it is really important to know, that many behaviours and stylings can already be done without using this language. CSS 3 is a really important topic! However, the next part will completely talk about cool Animations and Stuff using vanilla JavaScript only, because you don’t need something like jQuery to achieve this!

But please don’t get me wrong, this whole DOM and function libraries arn’t bad (ok rather the must of them) and specially jQuery was a really good library, back in 2010. Nowadays, where anyone who uses the Internet Explorer < 11 does it just out of self-hatred and where JavaScript envolves, you don't need jQuery at all. And this Just Vanilla blog post series here on this website should prove that to you!