June 2012

Volume 27 Number 06

Building HTML5 Applications - CSS3 Effects, Transitions and Animations

By Clark Sell | June 2012

As a Web developer, you have three tools you can use to take your vision and make it reality: HTML, CSS and JavaScript. This wasn’t always the case. In the past, seemingly simple effects like text shadows or gradients sent you off to separate image editors instead of using CSS and HTML. And though you did have JavaScript, making the Web application fluid and alive usually required considerable amounts of coding. Not only did these techniques complicate building the application initially, but any small changes were costly.

Luckily, CSS3 and HTML5 eliminate the need for the image and JavaScript gymnastics of the past. You can build smooth interactions and beautiful experiences with simple declarative markup.

Now, if you’re like me, you might have just snickered a bit. Just because it’s CSS and HTML doesn’t mean it’s simple. But as you’ll see, by learning a few new CSS properties and trying them out in some cool demos, you’ll save countless development hours—not to mention the hours spent negotiating the need for a particular effect with your client.

Shadows

Let’s start off easy and look at some basic shadowing effects. For me, effects are all about altering the perception of an object. For example, take a look at the text shadow and box shadows in Figure 1.

Shadow Effects
Figure 1 Shadow Effects

This effect provides the illusion of a directional light source hitting an object and that object in turn casting a shadow on the objects around it. This helps give the perception of depth and some might even say it helps the object look like it’s floating.

Adding a shadow isn’t hard, so let’s add a text shadow to a header:

h1 {
  text-shadow: black 2px 2px 12px 2px;   
}

Here are the different text-shadow properties:

  • Shadow color (optional). You can specify a color by name, or you can use HSL or RGBA color designations.
  • Horizontal offset (required). This indicates the horizontal position of the shadow. Positive values move the shadow to the right of the object; negative values move it to the left.
  • Vertical offset (required). This sets the vertical position of the shadow. Positive values move the shadow to the bottom; negative values move it to the top.
  • Blur Radius. This value defines how clear the shadow text will appear. 0px is the font itself; increasing values increasingly blur an object’s edge. Negative values are not allowed.
  • Spread Distance. This value sets the distance away from the shadow—how the shadow’s shape expands outwardly (a positive value) or contracts inwardly (a negative value).

Box shadows work the same as text shadows and have the same parameters:

box-shadow: red 10px 10px 0px 0px;

Shadows are quite common. They’re used on elements such as buttons to provide depth and to give users an idea of the purpose of the element. They help point the user to the fact a particular object is somehow different from other objects visible in the UI. In the past, you likely turned to Photoshop and created PNGs to represent buttons; now you can do it in markup. Of course, I’m just scratching the surface here. You can create many more remarkable effects by adjusting opacity, border radius, gradients, typography and so forth.

Transforms

The CSS transform property lets you transform a given element in terms of size or space. To demonstrate, let’s set up an image so that when a user hovers over it, the image becomes twice as large:

#myImg:hover {
  transform: scale(2);
}

Of course this is CSS, which means you really need to include any applicable vendor prefixes. I’ll omit them for the remainder of this article, but the preceding transform should’ve looked like this:

#myImg:hover {
  -ms-transform: scale(2);
  -webkit-transform: scale(2);
  -moz-transform: scale(2);
  -o- transform: scale(2);
  transform: scale(2);
}

You’ll also want to take advantage of feature detection. This is actually one of the most important practices to implement in your Web sites today. Rather than basing the site’s behavior on user agents, you should leverage a tool like Modernizr (modernizr.com), which lets you ask the browser about its capabilities. If a user’s browser doesn’t support a particular feature you need, you can instead use a polyfill—a shim that implements the feature for the browser. This is even possible for CSS. For more information, check out “No Browser Left Behind: An HTML5 Adoption Strategy” at msdn.microsoft.com/magazine/hh394148. Now back to transforms.

Besides scaling, you can also apply transforms on a 2D or 3D plane. With 2D, you’re moving an element along its X and Y axes. Let’s take some text and rotate it 45 degrees:

 

.transform2d {
  transform: translate(0px, 0px)
             rotate(45deg)
             scale(1.45)
             skew(0deg, 0deg);
}

Figure 2shows a box that has been rotated 45 degrees.

Transforming an Element in 2D Space
Figure 2 Transforming an Element in 2D Space

Now 2D is great, but clearly 3D is the rage today—and, no, we don’t want to ask our users to put on any special glasses, but we do want people to think our boxes are about to come out of the screen. Here’s some code to do that:

.transform3d {
  transform-origin-x: 50%;
  transform-origin-y: 50%;
  transform: perspective(110px) rotateY(45deg);
}

The results are shown in Figure 3.

A 3D Transform
Figure 3 A 3D Transform

Transitions

Now let’s explore transitions, which let you change an element from one style or state to another. I’ll start with the hover pseudo class. Historically we’ve used CSS to set the states of an element, such as its initial state and its state after an event. Button elements and anchor links have two states—the initial state and the hover state. When a user activates the hover state, those properties get set. Here’s a quick example for hovering over a button:

#boxTrans:hover {
  background-color: #808080;
  color: white;
  border-color: #4cff00;
  border-width: 3px;
}

Standard stuff, and no doubt you’ve done this before. Today’s browsers are so fast that the state transition is almost instantaneous. That’s great from a performance perspective, but it presents a new problem. In some cases, that state change might be jarring or not even visible. It’s entirely possible the user will never see that quick and subtle change.

With CSS3 transitions, you can manage the time it takes for a transition to occur, and control other aspects of the transition as well. For example, rather than a button just automatically changing its background color, you can now specify what should happen during that change.

Adding a CSS transition is easy—you add the transitional commands to the base element. As an example, let’s create a simple box with some text in it. When a user hovers over that box, the background color, text and border should change:

#boxTrans {
  ...
  transition: all .5s linear;
  ...
}
#boxTrans:hover {
  background-color: #808080;
    color: red;
    border-color: green;
}

As you can see, I’ve defined the transition on the #boxTrans element. I’m choosing to transition all properties of this element, and I want them all to transition linearly (that is, at a constant speed) over the course of .5s. I can also choose specific properties to transition by indicating only those properties, like so:

transition: background-color .5s linear;

Animations

Unlike transitions, where you tell the browser the start and end states, with animations you specify a series of CSS properties over a given time. Animations are really just extensions of transitions. To create an animation you use a keyframe. You can think of a keyframe as the state of an item at a given point in time within the duration set for that overall animation. Let’s create a simple animation—a small box that scrolls back and forth. First, I’ll define the element:

<html>
...
  <div class="box" id="boxAnimation"></div>
...
</html>

Let’s give that div boxAnimation a bit of style so it looks like a box:

<style>
...
  .box {
  border: 1px solid black;
  background-color: red;
  width: 25px;
  height: 25px;  
  position: relative;
  }
...
</style>

With that in place, I’ll define the base animation. I need to set both the animation keyframe and its duration. If you don’t set the duration property, the animation will never run because the default is 0. I’ll also set the number of iterations I expect the animation to run; here I want it to run 10 times for 5 seconds each (if you prefer, you could set the animation-iteration-count to infinite, which would tell the animation to run as long as the page is open):

#boxAnimation {
  animation: 'not-knight-rider';
  animation-duration: 5s;
  animation-iteration-count: 10;
}

Last, I need to define the keyframe itself. I’m going to start with a simple keyframe that will move the box across the screen. To do this, I set the from and to properties and let the browser take care of the rest:

@keyframes not-knight-rider {
  from {
    left: -100px;
  }
  to {
    left: 100px;
  }
}

If you run this, you’ll see a red box that floats across the screen and then repeats. As I mentioned, you have complete control of the animation. Let’s update that keyframe to actually control where the box is at what time and what exactly it’s doing, as shown in Figure 4.

Figure 4 Controlling the Animation

@keyframes not-knight-rider {
  from {
    left: -100px;
    opacity: 0;
  }
  25% {
    left: 100px;
    opacity: 0.5;
  }
  50% {
    left: -100px;
    opacity: 0;
  }
  75% {
    left: 100px;
    opacity: 0.5;
  }
  to {
    left: -100px;    opacity: 0;
  }
}

In Figure 4, I’m defining what the keyframe will do at a given point in a single iteration. I define a starting point (to) and an ending point (from), as well as points in between, represented as percentages of its defined duration. Quite honestly, not very difficult. Now sparking up those creative juices to come up with some wicked animations—that’s a different story!

Again, to support all of the different browsers on the market today you have to use the appropriate vendor prefixes. In the case of keyframes, this would look like @-webkit-keyframes and so on.

Note that you can see working examples of all the samples mentioned in this article online at bit.ly/I0Pa4d, and you should also check out the incredible series of interactive, hands-on CSS3 demos at bit.ly/pF4sle, where you can explore a number of the different CSS specs without ever actually writing a line of CSS.

You might notice these demos are about Windows 8. That’s because with the arrival of Windows 8, the Windows team introduced a new programming model. Web developers can now take their skills and build a native app for Windows 8 using HTML5, CSS3 and JavaScript. Microsoft has just opened a completely new surface area for you to sell your apps across the globe! I encourage you to check out the Windows Dev Center at dev.windows.com.

This is an exciting time to be a software developer, Web or otherwise. Technologies are advancing so fast, it’s easy to get overwhelmed with all of the new tools in your toolbox. Regardless, it’s important to look forward and understand the tools and techniques at your disposal. The last thing you want to do is start creating a bunch of pretty images when you can just add a few lines of CSS to achieve that drop shadow.


Clark Sell works as a senior Web and Windows 8 evangelist for Microsoft outside of Chicago. He blogs at csell.net, podcasts at developersmackdown.com and can be found on Twitter at twitter.com/csell5.

Thanks to the following technical experts for reviewing this article: John Hrvatin and Brandon Satrom