Effects

A brief clarifying look into how callback functions are used.

Scroll down...

Content

Resources

Comments

Events in jQuery (and JavaScript) are sort of like the scaffolding that holds together all the interactions of your page. Effects (aka Animations) are the facade -- they make things look great.

An effect is something like a dropdown menu folding open or a button highlighting or a modal fading into view. They take the binary world of "there" vs "not there" and connect the dots in a way that's visually pleasing. Effects are the icing that really makes your application look professional (if done well).

It's a good thing JavaScript is so good at asynchronous event handling because effects are all about timing. A typical effect uses a simple equation to determine how much change to display between two states of an element. For instance, it might take an email signup modal and slide it into view over a period of 500ms, starting quickly and then easing into place.

All aspects of that event are governed by vanilla JavaScript that has been abstracted into handy helper functions provided by jQuery. In this lesson, you'll learn how effects are handled and you'll be introduced to some of the more useful ones. Our goal is for you to understand how to interact with effects, not memorize all the ones out there. You'll have plenty of time to go exploring the documentation and additional libraries like jQuery UI on your own.

Showing and Hiding

The simplest effects aren't too flashy. You can easily use the show and hide methods on any jQuery object (or objects) to set its display property to none.

The toggle function we've mentioned before will show if the object is hidden or hide if the object is visible. This means the element acts like it's been removed from the DOM -- if it was taking up space, that space will collapse.

Examples:

// Hide, then show, then toggle
// Interestingly, `hide` returns the updated
// object while `show` does not... careful!
$( "p" ).first().hide();
//=> [<p style=​"display:​ none;​">​…​</p>​]
$( "p" ).first().show();
//=> [<p style=​"display:​ none;​">​…​</p>​]


// ...it worked though:
$("p").first()
//=> [<p style=​"display:​ block;​">​…​</p>​]


// Toggle between visibility states
$( "p" ).first().toggle();

Show and hide don't have to be binary, though. You can pass in a duration and they will slowly hide during that number of milliseconds. This will not be a smooth fade out -- it both fades and slides the element off to one side:

// take a little time...
$( "p" ).first.hide(500);
[<p style=​"display:​ none;​">​…​</p>​]
$( "p" ).first().show(1500);
[<p style=​"display:​ none;​">​…​</p>​]

Fading and Sliding

Simple slide effects reduce an element's height property over the specified time period while fade effects alter the opacity of the element until it disappears entirely:

Make me do things!
// fading and sliding galore!
$('div').first().fadeOut(1000);
$('div').first().fadeIn(1000);
$('div').first().slideUp(1000);
$('div').first().slideDown(1000);

Order of Operations

If you chain animation methods together with normal jQuery functions and expect that one will begin when the other one finishes, you're in for a world of trouble. Animations are asynchronous. As you're no doubt well aware by now, asynchronous events like animation effects take place outside the normal order of execution so any normal function that's chained to it will execute immediately after the animation BEGINS.

After starting, JavaScript uses the setInterval looping function behind the scenes to change the CSS property in question.

Note that you CAN chain effects directly onto other effects. Effects have their own special queue (the fx queue), so you can chain them together one after another.

// Assuming the added class displays the
// div as normal, you would see the opacity
// decrease over 10 seconds and then immediately
// the element will POP back into view
// because, when the opacity reaches 0, the
// fadeOut animation is *supposed* to set the
// display to none but our addClass has long
// since overridden that (we assume)
// ... try it!
$("#my-div").fadeOut(10000).addClass("show-div");


// This will take 20 seconds to finish
$("#my-div").fadeOut(10000).fadeIn(10000);

All animations take an optional callback which solves these problems -- it will always execute upon completion of the action.

// let us know in 10 seconds!
// Note that `this` is NOT a jQuery object,
// it is the normal DOM object you're fading
$("div#special").fadeIn(10000, function(){
  console.log("all done fading in " + this + "!");
})

If you target multiple elements with your fadeIn effect, the callback will run once for EACH element. The opposite is true if you (accidentally) target no elements -- the callback won't run at all. You already know how to check whether you've got an empty selector by checking the length of the returned object, so this shouldn't be a problem.

Managing Animations

Sometimes, a user will interact rapidly enough that animations begin to pile up on top of each other and the web page either becomes very jerky or it all devolves into chaos. As you know, JavaScript maintains a message queue. If that queue fills up more than your browser's render function can keep up with (at 60Hz or 16.6ms), messages will keep piling up faster than they can be processed and rendered and you're in trouble.

These functions will help you manage animations in mid-stream to avoid that kind of situation:

// immediately stop all animations running
// on selected elements
$(".stop-divs").stop();


// To stop any elements which are currently
// being animated, look for the pseudo-selector
// `:animated` and stop those
$("div").filter(":animated").stop();


// create a button to stop all animations
$( "<button type='button'></button>" )
    .text( "Stop Animations" )
    .on( "click", function() {
        $( "body *" ).filter( ":animated" ).stop();
    })
    .appendTo( document.body );

You can delay animations with the appropriately named delay function:

// delay a second in between animations
$("p").hide().delay(1000).show();

jQuery.fx

The master control board for jQuery animations is the $.fx object. It has properties that control all the default animation settings, including how fast or slow elements move by default or how many frames per second you want animations to display at.

If you want to disable animations altogether, set $.fx.off = true. This will ignore interim states and just make objects jump to their final state.

Customizing Animations

Any CSS property that can transition between two numerical values can be animated. This includes everything from position (X and Y coordinates) to size (height, width) to color (RGB values) to opacity. The animate function takes care of this for you.

animate isn't quite as straightforward out of the box as the other properties because you'll need to pass it an object with the desired options. The default signature is:

// only the options are required
animate( { options object }, duration, easing, callback)

See the docs for more info.

The options object contains keys with the name of each CSS property you want to animate and values for what number these properties will end up at.

Here is an example which moves opacity to 0.25 and increases the left value by 50 px:

// Custom effects with .animate()
$( "div.funtimes" ).animate({
    left: "+=50",
    opacity: 0.25,
    // Including easing for just this property:
    top: [50, "swing"]
  },
  300, // Duration
  function() { // Callback when the animation is finished
    console.log( "done!" );
  }
);

Easing

Easing is the equation that governs the transition between two properties. By default, this transition is "swing", which starts fast then slows to the final destination. The other available value is "linear", which looks a bit mechanical when used in reality.

Easing is one thing that front-end developers and particularly interaction designers love to play with. There are a number of plugins for jQuery (like jQuery UI) which provide a whole range of additional easing functions, for instance bouncing into place.

Animating Color

You actually can't animate color by default because it can't be broken down to just a single value like the other properties. That said, there are a number of different plugins available (again, including jQuery UI) which will allow this.

Browser Load

A word of caution -- it's fun to play with animate but be aware that it puts a fair bit of stress on the browser's computational resources. If you overuse it or need to support slower machines (and mobile!), it can backfire and cause jerky display issues.

If you choose to bring in additional plugins like jQuery UI, not only will they increase page loads but they will potentially add to this problem. This may be justified by your project, but you should keep it in mind.

Queuing

As we mentioned above, animations have their own special queue called the Effects Queue. It's managed by the $.fx object we briefly talked about above. If you're so interested, you can build your own custom animations which queue and dequeue themselves but that's well beyond our scope here.

Animations and Compatibility

As said by jqfundamentals:

An important note about animations: In modern browsers, and especially on mobile devices, it is often much more efficient to achieve animations using CSS rather than JavaScript. The details of doing this are beyond the scope of this guide, but if you are only targeting mobile devices or browsers that support CSS animations, then you should use CSS for animations where possible. You may also want to consider setting jQuery.fx.off to true on low-resource devices; doing so will cause animation methods to immediately set elements to the desired state, rather than animating to that state.

Further Reading

Browse through the options available in the jQuery documentation for effects for more inspiration about what's out there.

If you really want to drool, poke around the jQuery UI library demos.

Code Review

The important bits of code from this lesson

// hide, show, and toggle
$( "p" ).first().hide();
$( "p" ).first().show(1500);
$( "p" ).first().toggle();

// fading and sliding galore!
$('div').first().fadeOut(1000);
$('div').first().fadeIn(1000);
$('div').first().slideUp(1000);
$('div').first().slideDown(1000);

// provide a callback
$("div#special").fadeIn(10000, function(){
  console.log("all done fading in " + this + "!");
})

// stop animations on an element
$(".stop-divs").stop();

// delay in between animations
$("p").hide().delay(1000).show();

// Custom animations
$( "div.funtimes" ).animate({
    left: "+=50",
    opacity: 0.25,
    top: [50, "linear"]  // easing
  },
  300, // Duration
  function() { console.log( "calling back, done!" ); }
);

Wrapping Up

jQuery's effects are really fun to play with once you get the hang of the syntax. With these animations under your belt, you can hack together pretty much any web page you've ever seen. You'll get to play with them during the upcoming projects.



Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

Sorry, comments aren't active just yet!

Next Lesson: Intervals and Timeouts