Visual Effects with CSS

This is an eye candy chapter. Eye candy is fun and nice to have, but in most cases is not essential. On the other hand, managing the limited space on the screen by having thing appear and disappear is important for the useability of a site.

This is a brief summary of the chapter. Read the chapter first for all the important concepts and techniques.

Using Descendant Selectors

The first important point is that we can change the layout of the page by adding and removing classes to the elements that need to change. However, the disadvantage of this technique is that if we make N changes via JavaScript, the page needs to have its layout recomputed N times. It's better to make one change that all our layout rules react to.

We can do that by adding a class to a top-level element of our page (such as the body), and using descendant selectors on all the lower-level elements of the page that need to change.

Raw JS versus jQuery

Your book uses

node.classList.add(classname)

to add a class to the list of classes on an element. (Think of this as converting

:::HTML
<div class="sidebar"> ... </div>

to

:::HTML
<div class="sidebar hidden"> ... </div>

You can achieve the same effect in jQuery with the

$(selector).addClass(classname);

Keyboard Events

There are three keyboard events that you might potentially be interested in:

  1. keydown
  2. keyup
  3. keypress

The last is only for real characters, not modifiers like shift or control. The keypress event is officially deprecated in favor of device-independent events, but it's likely to be supported for a long time.

Your book uses keyup, so we will too.

The event listener is invoked with an event object, and that will contain a keyCode property that is the Unicode codepoint of the key that was entered. We'll stick to ASCII, and the Escape key has a value of 27 (decimal). So, we can do something like:

:::JavaScript
document.addEventListener('keyup',function (eventObj) {
    var ESC = 27;
    if( eventObj.keyCode === ESC ) {
        eventObj.preventDefault();
        ...
    }
});

Pseudo Classes

You can add a pseudo-class to a CSS rule that will apply when the element is in a particular state. For example, a hyperlink that has been visited can be shown differently than an unvisited hyperlink, even though they are both hyperlinks. The default blue/purple for unvisited versus visited hyperlinks could be done as shown below. We can even make them green when they're hovered over and red at the moment they are clicked:

:::CSS
a:link    { color: blue; }
a:visited { color: purple; }
a:hover   { color: green; }
a:active  { color: red; }

Try it on the following link:

I am a hyperlink to somewhere you have probably never been before

We will use the :hover pseudo-class in this chapter to trigger a transition

CSS Transitions

Instead of instantaneously changing the appearance of a page when applying new CSS rules, the browser can gradually change the layout to produce animations. The MDN article on transitions is, I think, a little clearer than our book. Here's an example. Hover over the middle box to see the effect.

the quality of mercy is not strained
it droppeth as the gentle rain from heaven
upon the place beneath

Here are the CSS rules that accomplish that example. Note that the middle box is defined with the same rules as the before box, and the :hover pseudo-class is the same as the after box. The sole unique rule is the transition property, which specifies which properties change and how long. Here, I made them all 2 seconds long.

:::CSS
.box {
    display: inline-block;
    font-family: arial;
    width: 30%;
    vertical-align: top;

}
#before, #during {
    border: 1px solid green;
    font-size: 10px;
    height: 50px;
    background-color: #4080ff;
    }          
#during {
    /* transition these properties over 2 seconds each */
    transition: border 2s, height 2s, font-size 2s, background-color 2s;
}
#after, #during:hover {
    border: 4px solid red;
    height: 150px;
    font-size: 30px;
    background-color: #80ffff;
}

Easing

The transitions are, by default, just done in a linear way. For example, if the height has to change by 100px in 1 second, then it might change in 10 discrete steps of 10px every 100 milliseconds. (The length of time between steps is determined by the refresh rate of the browser.) However, the linear transitions can be changed using easing which changes the timing function. There is a list of timing functions on MDN.

Custom Timing Functions

You can even create your own timing functions, say using cubic-bezier.com

jQuery Animations

The effects that our book describes are for the newest browsers (see some of the warnings an MDN). jQuery provides another way to do animations in an easy way that is compatible with older browsers, since the animations are done by jQuery. You can read the details here: jQuery animate() method. jQuery's animate() method even includes options for different easing functions.

It's very easy to use. Try clicking on the following box:

Now is the winter of our discontent...

Here's the JQ code. You'll see that the .animate() method's first argument is a JS object literal that contains a collection of target CSS values, just like the .css() method. The second argument says how many milliseconds it should take to achieve that change.

:::JavaScript
$("#box1")
    .css({height: "50px", "font-size": "10px"})
    .click(function () {
        $("#box1").animate({height: "200px", "font-size": "20px"},
                           2000);
        });

Note that I could have specified the initial CSS using CSS style rules instead of JQ's .css() method, but I like using the same medium for specifying both the starting and ending values.