object(WP_Query)#69 (47) { ["query_vars"]=> array(56) { ["page"]=> int(2) ["category_name"]=> string(4) "blog" ["paged"]=> int(2) ["error"]=> string(0) "" ["m"]=> int(0) ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["name"]=> string(0) "" ["static"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["tag"]=> string(0) "" ["cat"]=> string(1) "1" ["tag_id"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["comments_popup"]=> string(0) "" ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["fields"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["ignore_sticky_posts"]=> bool(false) ["suppress_filters"]=> bool(false) ["cache_results"]=> bool(false) ["update_post_term_cache"]=> bool(true) ["update_post_meta_cache"]=> bool(true) ["post_type"]=> string(0) "" ["posts_per_page"]=> int(15) ["nopaging"]=> bool(false) ["comments_per_page"]=> string(2) "50" ["no_found_rows"]=> bool(false) ["order"]=> string(4) "DESC" } ["tax_query"]=> object(WP_Tax_Query)#90 (2) { ["queries"]=> array(1) { [0]=> array(5) { ["taxonomy"]=> string(8) "category" ["terms"]=> array(1) { [0]=> string(4) "blog" } ["include_children"]=> bool(true) ["field"]=> string(4) "slug" ["operator"]=> string(2) "IN" } } ["relation"]=> string(3) "AND" } ["meta_query"]=> object(WP_Meta_Query)#89 (2) { ["queries"]=> array(0) { } ["relation"]=> NULL } ["post_count"]=> int(15) ["current_post"]=> int(-1) ["in_the_loop"]=> bool(false) ["comment_count"]=> int(0) ["current_comment"]=> int(-1) ["found_posts"]=> string(3) "543" ["max_num_pages"]=> float(37) ["max_num_comment_pages"]=> int(0) ["is_single"]=> bool(false) ["is_preview"]=> bool(false) ["is_page"]=> bool(false) ["is_archive"]=> bool(true) ["is_date"]=> bool(false) ["is_year"]=> bool(false) ["is_month"]=> bool(false) ["is_day"]=> bool(false) ["is_time"]=> bool(false) ["is_author"]=> bool(false) ["is_category"]=> bool(true) ["is_tag"]=> bool(false) ["is_tax"]=> bool(false) ["is_search"]=> bool(false) ["is_feed"]=> bool(false) ["is_comment_feed"]=> bool(false) ["is_trackback"]=> bool(false) ["is_home"]=> bool(false) ["is_404"]=> bool(false) ["is_comments_popup"]=> bool(false) ["is_paged"]=> bool(true) ["is_admin"]=> bool(false) ["is_attachment"]=> bool(false) ["is_singular"]=> bool(false) ["is_robots"]=> bool(false) ["is_posts_page"]=> bool(false) ["is_post_type_archive"]=> bool(false) ["query_vars_hash"]=> string(32) "c710369e85d73820e946f7de0f8adb97" ["query_vars_changed"]=> bool(false) ["thumbnails_cached"]=> bool(false) ["query"]=> array(3) { ["page"]=> string(2) "/2" ["category_name"]=> string(4) "blog" ["paged"]=> string(1) "2" } ["request"]=> string(341) " SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (1) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 15, 15" ["posts"]=> &array(15) { [0]=> object(stdClass)#116 (25) { ["ID"]=> int(3631) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-08-22 10:52:32" ["post_date_gmt"]=> string(19) "2011-08-22 00:52:32" ["post_content"]=> string(1749) "

McFarlane Prize 2007

In 2006, Maxine and I started a prize for excellence in Australian Web design in honour of Nigel McFarlane, Australian web and open source pioneer.Unlike many awards, it's not about popularity, it's about excellence - as assessed by a Jury of genuine experts in the fields of design, coding, accessibility and user experience. It's all about recognising best practice, and sites that go that little bit more.We've just launched this year's prize nomination period. You've got month to nominate a site you've worked on, or a site you think is worthy of the prize.The criteria for entry are straightforward
  • it must be a site developed by an Australian individual or team
  • it must have launched or been significantly upgraded between September 22nd 2010 and September 23 2011 (you have another month to finish your site or upgrade!)
And, there's no cost to enter.The shortlist of 6 finalists will be announced early October, and the overall winner, as has become tradition, at Web Directions South, on October 13th, with all shortlisted finalists receiving recognition for their achievement, as our guests at the closing keynote session day 1. Help show the strength of the Australian Web Industry and enter your work. You can enter as many sites as you like!" ["post_title"]=> string(65) "The 2011 McFarlane Prize for Excellence in Australian Web Design " ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(64) "the-2011-mcfarlane-prize-for-excellence-in-australian-web-design" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-08-22 10:52:32" ["post_modified_gmt"]=> string(19) "2011-08-22 00:52:32" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3631" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "1" ["filter"]=> string(3) "raw" } [1]=> object(stdClass)#117 (25) { ["ID"]=> int(3580) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-08-05 08:01:17" ["post_date_gmt"]=> string(19) "2011-08-04 22:01:17" ["post_content"]=> string(40686) "

A brief history on Animation of the Web

If you've been developing for, or even just using the web for more than about 15 years, you'll likely remember a time when animated effects were the bomb. Animated GIFs adorned just about every page, spinning globes, little men with jack hammers, self-folding winged envelopes. And if you're very unlucky, you'll remember the explosion of blinking content on the web around 1995, as the blink element in the then dominant Netscape browser took hold of the imagination of designers everywhere (for killing off the non-standard blink element alone, the web standards movement deserves at the very least a Noble Peace Prize). And perhaps the single widest JavaScript use in its earliest days was for creating image rollovers, until CSS got into the act with the hover state. In short, animation has had a long, if checkered career on the web.

Then, for years, animation fell out of favour, but with the rise of JavaScript libraries, we've seen the re-emergence of animated interfaces.

CSS3 animation

In the last 2 or 3 years, CSS3 has got into the act, providing a reasonably straightforward declarative way of creating even quite sophisticated animations, where complex JavaScript had previously been required.

In this article we'll take a look at two related ways CSS3 provides for creating animations and animated effects, CSS Transitions and CSS Animations. We'll look at how to create them, browser support, some interesting gotchas, and yet again, I'll introduce a tool, AnimatR, I've created to help you more easily, and quickly, create cross-browser CSS animations. But please use animations wisely, tastefully and sparingly - we've take nearly 15 years to recover from the "blink tag". Let's not wait until 2026 for our next opportunity to get animations on the web right.

The JavaScript controversy

First up, let's address a now fading controversy. When CSS animations were first proposed and experimentally introduced in Webkit, (coming up on 4 years ago now), many prominent, thoughtful developers felt strongly that animations were rightfully the domain of JavaScript, not CSS. Among the strongest, and most articulate, of those critics was Jonathan Snook, who subsequently revisited his concerns, and changed his position. In short, the concern is that animation is a kind of behavior, considered the domain of JavaScript, not presentation, the domain of CSS. But the simplest way of understanding an animation is that it is the change of presentational aspects of an element (height, width, color, etc.) over time. In short, animations are presentation, even if prior to CSS3 Transitions and Animations, they could only be achieved via JavaScript.

We also increasingly have the benefit that CSS based animation is being hardware accelerated in browsers, making for smoother animations and transitions even on relatively low powered mobile devices.

Let's begin with the simpler CSS Transitions, then continue with CSS Animations. Animations reuse many of the concepts, and even syntax of transitions, so what we learn about transitions we can apply with animations as well.

Transitions

In CSS3, there are two kinds of animated effects - transitions and animations, which work in very similar ways. You might even think of transitions as simple kinds of animations. Transitions are the animation from one set of an element's CSS property values of to another set. At their simplest, that might be a smooth animation from a background-color of red to a background-color of green.

Animations enable multiple changes to the presentational properties of an element over time - for example a 2 second animation from background-color of red to green, then a 1 second transition back to red again, repeated indefinitely (we'll see less boring, and more useful animation examples shortly).

First introduced in Webkit and now supported across all modern browsers, including IE10 developer previews, transitions allow us to animate the change in presentation between two states, that is two sets of CSS properties. At its simplest, a transition might be just a smooth change from one value of a property to another value, over a specified period of time - for example, the smooth change of height over 2 seconds. To create simple transitions, we use the transition-property property, with a space separated list of CSS properties to be animated, and the transition-duration property, to specify how long the animation should take.

Here's a really simple example: let's cross fade a background-color from red to blue in 2 seconds.

p {
	transition-property: background-color;
	transition-duration: 2s;
	background-color: red;
}

Which leaves one simple question to answer - how do we trigger the change, and so the animated transition? Well, here's the deceptive simplicity of transitions - they take place any time the specified property (in this case background-color) changes. So, if the background-color changes because we have a different background-color specified for the hover or other state, or if we use JavaScript to change the background-color, then those changes in color will be animated! Let's try it out. If we specify a different background-color when the paragraph is in a hover state, like so:

p:hover {
	background-color: blue;
}

Then any time you hover over a p element, the color will fade. Let's see that in action below

In all modern browsers (except IE9) this background color should fade from red to blue when you hover over it

A little pro tip as we go along - make sure you put the transition properties (transition-property, transition-delay etc.) on the element in its normal, not hover state.

But what's with the s unit for the transition-duration property? CSS has in fact had units of time since CSS2. Originally part of Aural Style Sheets, we can specify time in either seconds (s) or milliseconds (ms) - 1,000 milliseconds in a second. CSS3 Transitions and Animations reuse these units, which are also part of CSS3 of course.

So, hopefully the basic idea is clear - with transitions we tell a browser that when a certain property or set of properties change, the change should not be abrupt, but be animated over a certain time period. Now, you might have noticed in the transition above the text color changes too - but does so without an animation. That's because we've only specified that the background-color have an animated transition, via transition-property. We can as mentioned specify multiple properties, by listing each in a comma separated list of property names like so:

transition-property: background-color, color;

If we want all of the transitions to take the same amount of time, we can specify a single transition-duration property value. But, if we want different properties to transition over different time periods, we do so by listing the time values in a comma separated list - with the time periods and properties in the same position in their respective lists. Here for instance, the color will transition over 1s, while the background-color will do so over 2s:

p {
	transition-property: background-color, color;
	transition-duration: 2s, 1s;
	background-color: red;
}

And here this is in action:

In all modern browsers (except IE9) this background color should fade from red to blue when you hover over it, over a 2 second period, while the text color changes from black to green over 1 second.

If we want to animate the changes for any properties which change, we can use the keyword all as the value for transition-property. This will ensure that regardless of which property changes, that change will be animated (not all properties can in fact be animated - we'll cover which ones can be shortly). Be careful with the all keyword - should future properties support animation, these will be animated, and it may not be clear at this stage just what these animations will look like.

There's also the shorthand transition property which takes a space separated property name and time values like so:

p {
	transition: background-color 2s;
}

Note how there are no commas between the property and time value.

Or, if we have multiple property and time pairs, we separate each pair with a commas, like so

p {
	transition: background-color 2s, color 1s;
}

And in a nutshell, that's the core of CSS3 transitions. We'll touch on some gotchas (most of which are shared with animations) a little later. And we'll take a look at browser support in detail in just a moment. But there are some optional features of transitions you might find useful, including specifying the nature of the transition, and a delay before a transition starts.

Transition Timing Functions

When a transition occurs, there are various ways the intermediate steps can take place. Let's take the example of an element moving from left to right across the screen, over 2 seconds:

This element moves from left: 0% to left: 80% in 2s when you click it. It reverses this when you click it again.

Notice how it begins quickly, then slows down as the transition draws to an end. Now, take a look at the same transition below, with a very slight change.

This element moves from left: 0% to left: 80% in 2s when you when you click it. It reverses this when you click it again.

The difference between the two is they have different transition-timing-function properties. This property "describes how the intermediate values used during a transition will be calculated". There are 5 timing function keywords (as well as some more complicated ways of describing timing functions mathematically using Bezier curves which we won't go into here), ease, linear, ease-in, ease-out, ease-in-out.

Each of these is defined in mathematical terms in the specification, but it makes much more sense to let you see them all in action.

This transition has a timing function of ease, the default timing function. Click it to see it in action.
This transition has a timing function of linear. Click it to see it in action.
This transition has a timing function of ease-in. Click it to see it in action.
This transition has a timing function of ease-out. Click it to see it in action.
This transition has a timing function of ease-in-out. Click it to see it in action.

We specify an optional timing function (as noted above, the default is ease) using the property transition-timing-function, with one of the keywords above as its value. As mentioned, we can specify a timing function as a cubic Bezier curve, but if you need to get this technical with your transitions, the best place to understand the details is the specification.

Which timing function you choose is a matter of taste, and for most purposes, the default value of ease should be fine.

Delay

There may be occasions on which we want a transition to delay for a certain amount of time before commencing, and we can do this quite straightforwardly with the transition-delay property. As with transition-duration we do this using a time value in seconds or milliseconds.

transition-duration: 150ms;

We can also specify different delays for different transitions, like this (click the element below to see the effect):

This element transitions the change of top value, but delays the transition on the change of left value for .5s.
	transition-property: top, left;
	transition-duration: 2s, 1.5s;
	transition-delay: .5s, 0s;

Browser Support and Backwards Compatibility

So, having introduced such a mouthwatering prospect for designers, just how useable is it today? In fact, surprisingly so. All modern browsers support transitions, including IE10 developer previews. Firefox has done so since version 4, Safari since 3.2, Chrome since at least version 9, Opera since 10.6, iOS since 3.2 and Android since 2.1.

It does need to be noted that not all browsers animate all property changes - we'll look at this in a little more detail in the animations section, since the list of properties applies to both animations and transitions.

However, as yet, all browsers require vendor prefixes in front of all the properties for transitions - which can make for some unwieldy CSS.

Since transitions only animate changes in style that are triggered either by a change in state (like hover or focus) or via JavaScript, they are effectively backwards compatible to just about any browsers likely to be used today. Users of those browsers simply don't see the intermediate steps between one state and the other, merely the abrupt transition they'd always have seen. We just need to ensure that in the absence an animated transition, no information is lost.

From a usability and accessibility perspective, we should also be mindful that flashing content can trigger seizures in some users, and that sudden movements of content (for example a block of content from one place to another) in the absence of an animated transition may be disorienting, particularly for users with cognitive disabilities.

Transitions are straightforward to use, widely supported, backwards compatible, and can add a little more to your site or application. However just make sure you don't overdo them. Remember the <blink>.

Animations

Similar in many ways to transitions, CSS Animations allow us to create multi-step animated content using only CSS and HTML (though we will often want to use just a little JavaScript to trigger the animation).

I've mentioned that animations and transitions have a good deal in common - here's a quick look at their similarities and differences.

Similarities between CSS Transitions and Animations

  • Both animate the change in CSS property values over a period of time
  • Both have a duration
  • Both have an optional delay
  • Both have an optional timing function, defined in the same way

Differences between CSS Transitions and Animations

  • Animations can repeat any number of times
  • Animations can be specified to go in a forward and reverse direction
  • Animations can have any number of defined intermediate steps, called "keyframes", but transitions only have a defined start and end "keyframes".
  • With transitions we can specify an animation for any property which changes, using the all keyword. With animations, we need to specify every property we want animated.

How CSS Animations are defined

Creating a CSS3 animation is a little more work than creating a transition, involving two interlinked steps.

We need to create a regular CSS rule, which selects the element or elements we want to be animated, and we give this rule a set of CSS properties related to animations (we'll look at these properties in a moment).

We also create an @keyframes rule, similar to an @media rule, which defines the two or more keyframes in our animation. If we have simply two keyframes, for the beginning and end of our animation, a transition is most likely the better choice. Each keyframe specifies the state of the animated properties at that particular time during the animation.

While it might sound a little complicated, each step is quite straightforward. Let's take a look at each in turn.

The animation properties

Just as with transitions, we specify various aspects like the duration and timing function of the animation using CSS properties. But first we need to declare which @keyframes rule will be used to specify the keyframes of our animation, which we do using the animation-name property. Animation names follow the same rules as HTML4 id values - alphanumeric characters, dashes and underscores, and begin with a letter. Here we're specifying that the header element should be animated using an @keyframes rule with the name opening-sequence (we'll see very shortly how we give @keyframes rules names).

header {
	animation-name: opening-sequence;
}

Notice how the animation-name value is not quoted.

We'll return to familiar territory by specifying a duration and timing function for the animation, using the properties animation-duration and animation-timing-function. As with transitions, the duration is specified in seconds or milliseconds, while the timing function takes one of the keywords we saw earlier (or again a more complex formula we'll not go into here).

header {
	animation-name: opening-sequence;
	animation-duration: 5s;
	animation-timing-function: ease-in;
}

As with transitions, we can also delay the beginning of an animation, here using the animation-delay property, with a value once again in s or ms.

header {
	animation-delay: 500ms;
	animation-name: opening-sequence;
	animation-duration: 5s;
	animation-timing-function: ease-in;
}

So far, all should be very familiar from transitions. Now we meet two new properties. The first is for specifying how often the animation runs (once, a certain number of times, or indefinitely). The other is for specifying what happens when a repeating animation completes - should it begin again from its initial state, or play the animation in reverse? Let's take a look at each.

Specifying that an animation should run more than once is very straightforward. We use the animation-iteration-count property, and give it either a numerical value, or the keyword infinite. The animation then runs the specified number of times, or indefinitely. The delay in commencing the animation only applies to the very beginning of the animation, and there will be no delay between iterations.

When an animation does run more than once, for example if an element moves from left to right on the page, what should happen when the next loop of the animation begins? There's two possibilities. The animation could begin where it did the first time - for example on the left, as in this example

animation-direction: normal;

Or, the animation could reverse direction, returning to the starting values, as the animation below does:

animation-direction: alternate;

We define this behavior using the animation-direction property, which takes one of two possible keyword values: alternate or normal. To achieve the first of the effects above, we use the animation-direction property with a value of normal. The second of the two has a value of alternate for the animation-direction property.

Now we've set up part one of our animation, it's time to create the animation itself. As we've mentioned, this is done using an @keyframes rule. The form of this rule is:

@keyframes opening-sequence {

  0% {
    /*properties to animate*/
  }

  20% {
    /*properties to animate*/
  }
  
  100% {
    /*properties to animate*/
  }
}

That is, we start with the keyword @keyframes. This is followed by the animation name. Next, inside curly braces (}"{" and "}") we have two or more keyframes. A keyframe has the form of a percentage value, and then a group of CSS properties inside their own curly braces.

The first keyframe must be 0%, and unlike elsewhere in CSS, the % is required. The last keyframe must be 100%. OK, so we can use the keyword from in place of 0% and to in place of 100%, but both the first and last keyframes must appear.

To create the animations above, we'd have this @keyframes rule:

@keyframes opening-sequence {

  0% {
left: 0%;
  }

  100% {
left: 80%;
  }
}

Note how our keyframes rule doesn't have anything to say about the direction, duration, and so on. These are properties we specify for particular elements using the animation properties we've just seen. Both of the animations just above use the same @keyframes rule - they just have different animation-direction properties. Here are the complete rules for each of those animated elements

#normal-animation {
background: red;
position: relative;
width: 20%;
animation-name: opening-sequence;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: ease;
animation-direction: normal;
}
#alternate-animation {
background: red;
position: relative;
width: 20%;
animation-name: opening-sequence;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: ease;
animation-direction: alternate;
}

The only difference between the two is the value of the animation-direction property.

Let's take a closer look at the @keyframes rule. Each keyframe is more or less like a regular CSS rule. In place of a selector like p.classname, it has a percentage value. The percentage value specifies where in the animation this keyframe belongs. For example a keyframe percentage of 40% in a 10 second animation occurs after 4 seconds.

It also has a declaration group of properties, separated by semicolons, as we'd find in a regular CSS rule. These define what the appearance of the selected element or elements should be at this point in the animation. The browser then animates the transitions between these keyframes.

Rather than go on in ever greater detail, perhaps the best way for you to get a better understanding of animations is to create some. And you don't need to fire up a text editor, just head over to AnimatR, the tool I've developed to help you create animations. I'll go into a bit more detail about how it works shortly, but it should make sense if you've read this far (and hopefully make more sense of what you have read).

Before and After Animation

Suppose we have this CSS

header {
	width: 90%;
	animation-name: opening-sequence;
	animation-delay: 2s;
	...
}

And this animation

@keyframes opening-sequence {
  0% {
    width: 40%;
  }
    
  100% {
    width: 60%;
  }
}

What width is the element during the 2 second delay before the animation begins? What about after the animation completes? In both cases, it's 90% (which may not be what you want). But we can specify that instead of the applied properties, the opening and closing keyframe properties should apply during the animation delay, and after the animation completes using the animation-fill-mode property.

animation-fill-mode can take the following keyword values:

none
the default state, as described above
forwards
the properties from the 100% keyframe will continue to apply after the animation completes
backwards
the properties from the 0% keyframe apply during the delay period of the animation
both
both the forwards and backwards cases hold

Triggering animations

We saw that transitions occur when we change the associated CSS properties, either using CSS, or JavaScript. But when do animations occur? An animation will begin as soon as a page is loaded, which may not be what we want to occur. There's various ways we can stop the animation auto-playing. We could not give an animation-name property to the elements we want to animate, and then apply this property using JavaScript when we want the animation to commence. But simpler in a way is to use the animation-play-state property. This takes one of two keywords, running or paused. We can change this using JavaScript:

element.style-animation-play-state="running";

Or even trigger an animation to run only when the user is hovering over an element (far from recommended):

header {
 animation-play-state: paused;
}

header:hover {
 animation-play-state: running;
}

Browser Support

We were in luck with transitions, as we saw they have widespread support in modern browsers, including IE10. We're not quite so lucky with animations, but support is definitely on the increase. At present, Safari since version 4, Chrome since at least 9, Firefox since version 5, iOS since 3.2 and Android since 2.1 have support for animations. While support in Opera and Internet Explorer 10 has not been announced, as both these browsers support transitions, arguable the hardest part of CSS animations to implement, support for animation in these browsers may not be too far off.

As with transitions, all animation properties must currently have vendor prefixes: -webkit-, -moz- (and so on for future browser support). This is also true for @keyframes rules, but these have a slightly unusual format. Typically we prefix the property name, but for @keyframes the prefix comes after the @ and before the keyframes keyword, like so:

@-webkit-keyframes{
}

@-moz-keyframes {
}

As with transitions, animations will typically be backwards compatible, particularly if they are used to add a layer of enhanced user experience, rather than content in their own right. One area where animations are beginning to see some use is in browser-based games. As many browsers and devices hardware accelerate animations and transitions, for applications where performance is a significant issue, as it often is with games, animations will become an increasingly attractive solution. But here backwards compatibility is a significant issue - with games, animations aren't simply decoration, they are central to the user experience. So, for some time to come, choosing to use CSS animation to develop games will necessarily mean excluding some users from playing those games.

Animations also pose a potentially significant challenge to creating accessible content. Where sophisticated animations are in essence an important part of the content, there is as yet no consensus as to how to make rich animations developed using CSS3 accessible.

Animation (and Transition) Gotchas

As a technology still in its infancy, animations do have a number of gotchas it is worth knowing about, to save hours of hair pulling and head-on-table banging. I'm sure there are many more than this, but here are some that I've come across.

Supported properties

Not all properties are animated. A list of properties that can be animated is outlined in the specification. Noteworthy is that background images can't be animated (though properties like background-position are), with the theoretical exception of gradients (in practice gradients aren't animated by any browser as yet).

It's also important to note that transitions and animations only animate property transitions which would otherwise occur. For example

@keyframes widen {

  0% {
width: 5em;
  }

  100% {
width: 10em;
  }
}

won't animate the width changes of an inline element like an <a>, because we can't set an explicit width on an inline element. Similarly, for a paragraph which is statically positioned,

@keyframes move {

  0% {
left: 5em;
  }

  100% {
left: 10em;
  }
}

won't animate the element, as we can't set the position of elements with a position: static. So, if your animation or transition isn't working, make sure the properties make sense. In the case of our link above, we could give it a display: inline-block, while in the case of the paragraph, a position: relative, and then the animations would take effect.

Animations in the Wild

So, just how sophisticated can CSS based animation be? Earlier this year, Naomi Atkinson and Mircea Piturca created an opening title sequence for our European conference, @media. Here's a video of it appearing on the big screen, in front of hundreds of people in London's famous Queen Elizabeth Hall:

Opening credits at Web Directions @media 2011 from Naomi Atkinson on Vimeo.

Renowned designer and developer Cameron Adams created these stunning opening titles for our conference, Web Directions South 2010. Displayed on two enormous screens in a theatre with a capacity of 1,000, it was an amazing sight to see. Note, this was expressly designed for 1024x768 resolution, and uses the font Gotham, so if possible, make sure you have the font, and set your screen to that size.

Perhaps the pre-eminent CSS Animator to date is Anthony Calzadilla, whose experiments and commercial work have really opened up people to what's possible with CSS transitions and animations. Well known examples include Madmanimation, and an animated cover for the Wired Magazine iPad edition.

You'll also find various collections of animation demonstrations like this one.

Introducing AnimatR

As CSS becomes ever more powerful and sophisticated, understanding, learning and remembering all the associated concepts, property names, syntax and so on becomes an ever more onerous job. So, as I am lazy, I've developed yet another tool, this time to help me (and hopefully you) understand and use CSS animations - AnimatR. AnimatR is not a WYSIWYG animation tool like Sencha's slick Animator, the eagerly awaited Animatable, or the just announced Adobe Edge. Rather, it's kind of like training wheels, to help you get up to speed with the concepts and syntax of animations (or for me a kind of Zimmer frame to help me totter along with all these new fangled CSS innovations).

It helps you easily set up the animation properties (except animation-play-state), as well as the keyframes for your animation. You can also add further style for the animated element, for example, giving it a position: absolute for animating an element's location (an ever popular pastime).

To use the code you create with AnimatR, just change the #demo selector to select the element or elements you want to animate in your pages, and paste the contents of the code field into your style sheet. AnimatR will even generate the vendor prefixed versions for -moz- and -webkit- browsers (since Opera and IE have yet to announce support, I've not added support for these browsers yet).

Use wisely

Right now, there's very little "hotter" in web development than animation, shown by the takeoff of Apple's iAD, and other mobile advertising technologies along with tools like Adobe Edge and Sencha Animator. I hope you'll agree they really aren't all that complex to use, but also that they need to be used intelligently. The novelty of stuff on the web which flashes and moves has worn off (I hope). It's time for web based animation that is smart and engaging. You have the tools - now get to it!

" ["post_title"]=> string(54) "Let the Web move you - CSS3 Animations and Transitions" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(52) "let-the-web-move-you-css3-animations-and-transitions" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-08-07 14:36:34" ["post_modified_gmt"]=> string(19) "2011-08-07 04:36:34" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3580" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(2) "14" ["filter"]=> string(3) "raw" } [2]=> object(stdClass)#118 (25) { ["ID"]=> int(3536) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-07-26 14:54:32" ["post_date_gmt"]=> string(19) "2011-07-26 04:54:32" ["post_content"]=> string(30961) "

Hard perhaps to believe, but the world wide web began without an image element. That's right, there was no way to include images as part of the content of a web page before Mosaic implemented them (here's Marc Andreesen proposing the img element at the beginning of 1993). The img element ushered in the age of included content so the web browsers could now display gif, jpeg, and more recently PNG format images in a standard way, but that's where matters stayed for more than a decade. While the non-standard embed element (ironically, now standardized in HTML5, and later standardized object element enabled developers to include audio, video, and interactive content, browsers did not implement native handling of these kinds of media - the actual rendering was left to plugins, like Flash (while the number of different commonly used plugins today is quite low, in the late 1990s there was an explosion of different plug in technologies.)

While HTML5 for the first time specifies a way of incorporating audio and video content via the mundanely named audio and video elements, the revolution in web content these bring is that browsers now no longer require plugins to play the content, rather they do so "natively". Which has the advantage that users don't need to download and install plugins, or keep them up to date. But there's more to it than that. With plugin content, browsers effectively hand over a part of the browser window and say to the plugin - "ok, this is all yours, do your worst". Which makes applying style to a video player (rounded corners, or adding a drop shadow, for instance) challenging, and effects like layering HTML based content over the top of plugin content a bit of a lottery.

HTML5 audio and video has been, in browser years, quickly adopted by all major browsers (we'll cover off browser support in just a moment). But let's first take a look at how we incorporate audio and video content into HTML5 documents, how to provide fallbacks for browsers which don't support them, and the inevitable gotchas. And once again, I'll introduce a couple of tools we've developed to make life easier for you when using native multimedia content in your web sites and applications.

There are a lot of great resources out there, which go into much more detail on some aspects we only really touch on here, particularly on the complex issue of formats and codecs, as well as the challenges of making your content accessible. There's a list of further reading at the end of the article.

We'll begin by looking at audio, and then follow up with video, which we use in almost exactly the same way as audio.

HTML5 Audio

HTML5 introduces the audio element, for embedding audio files in a page. Browsers which support HTML5 audio provide a simple audio player for playing, scrubbing forward and back through content, as well as setting the volume. It's also possible to hide these controls, and either autoplay files, or build your own player interface using HTML and the audio element's JavaScript API (which is beyond the scope of this article, but not really that difficult at all if you are competent in JavaScript).

Setting up the element

The first thing we need to do to include audio in a page is to add an audio element to the HTML. Unlike img, audio is a non empty element - that is it can contain other HTML, so has an opening and closing tag.

<audio></audio>

Of course, this isn't going to play anything, just as an img element with no src attribute won't display an image. So, you're probably guessing we add the audio file reference using a src attribute. And you're more or less right. We can do that, but there is another, better way to add a reference to the sound files we want to play. This is because the audio element can have only one src attribute, but because different browsers support different audio formats, at least for now, and for the foreseeable future, we'll need to provide browsers with multiple sound files, so that we cover all browser bases. We'll turn to how we do this in a moment, but let's first look at several other attributes the audio element can take.

controls
The controls attribute, when present, tells a browser to display the default controls for its audio player. If the attribute is not present, then no controls will be displayed.
loop
another boolean attribute, if this is present, the audio file will begin again after it has played indefinitely
autoplay
if this attribute is present, then once the sound file can begin playing, it will. autoplay should be used carefully and sparingly!
autobuffer
this is now replaced with the preload attribute which we'll look at in a moment, but as older browsers, for example Safari 4 support autobuffer instead of preload, you may wish to add this attribute as well if you want audio to be buffered by the browser as soon as a page is loaded. Browsers may choose to ignore this, or not support it at all (Opera for example doesn't support preloading of audio)

Before we continue, these attributes are boolean attributes, which you might not necessarily be as familiar with as you are regular attributes. Boolean attributes (another exampled is checked) are either true, or false, depending on whether they are present or absent on an element. So, they look like this

<audio controls loop></audio>

That is, they don't take values. If this offends your XHTML sensibilities, they can also be written like so

<audio controls="controls" loop="loop"></audio>

That is, with their name as their value as well. Why they aren't written as controls="true" is beyond me, but there you have it.

In addition to these boolean attributes, and the src attribute (which we've recommended ignoring) audio can also take the preload attribute, which has one of three values. The preload attribute doesn't force the browser to preload an audio file, but rather, suggests to the browser how it can provide the best user experience to the user (balancing the impact of downloading a potentially large file, with the benefit of faster response to their choosing to play a file). In the words of the specification, these values are

none
Hints to the user agent that either the author does not expect the user to need the media resource, or that the server wants to minimise unnecessary traffic.
metadata
Hints to the user agent that the author does not expect the user to need the media resource, but that fetching the resource metadata (dimensions, first frame, track list, duration, etc) is reasonable.
auto
Hints to the user agent that the user agent can put the user's needs first without risk to the server, up to and including optimistically downloading the entire resource.

Getting Sourcey

Having suggested we don't use the src attribute to link to the audio file to be played, how then can we do this? Well, we saw audio elements can contain other HTML elements, and in this case, we're going to use the source element (also new in HTML5), to provide links to one or more audio files in various formats. The browser can then download the format it supports, ignoring others to save bandwidth.

Like img, the source element uses the src attribute to link to a file. So, if we want to link to an mp3 file, we do so like this

<source src="http://westciv.com/podcasts/youmayknowmypoetry.mp3">

and, if we put that all together, that's all we need to play this file in browsers which support mp3 (at present, IE9, Safari, Chrome, Android and iOS).

<audio controls="controls" loop="loop">
	<source src="http://westciv.com/podcasts/youmayknowmypoetry.mp3">
</audio>

While several browsers will be able to play this content, neither Firefox nor Opera support the mp3 format natively. They both however, support the Ogg Vorbis format, so in addition, we'll link to an ogg version of this same audio file, for the benefit of users of these browsers.

<audio controls="controls" loop="loop">
	<source src="http://westciv.com/podcasts/youmayknowmypoetry.mp3">
	<source src="http://westciv.com/podcasts/youmayknowmypoetry.ogg">
</audio>

Where a browser happens to support both ogg and mp3, it will use the first source it finds which it supports, and so in this case, play the mp3 version.

So now we have an audio element, with two sources, which provide audio that can be played in all modern browsers. But what about older browsers? Can we also include support for them? Let's find out.

As an aside, beneath the seemingly simple issue of audio and video formats, there's more than a little complexity. We'll look at this whole issue separately in the gotchas section, but I'll just note here, that we can give the browser further information about the file, including it's MIME type, and a specific codec to be used to decode it using the type attribute. This can further help a browser in deciding whether to download a file - audio and video files are typically large, so browsers really should only download files they can very likely play. For now, just note we have the type attribute, which may be useful, for example, to distinguish between audio files of the same format encoded at different bitrates.

Providing fallbacks

Because we've long been able to embed audio and video in a web page using Flash (or Silverlight, and other audio playing plugin technologies), we can use this to provide a fallback player for audio content. There's two approaches to this (for simplicity, we'll only consider the case of Flash, but a similar approach can be used with Silverlight).

  1. We use the object element to link to a .swf version of our audio file, which Flash can play
  2. We use object to embed a Flash audio player which can play mp3 files

The first approach is simplest, but Flash won't display controls for the sound file - the user will have to context menu click to play, rewind, etc.

The second approach potentially involves hosting an audio player at your site, or using a free hosted player such as the Google Reader Audio Player, but has the advantage of reducing the number of audio files we need to encode, and of providing a better user experience.

In both cases, we use the object element, as the only browser we really need to worry about is Internet Explorer versions 8 and older, which support object. Unless you're looking to also cover an old version of a browser that doesn't support object (which to be honest is unlikely), there's no need to also include a nested embed element inside the object.

Here's how we go about using the object element to add the Google Reader player, and our sound file.

<object type="application/x-shockwave-flash" data="http://www.google.com/reader/ui/3523697345-audio-player.swf" width="400" height="27" >
        <param name="flashvars" value="audioUrl=http://westciv.com/podcasts/youmayknowmypoetry.mp3">
        <param name="src" value="http://www.google.com/reader/ui/3523697345-audio-player.swf"/>
        <param name="quality" value="best"/>
</object>

There's no great need to go into detail here, because all you really need to know is the value of the flashvars parameter includes the URL of the sound file. Simply replace the URL there, leaving the audioURL= part as is, and you'll be fine.

Note that this fallback won't work if the browser supports audio, but none of the audio formats you've linked to, or if the files go missing. The browser in these instances will show the native audio player controls (if you've used the controls attribute), but no sound will be played.

Lastly, what if we have a browser that supports neither audio, nor the object element? We can include fallback text (and HTML) within the object element (or if we choose not to include a flash based fallback, inside the audio element, after any source elements). We could for example link to a downloadable version of the file. Here's what this would look like if we haven't included a Flash based fallback

<audio controls="controls" loop="loop">
	<source src="http://westciv.com/podcasts/youmayknowmypoetry.mp3">
	<source src="http://westciv.com/podcasts/youmayknowmypoetry.ogg">
	
	<p>Sadly your browser can't play this audio file</p>
	<p>The good news is you can still <a href="http://westciv.com/podcasts/youmayknowmypoetry.mp">download an MP3 version</a></p>
</audio>

Gotchas

We've covered most of the things that can trip you up with audio (with the exception of the whole issue of formats and codecs which we'll cover shortly) but keep in mind these as well:

  • fallbacks only come into play if the audio element is not supported, not if the file formats aren't or if the files are missing.
  • ogg files must be served as audio/ogg or application/ogg. If the server is set up to serve these as another MIME type, Firefox will ignore them.
  • Fallback text is not for the purposes of accessibility, but as a last resort when audio is not supported (we'll look at accessibility in a moment).

But, on the whole, HTML5 audio is not particularly complicated, and in my opinion far less of a headache than using plugin based audio with the object and embed elements. As I mentioned earlier, I've built a web based tool that helps you create audio elements, including fallbacks, and hopefully helps you understand exactly what's going on. Let me know what you think

HTML5 Video

Let's now turn to incorporating video in HTML5 documents, and the good news is, it's more or less identical to audio. Where audio and video are the same, we won't repeat what we've covered earlier.

Adding the element

In place of the audio element, for video we have, not surprisingly, the video element. As with audio, we recommend you don't use the src attribute to link to the video file, but again the source element, so we can link to different formats (as with audio, different browsers support different formats, so to cover all modern browsers we need at least two different video files).

video elements can take all the attributes of the audio element - controls, loop, autoplay and preload. But in addition, it can also take the poster attribute. The value of the poster is a url that specifies a file to be used as a placeholder image when video is not playing. Here's a video element, with controls, and a poster

<video controls="controls" poster="http://westciv.com/podcasts/lesson6.jpg">
</video>

and while this won't play any video, it will look impressive, something like this

video player with poster and controls

Adding sources

Now we need to specify the video files to be played. As with audio, we use the source element, with the src attribute pointing to the video file to be played. To cover modern browsers, we need at least two formats, to simplify considerably, h.264 and either ogg/theora or webM/VP8.

<video controls="controls" poster="http://westciv.com/podcasts/lesson6.jpg">
	<source src="http://westciv.com/podcasts/lesson6.mp4">
	<source src="http://westciv.com/podcasts/lesson6.ogv">
</video>

Which now gives us video which will play in almost any modern browser, including IE9. again, we're going to add fallbacks much as we did for audio, to round out our coverage.

Providing fallbacks

The simplest way to add Flash based fallback video content is to create a .swf version of the file, and then embed this in your HTML document using the object element. If Flash is installed this will play in the user's browser, and while no controls will be shown, if you add a menu parameter with the value of true, then the user can context menu click and play, rewind and otherwise control the video.

<object type="application/x-shockwave-flash" data="http://westciv.com/podcasts/lesson6.swf" width="320" height="400">
    <param name="movie" value="http://westciv.com/podcasts/lesson6.swf">
    <param name="menu" value="true">
  </object>

All we need to concern ourselves with here is that we put the url of our video file as the value of the parameter with the name "movie", as well as the data attribute of the object element.

There are also various Flash based video players we might include, similarly to the way we included the Google Reader MP3 player. This will likely require serving the Flash application, in addition to the video files.

Again we've used only the object element, as we're really only looking to ensure IE 8 and older is served the video, and as these support object there's no need to also include the embed element.

Lastly, as with audio, we can provide fallback text or HTML to display when video is not supported. Here, we'll provide a download link when neither video nor Flash are supported.

<video controls="controls" poster="http://westciv.com/podcasts/lesson6.jpg">
	<source src="http://westciv.com/podcasts/lesson6.mp4">
	<source src="http://westciv.com/podcasts/lesson6.ogv">
	
	<object type="application/x-shockwave-flash" data="http://westciv.com/podcasts/lesson6.swf" width="320" height="400">
		<param name="movie" value="http://westciv.com/podcasts/lesson6.swf">
		<param name="menu" value="true">
		
		<p>Sadly your browser can't play this video file</p>
		<p>The good news is you can still <a href="http://westciv.com/podcasts/lesson6.mp4">download an MP4 version</a></p>
    
   </object>
   
</video>

Gotchas

HTML5 video gotchas are similar to those with audio. Fallbacks are only for when video is not supported at all. Ensure video files are served with the right MIME type. But on the whole, both audio and video are quite usable today.

As I've mentioned, the single biggest challenge is ensuring we serve the right video files, to ensure all browsers can play the video. Which means delving a little into the more complex issue of formats and encodings.

Video and Audio formats

Probably I should skip this part, and just point you in the direction of Mark Pilgrim's fantastic coverage at Dive Into HTML5. But, I feel I should at least cover this issue briefly, so here goes.

When we think of video formats, like h.264, there are in fact 2 and usually 3 separate pieces of technology involved.

  • There's the container file - for example MPEG4, WebM or Ogg
  • There's the video data, encoded with one of many possible codecs (decoding/encoding formats) such as H.264, VP8 or Theora
  • There's audio data encoded with one of many possible audio codecs such as mp3, AAC or Vorbis

So, when we talk about the video format a browser supports, it's important to understand what this actually means. It means the combination of container, video and audio encoding.

With this in mind, The current state of browser support for audio and video formats is

Video
  • Firefox 3.6+, Chrome, Android 2.1+ and Opera support Ogg/Theora (.ogv).
  • IE9, Safari 4+, Chrome, Android and iOS support MPEG4/h.264 (.mp4), although Chrome 14 will drop support for the format.
  • Firefox 4+, Chrome, Opera, and Android (2.3+) support WebM/VP8 (.webm), as does IE9 if the required codecs are installed on the system (they can be downloaded from here)

So, to cover all modern browsers, we need at a minimum, MPEG4/h.264 and either Ogg/Theora or WebM/VP8

Audio
  • Firefox, Chrome, Android and Opera support Ogg/Vorbis (.ogg).
  • IE9, Safari, Chrome, Android and iOS support MP3 (.mp3).
  • Safari, Chrome, IE and iOS support AAC (.aac).

To cover all modern browsers, we need Ogg/Vorbis and either MP3 or AAC.

The type attribute

We mentioned earlier that the source element can take a type attribute in addition to the src attribute. While not required, this can help a browser decide whether it can actually play the content located at the end of the src URL. You might think that the file extension would be enough, but not necessarily so. For example, iPhone with iOS 4 supports H.264 video up to 720p (the so called H.264 "Main Profile"), so can't play a 1020p H.264 encoded video (that is, a "High Profile" H.264 video). If we wanted to provide various H.264 profiles, for various devices, all these files will have the extension mp4. But we can provide codec information in the type attribute to differentiate between the various versions.

The type attribute's value provides two pieces of information, separated by a semicolon. First is the MIME type of the file, then (optionally) the codecs used (separated by a comma). So, for example we could provide various H.264 profiles of our video like so:

<source src='video.mp4' type='video/mp4; codecs="avc1.58A01E, mp4a.40.2"'> <!-baseline profile-->
<source src='video.mp4' type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'>
<!-main profile-->
<source src='video.mp4' type='video/mp4; codecs="avc1.64001E, mp4a.40.2"'> <!-high profile-->

(Which to tell the truth is taken directly from the HTML5 specification, and is beyond my level of understanding of the ins and outs of codecs.), but depending on your circumstances, you may find it useful to include MIME type and codecs information using the type attribute. If you do, I'm sure you'll know the codecs information to use, and now where to put it.

Accessibility

The web is about inclusivity and access to as wide an audience as possible, which includes those with hearing and visual disabilities. Creating accessible audio and video content is far beyond the scope of this article, but I do have some links for further reading below. But, it is important to note that, as spelt out in the HTML5 specification

In particular, [fallback] content is not intended to address accessibility concerns. To make video content accessible to the blind, deaf, and those with other physical or cognitive disabilities, authors are expected to provide alternative media streams and/or to embed accessibility aids (such as caption or subtitle tracks, audio description tracks, or sign-language overlays) into their media streams.

The tools

I'm not sure whether it's stupidity, or laziness, but many aspects of web development, if I've not used a particular technology for a while, I quickly find myself reaching for a reference. And sadder still, it's often the book I wrote myself! But in all seriousness, as aspects of CSS and HTML (not to mention JavaScript and the DOM) become increasingly complex, our chances of remembering every aspect of our craft, along with the subtleties of browser support, grow ever smaller (even Einstein was reputed to have said that he didn't remember the speed of light as he could always look it up). Well, mine certainly do. So, I write little web based tools to replace my dwindling brain cells.

I've recently developed two new tools, one each for audio and video, that help you easily do pretty much all we've covered here - create the elements, add controls, a poster, and other attributes, sources, and fallback audio, video and HTML. It will even tell you which browsers can play a particular file (well, it will make a guess based on the files' extensions).

You can find the audio tool here, and the video tool here.

There's also a similar excellent tool for creating HTML5 video which I wasn't aware of when creating mine, the Video for Everybody Generator. It's highly recommended.

Further reading

Here's a few of the many articles and other resources on HTML5 video and audio I've come across in my travels. They cover video and audio encoding, accessibility, some Flash players you might consider for your fallback content, browser support, and more.

The very best place to start is the video chapter in Mark Pilgrim's Dive into HTML5. Video for Everybody, the originator of the Flash fallback technique for HTML5 Video

Opera Developer Connection has a series of articles on HTML5 media, including an Introduction to HTML5 Video, and Everything you need to know about HTML5 audio and video.

The HTML5 Doctor has a detailed overview of HTML5 Audio, and video.

HTML5 Rocks has several various articles on native HTML5 media including a quick guide to audio, the basics of HTML5 video

Encoding your audio and video

Here are some great places to get tips and techniques on encoding video and audio for HTML5, and services which you can use to create the right formats of your media files

Flash players for video and audio fallback

There are some open source Flash video players you can host yourself to play your video files.

  • FlowPlayer
  • JW Player
  • Media.js supports both audio and video with fallbacks to Flash
  • VideoJS is a highly regarded JavaScript HTML5 player, with fallback support as well. You can skin it with CSS.
  • JPlayer open source jQuery HTML5 Audio / Video Library (as used in Pandora)

In addition to the commonly used Google Reader Flash MP3 Player, other Flash MP3 players you might consider include

Accessibility

Browser support

As always When Can I Use? is the place to keep up to date with browser support.

Addressing challenges playing audio and video in the Android browser.

A look at the challenges associated with video on the iPad.

A further look at HTML5 media challenges in iOS.

" ["post_title"]=> string(46) "Getting Sourcey - native HTML5 Audio and video" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(44) "getting-sourcey-native-html5-audio-and-video" ["to_ping"]=> string(0) "" ["pinged"]=> string(342) "http://www.broken-links.com/2010/07/08/making-html5-video-work-on-android-phones http://blog.millermedeiros.com/2011/03/html5-video-issues-on-the-ipad-and-how-to-solve-them/ http://blog.millermedeiros.com/2011/04/unsolved-html5-video-issues-on-ios/ http://html5doctor.com/the-video-element/ http://html5doctor.com/native-audio-in-the-browser/" ["post_modified"]=> string(19) "2011-08-07 14:35:41" ["post_modified_gmt"]=> string(19) "2011-08-07 04:35:41" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3536" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(2) "10" ["filter"]=> string(3) "raw" } [3]=> object(stdClass)#119 (25) { ["ID"]=> int(3506) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-07-19 07:46:28" ["post_date_gmt"]=> string(19) "2011-07-18 21:46:28" ["post_content"]=> string(25649) "

Getting your head around CSS3 radial gradients

We recently took a detailed look at linear gradients in CSS3. If you've not read that, you might like to spend a few minutes doing so, as the concepts are very similar, and I don't spend quite as much time in this article on the fundamentals of gradients which I've already covered there.

This time we'll look in detail at radial gradients. If you've got a good sense of how linear gradients work, radial gradients should present no great difficulty. And, I'll again introduce an updated tool for creating radial gradients, which supports the current syntax, and works across all modern browsers which support radial gradients (more on which they are shortly).

A brief history

Like linear gradients, radial gradients were first introduced in Webkit in 2008. Like linear gradients, they are still in a draft CSS3 specification, and indeed are still in something of a state of flux, so it is more than possible the final specified version will be different from that described here. As with linear gradients, radial gradients as originally proposed by Apple's Webkit team had a different syntax, and quite significantly different conceptual basis from how they are currently specified, and from how they are supported in current browsers. With Safari 5.1, all modern browsers have harmonized on the same syntax, and conceptual basis for radial gradients, which is what we cover here. Safari 4, and Chrome 10 and up support a very different syntax, and model for radial gradients, which is effectively obsolete, and which we won't cover here.

What exactly is a radial gradient?

I've thought long and hard about whether to try and explain what is really going on with a radial gradient (and for most folks, simply playing around with them is likely the best way to really come to grips with them). But, as I've yet to see a very good description of exactly how radial gradients work, here's my attempt.

You'll hopefully remember that linear gradients have a straight gradient line, from one edge of the element's background box. It could be vertically from top to bottom, or bottom to top. It could be horizontally from left to right, or right to left. Or it could be at an angle, from left to right, right to left, upwards or downwards.

linear gradient lines

Some common linear gradient lines

We then specify two (or more) colors to create the gradient along this line. The gradient "smoothly fades" from one color to the next along the gradient line. So, what exactly does "smoothly fades" mean? To get all technical on you, the Image Values and Replaced Content module of CSS3 says "between two color-stops, the line's color is linearly interpolated between the colors of the two color-stops, with the interpolation taking place in premultiplied RGBA space". Glad you asked? And if you really want to get down and dirty with linear interpolation, the spec has a whole section on it.

Radial gradients also specify a gradient line, but this time, the line goes from the center of an ellipse, outwards in each direction to the edge of the ellipse. Along this line color also "fades smoothly" from one color stop to the next.

We also know from linear gradients, that the gradient can have intermediate stops between the starting and final color. Not surprisingly, radial gradients can have color stops, specified as being a certain percentage, or length value, along the gradient, between the start and final colors.

But where radial gradients differ significantly from linear ones, is the shape and size of the gradient, as well as a gradient's location.

In essence, to specify a radial gradient, we give the gradient

  • a location
  • a shape
  • a size
  • one or more color stops

Let's look at each of these, though slightly out of order, because to understand how they all work, we need to understand a little bit about what an ellipse is (this won't hurt a bit I promise).

Ellipses

an ellipse

An Ellipse, showing the major and minor radii.

An ellipse is what we more colloquially call an oval. It differs from a circle in that its width and height are different from one another (strictly speaking, a circle is a kind of ellipse where the width and height are equal).

circle

As you can see here, a circle is a special kind of ellipse where these two lines are the same length.

If you drop a vertical line through an ellipse at its tallest point, and a horizontal line through it at its widest, where these two intersect is the center of the ellipse. The longer of these two lines is called the major semi-axis or major radius, and the shorter the minor semi-axis or minor radius.

From all this, the key concepts to take away are

  1. What the center of an ellipse is
  2. What the radii of an ellipse are

Radial gradient location

We give a radial gradient a location by specifying where its center will be in relation to the element it is a background image for (we'll leave aside the case where the gradient is used elsewhere for now).

We can specify the location of the ellipse's center essentially the same way we specify the location of a background image with the background-position CSS property. We specify the horizontal position of the background, and optionally the vertical position using either keywords (left, center right, or top, center, bottom), length values, percentage values, or some combination of these. For example we might have

  • left bottom
  • left 100%
  • 0% bottom
  • 0% 100%

Which all specify that the center of the gradient ellipse should be in the left bottom corner of the element background.

Where the second value is omitted, it is treated as center (similarly, if we omit the first value as well, the center of the gradient ellipse is in the center of the element's background.)

So, let's start putting together a radial gradient. As we saw with linear gradients, a gradient is not a CSS property. Rather it is a value, that can in theory be used anywhere an image would be used, but in practice, typically only as a background image on an element. Here we'll start a radial gradient as the background image of an element, and give it a location. We'll place the gradient in the center of the element's background.

background-image: radial-gradient(50% 50%,

Notice how the horizontal and vertical center values are simply separated by a space, and then pair is then followed by a comma. Note too that this is not yet a gradient, just the start of one. We still need to specify the shape and size, plus its color values.

Radial Gradient shapes and sizes

Now we've specified the location of the center of the gradient, we need to specify the shape and size of the ellipse. These can be specified in one of two ways, implicitly, or explicitly.

Explicit shapes and sizes

We explicitly specify the shape and size of the ellipse for our radial gradient by specifying the lengths of the major and minor radius, using a length or percentage value. (as of July 2011, this aspect of radial gradients was not supported by any browser, so we'll only cover this briefly).

For example, we might specify a width of the gradient ellipse as being 50% of the width of the background element and 30% of the height of the element with the values25% 15% (note that these values specify the radius, which is half the width or height). If we specify identical values for width and height, then the two radii are the same length, and so we get a circular gradient. Here's what our gradient would look like with this explicitly declared width and height

background-image: radial-gradient(50% 50%, 25% 15%,

Notice again, the width and height values are separated only by a space, and then we follow these by a comma.

Implicit shapes and sizes

Alternatively, instead of specifying an explicit width and height to give us the size and shape of our gradient, we can specify the size and shape implicitly with keywords. In practice, this is the only one of the two forms that is supported in contemporary browsers, and so is the one you should use.

Shape

This part is very straightforward, we just use one of two keywords ellipse or circle, to specify the shape of the gradient. So, we create an elliptical shape for our gradient like so

background-image: radial-gradient(50% 50%, ellipse

Now it's time to give the gradient a size.

Size

If we are declaring the size of the gradient implicitly, we specify the size of the gradient shape using one of several keywords. Each of these keywords specifies an algorithm for giving the gradient a size. These algorithms are sometimes slightly different for ellipses and circles. While they may initially seem quite complicated, they make sense once you understand the key principle of each. Here's my way of understanding what is going on with each keyword.

KeywordFor Circular gradientsFor Elliptical Gradients
closest-side

closest side for circles

with closest-side a circular gradient is sized so that it "exactly meets the side of the box closest to its center"

closest side ellipse

with closest-side an ellipse is sized so that it "exactly meets the vertical and horizontal sides of the box closest to its center"

closest-corner

closest corner ellipse

with closest-corner a circular gradient is sized so that its edge exactly meets the closest corner to its center of the box

closest corner ellipse

with closest-corner an elliptical gradient is sized so that its edge exactly meets the closest corner to its center of the box

farthest-side

farthest side for circles

with farthest-side a circular gradient is sized so that it "exactly meets the side of the box farthest from its center"

farthest side ellipse

with farthest-side an elliptical gradient is sized so that it "exactly meets the vertical and horizontal sides of the box farthest from its center"

farthest-corner

farthest side ellipse

with farthest-corner the gradient-shape is sized so that its edge exactly meets the farthest corner from its center of the box

farthest side ellipse

with farthest-corner an elliptical gradient-shape is sized so that its edge exactly meets the farthest corner from its center of the box

There are two additional keywords, contain and cover. The keyword contain is the same as closest-side, while the keyword cover is the same as farthest-corner.

Here we'll give our gradient a size of closest-corner.

background-image: radial-gradient(50% 50%, ellipse closest-corner,

As with the location of the center of the gradient, the two keyword values are separated by space, then followed by a commas

Color Stops

Now we've established the size, shape and location of the gradient, all that remains is for us to specify two or more color stops. As with linear gradients, we specify a color stop with a color, and an optional stop position, which is a length or percentage value. The simplest case is color values alone.

When color stops are specified with color values only, the stops divide the size of the gradient evenly. So, if there are 3 color stops, each color covers a third of the gradient shape, and fades into its adjacent color stop(s).

Let's take a look at an example. Here's a simple circular gradient. It's implicitly sized to touch the closest size to its center, and has three color stops, red, green and blue

background-image: radial-gradient(center center, circle closest-side, #ff0000, #00ff00, #0000ff )

Notice how each stop is separated by a comma.

And here's what it this will look like in a browser which supports radial gradients.

Simple color stops

If we add more stops, these are simply evenly spaced in the same size, as here, where we have 6 color stops, evenly spaced across the size of the gradient.

background-image: radial-gradient(center center, circle closest-side, #ff0000 ,#ff9f40 ,#fff81f ,#050a99 ,#0b990f ,#911c99 ,#d24fe0 )

six color gradients

Color stops can, as we mentioned, optionally also specify a length or percentage value. So, we can make color stops a specific distance apart from one another, like so:

percentage gradients

background-image: radial-gradient(center center, circle closest-side, #ff0000 25%, #19ff30 90%, #2f3ced 100%)

Notice again, the color and position of each stop is separated by a space, and again each stop is separated by a comma.

It's also possible to use length values, like px and em in place of percentages, and to mix all three forms of color stop (color alone, percentage and lengths). Keep in mind that percentage gradients will adapt to the size of the element, so that when it grows or shrinks in size the gradient remains in proportion to the element's size, and so in many cases, percentage gradient stops (or simple color stops specified only by color) are likely to be the most adaptable choice.

Coloring inside and outside the gradient

You might have noticed that in our examples, outside the gradient shape is a solid color background, the color being that of the last color stop specified. Once the gradient completes, whatever the finishing color is will then fill the remainder of the element's background.

In this last example, you might also have noticed the same thing happens inside the gradient shape. Our first color stop is at 25%, so from the center of the gradient to 25% of its width, we have a solid red color. The red only fades smoothly into the next color stop, green, from 25% out from the gradient shape's center.

Stop positions can in fact be greater than 100% of the size of the gradient, so we can fill the entire element with a gradient by specifying a final stop position large enough that the entire element is covered by the gradient.

Repeating gradients

As with linear gradients, radial gradients can repeat. This we specify with a slightly different value name - repeating-radial-gradient. If we take our previous gradient, and repeat it, here's what we get

repeating radial gradient

background-image: repeating-radial-gradient(center center, circle closest-side, #ff0000 25%, #19ff30 90%, #2f3ced 100%)

Where we would have solid color outside the gradient shape, we now have the gradient repeating. If we reduce the size of the gradient, the effect becomes more pronounced. In this example, we reduce the size of the gradient shape, to get the following non-repeating gradient.

small radial non repeating gradient

background-image: radial-gradient(center center, circle closest-side, #ff0000 0%,#19ff30 29%)

Now if we repeat the gradient, the effect is far more noticeable.

the same radial gradient repeating

background-image: repeating-radial-gradient(center center, circle closest-side, #ff0000 0%,#19ff30 29%)

Doing the heavy lifting for you

Shapes, sizes, centers, radii, stops... If it all sounds like a lot to learn and remember, then again we're here to help. As we've done for linear gradients, we've built a radial gradient tool, which helps you build gradients, without having to remember all the heavy lifting.

As with our linear gradient tool, in addition to just helping you create radial gradient, it has some other features.

  • You can tweet a link to a gradient you’ve created by simply clicking a button
  • You can copy the url of your gradient, and send it to someone via email, put it in a link (like I’ve done for many of these examples) or otherwise share it
  • Via the magic of HTML5 localStorage, it remembers your most recent gradient, and other settings next time you visit
  • It adds vendor prefixes for all modern browsers (as an option)
  • It adds the start color as a background color for older browsers
  • There’s a related tool for creating old-style Webkit gradients
  • It provides up to the minute browser compatibility information (provided I remember to update that as browsers change)
  • It looks really pretty, all thanks to CSS gradients of course

So give it a try, and let us know what you think.

Browser Compatibility

Despite being relatively new, and as yet not completely specified, radial gradients are safe to use in a way that is backwards compatible, and are in fact quite widely supported (we'll take a look at which browsers support them in a moment).

To ensure compatibility and accessibility when using radial gradients, as with linear gradients, it's important to

  1. include vendor specific prefixes (-o-, -ms-, -moz, -webkit-), as well as the standard form of gradient values
  2. include a background color for browsers which don't support gradients. Make sure the text of an element with a gradient background has sufficient contrast with the element's background color

Browser support

A quick summary of current browser support for CSS Radial Gradients (based on the information at the fantastic When Can I Use).

  • Safari 4 introduced radial gradients, though as noted with a different syntax from that detailed here. The vendor prefix -webkit- is required for gradients in Safari 4.1 and newer.
  • Safari 5.1 introduces the syntax detailed here, as well as continuing to support the older style syntax. Again, the -webkit- vendor prefix is required.
  • Firefox 3.6 was the first browser to support the current gradient syntax. The -moz- prefix is required, and it's currently only supported on backgrounds.
  • Chrome 10 and up (and probably earlier versions) supported the syntax for gradients detailed here. The -webkit- prefix is required.
  • Opera 11.1 introduced linear gradient support, but at present does not support radial gradients of any kind
  • Internet Explorer 10 also features CSS radial gradients, using the prefix -ms-, and also only on backgrounds.

Gradients can be computationally intensive, and may cause browsers running on older hardware difficulty. At present they are not able to be animated with CSS transitions in any browser which supports transitions.

Links, galleries, articles and more

Here are some places to go to learn more.

The wrap

I hope this article has been helpful in understanding a little more deeply what is really going on with radial gradients, and hope the radial gradient tool makes working with them enjoyable. Let me know if you've found them helpful on twitter!

" ["post_title"]=> string(21) "CSS3 Radial Gradients" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(21) "css3-radial-gradients" ["to_ping"]=> string(0) "" ["pinged"]=> string(131) "http://www.webdirections.org/blog/css3-linear-gradients/ http://www.webdirections.org/resources/lea-verou-mastering-css3-gradients/" ["post_modified"]=> string(19) "2011-08-07 14:35:48" ["post_modified_gmt"]=> string(19) "2011-08-07 04:35:48" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3506" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(2) "27" ["filter"]=> string(3) "raw" } [4]=> object(stdClass)#120 (25) { ["ID"]=> int(3475) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-07-11 21:05:05" ["post_date_gmt"]=> string(19) "2011-07-11 11:05:05" ["post_content"]=> string(23748) "

Taking your web sites and apps offline with the HTML5 appcache

There's a general (and understandable) belief by even many developers that web sites and web applications can only be used when the browser has a web connection. Indeed, this is routinely cited as one of the real advantages of "native" apps over web apps. But as unintuitive as it sounds, in almost every modern browser and device (except even for now IE10 developer previews, but here's hoping that changes), that's not the case, provided the developer does a little extra work to make their app or site persist when a browser is offline. (Of course the user must have visited your site while their browser did have a connection)

In this article, I hope to clear this whole areas up once and for all, show you how to do it, and point to some great resources out there for learning more about creating offline versions of your web sites and apps. Perhaps most importantly, introduce a simple new tool I've built to do the heavy lifting for you, ManifestR.

Even if you develop web sites, rather than applications, you can benefit from the techniques outlined here, because caching resources can seriously decrease the load time for your site, particularly on a visitors subsequent site visits.

Making a cache

As I'm sure you know, browsers cache HTML, CSS, JavaScript files, images and other resources of the sites you visit, to speed up the subsequent loading of pages. However, you never know when the browser might discard cached files, and so this is not a reliable way for sites to work offline. But what if we could tell the browser what to cache? Well, with HTML5 application caches (also known as applications caches or "appcaches") we can do just that. Let's look at how.

Making it manifest

The heart of the technique is to create an appcache manifest, a simple text file, which tells the browser what to cache (and also what not to). The resources are then cached in an "application cache", or "appcache", which is distinct from the cache a browser uses for its own purposes. The anatomy of an appcache manifest is straightforward, but there are a few subtleties.

An appcache manifest

  • begins with the string "CACHE MANIFEST" (this is required)
  • has a section, introduced by the string "CACHE:" which specifies the URLs of resources (either absolute, or relative to the location where the manifest file will be located on the server) to be cached.
  • We can also optionally specify which resources should not be cached, in a section of the manifest file introduced by the string "NETWORK:". These resources aren't just not cached, but further, won't be used when the user is offline, even if the browser has cached them in its own caches.
  • We can also optionally specify fallback resources to be used when the user is not connected, in a section of the file called "FALLBACK:"
  • You can add comments to the file with, simply by beginning a line with "#"

It's recommended that the extension for a manifest file is .appcache (previously, .manifest was the recommended extension).

Here is a very straightforward example

CACHE MANIFEST

CACHE:

#images
/images/image1.png
/images/image2.png

#pages
/pages/page1.html
/pages/page2.html

#CSS
/style/style.css

#scripts
/js/script.js

FALLBACK:
/ /offline.html

NETWORK:
signup.html

The CACHE section

In the CACHE section we list the resources we want cached. We can use either a URL relative to the .appcache file, or an absolute URL. We can cache resources both in the same domain as the cache, as well as (in most cases) other domains (we'll cover this in more detail in a moment)

Often, the only section of an appcache manifest is this section, in which case, the CACHE: header may be omitted.

Be careful with what you cache. Once a resource, for example an HTML document is cached, the browser will continue to use this cached version, effectively forever, even if you change the file on the server. To ensure the browser updates the cache, you need to change the .appcache file. This can play havoc while you are developing a site, and we'll cover some techniques for managing this in a moment.

One suggestion is to add a version, and or a date stamp to the manifest as a comment. This way, you can quickly change the date or version number, and then browsers will refresh the appcache. Browsers do this intelligently, checking to see which resources might have changed since they were last cached, and only re-caching those which have.

The Network Section

Probably the most subtle aspect of app caching is the NETWORK section. Because a great many web sites, and particularly applications, have dynamically generated content, pulled in from APIs, CGIs and so on, we may want to ensure certain resources aren't cached, and are always directly loaded when the browser is online.

That's where the NETWORK section of the cache comes in. Here, we list the resources we never want to be cached, which is referred to as an "online whitelist". So, in our example above, we are specifying that the page signup.html (located at the root of our site - remember the entries in our manifest are either absolute or relative URLs) is never cached. When online, any request for this page will always cause the page to be loaded from the server (even if the browser might have previously cached it itself). When the user is offline, any request for this resource resuls in an error (again, even if the browser might have cached the resource in its own caches).

We can also specify a group of resources located within a site in the NETWORK section using a partial URL (technically a "prefix match pattern") (note that we can't use this technique in the CACHE section, where all resources must be explicitly listed to be cached in the appcache, with one exception we'll get to shortly). Any resources which have URLs beginning with this pattern are included in the online whitelist, and never cached. As developers we then need to handle the cases where these resources aren't available because the user is offline.

There's also a special wildcard, *. The asterisk specifies that any resources that aren't explicitly cached in the appcache manifest should not be cached.

Fallbacks

App caching also allow us to specify fallback resources. The form of an entry in the FALLBACK section is two resource identification patterns. The first (in the case above simply "/", which matches any resource in the site), specifies resources to be replaced with a fallback when the user is offline. The second specifies the resource to replace any resources matching the patter. So, in this case, when any resource in the site has not been cached, and the user is offline, the page offline.html will be used instead. We can also specify resources to be replaced more specifically. For example, we could specify an offline image for any images that haven't been loaded like so

/images/ /images/missing.png

Here we're specifying that any resources located in the directory images at the top level of our site that have not been cached, be replaced with the image called missing.png found in that same directory, when we are offline.

Using the appcache manifest

So now we've created our appcache manifest, we need to associate it with our HTML documents. We do this by adding the manifest attribute to the html element of a document, where the value of this attribute is the URL of the appcache file.

The current recommendation is the appcache file have the extension .appcache. So, if our manifest is located at the root of our site, we'd link to it like so

<html manifest='manifest.appcache'>

There are also suggestions that using the HTML5 doctype may be required for some browsers to use app cache, so, make sure you use the doctype

<!DOCTYPE html>

And we're all set. Well, almost. In order for the browser to recognize the appcache file, it needs to be served with the mimetype text/cache-manifest. How you set this up depends on your site's server. At the time of writing, it's likely that this is a step you'll need to take, so if caching isn't working, that's very likely why. One of the most common servers is Apache. There are two ways in which you can set up Apache to serve .appchace files as type text/cache-manifest. At the root directory of your site, add a file with the name .htaccess, with the entry AddType text/cache-manifest .appcache (if there's already a .htaccess file, just add this line to it).

Gotchas

App caching can be very powerful, allowing apps to work while the user is offline, and can increase site performance, but there are some definite gotchas it pays to be aware of. Here's a few well worth knowing about.

Resources in style sheets

You'd be forgiven for thinking that any images in a style sheet that has been cached will be included in the appcache, but that's not so. Images your style sheet refers to must be explicitly referenced in the CACHE section of the manifest as well.

Similarly, style sheets that are imported using @import, and resources included via JavaScript must also be explicitly cached.

To help build an appcache manifest, I've developed manifestR, which we'll look at in detail in a moment. It will generate an appcache manifest for you, which includes all the scripts, style sheets, including those @imported, images, linked pages at the same site, and any images linked to in stylesheets.

There's one exception to the rule that only explicitly listed resources are cached, and it is important to understand. Any HTML document that has a manifest attribute will be cached, even if it is not listed in the manifest. This can cause all kinds of headaches while developing, which we cover shortly.

Caching Cross Domain Resources

While there is some confusion on the issue, you can in general cache content from across different domains in an app cache. In fact, without this ability, the real world value of app caching would be limited, as content distributed via a CDN (content distribution networks like Akamai) could not be cached (even content served from a differently named server within the same domain couldn't be cached). The exception to this is that when content is served over secure http (https), then the specification says all resources must come from the same origin. In an exception to this exception, Chrome in fact does not adhere to this part of the specification, and it has been argued that the single origin policy for https is too restrictive in the real world for app caching to be of genuine value.

Refreshing the cache

In effect, unlike most caching of web resources, appcaches do not expire. So, once the browser has cached a particular resource, it will continue to use that cached version, even if you change the resource on the server (for example by editing the contents of an HTML document). The exception to this is when a manifest file is edited. When the manifest is changed, the browser will recache all the resources listed in the manifest.

Caching can cause real headaches while developing a site or application, so it is recommended that during development, you avoid appcaching. One way of achieving this is to serve .appcache files with the wrong mimetype. This way, you can include the manifest attribute in your HTML elements, and serve the appcache file, just as you wold in production, but not have the effects of appcaching. Moving from development to production is as simple then as associating .appcache files with the right mimetype.

Resource hogging and lazy loading

To improve the performance of a site, you might be tempted to preload the entire site, by adding all the pages, images etc in it to the appcache manifest. And, in certain circumstances this might be desirable. It will however place considerable demands on your server, and use more bandwidth, as the first time a person visits your site, they will download more resources than they otherwise might have. Luckily, appcaches have an additional feature that can help here.

You might recall earlier that even when an HTML document with a link to an appcache manifest isn't included in the manifest file, it will still be cached. The benefit of this is that rather than explicitly listing all the pages at your site in a manifest for them to be cached, each time someone visits a page that links to a manifest, it will then be cached.

If the primary motivation for using an appcache is to ensure your site or more likely app works offline, you'll likely want to explicitly list the pages of the site, so that they'll be available offline even if the user hasn't visited them. If your primary motivation is increased performance, then let pages lazily cache when the user visits them, but cache scripts, CSS, and perhaps commonly used images.

Cache failure

An important, but subtle gotcha with appcaching is that if even one of the resources you include in your cache manifest is not available, then no resources will be cached. So, it is really important to ensure that any resource listed in your appcache manifest is available online. There's a tool we discuss in a moment, the Cache Manifest Validator, to help ensure all those resources are online.

Size limits

While there specification places no limits on the size an appcache can be, different browsers, and different devices have different limits. Grinning Gecko reports that:

  • Safari desktop browser (Mac and Windows) have no limit
  • Mobile Safari has a 10MB limit
  • Chrome has a 5MB limit
  • Android browser has no limit to appcache size
  • Firefox desktop has unlimited appcache size
  • Opera's appcache limit can be managed by the user, but has a default size of 50MB
User Permission

In Firefox, when the user first visits an appcached site, the browser asks the user's permission (as it and other browsers do for location with the geo-location API). However, unlike with geo, other browsers don't ask the user's permission. Just something to be aware of, as there'll be no guarantee with Firefox that appcaching is being used, even when supported.

Flakiness and browser support

It must also be noted that the general consensus is that appcaching is currently far from perfect across all browsers which support it. The specification is still in draft, but it should also be noted that most browsers have supported at least some appcaching for quite some time.

According to an amalgam of When can I use, Dive into HTML5 and other online resources:

  • Safari has supported offline web apps since version 4
  • Chrome has supported the feature since version 5
  • Mobile Safari has supported offline apps since iOS 2.1
  • Firefox has supported it since version 3.5
  • Opera has supported appcache since version 11
  • Internet Explorer as yet does not support offline web apps, including in IE10 developer previews
  • Android has support appcache since version 2.1

Introducing ManifestR

We've already mentioned that a particular challenge in creating an appcache is identifying all the resources you need to add to the manifest. To help you with this, I've developed ManifestR, an online tool to help you create an appcache manifest for any page. I don't recommend you use it without at least a little additional fine tuning, as what it attempts to do is locate any resources referenced from a given page. As discussed above, depending on the purpose of your appcache, this is likely to be overkill.

Drag me to your bookmarks bar.

When you use ManifestR on a page, here's what it looks for

  • images both in the same and other domains referenced in the src attribute of any img element in the page.
  • links to pages in the same domain. This can improve the performance of your site for visitors viewing other pages, and is vital if you want the entire site/app to work offline, but means potentially considerable additional load on your server the first time someone visits the site. Whether you choose to keep this list, or remove some or all of the links is an important decision to make.
  • style sheets, linked, or included via @import statements, located both in your domain, or other domains
  • images linked to in any style sheet, both those in the same domain, or other domains
  • JavaScript files, both those in the same domain, and served from other domains. Here too, you'll need to consider carefully which to include and which you want to add to the online whitelist via the NETWORK section of the manifest.

it then puts them all together in a manifest, ready for you to cut and paste, tweak, save and upload.

I hope you find it useful in building appcache manifests (and make sure you let me know via twitter what you think, and how we can improve it).

More reading

There's quite a bit available online about app caching, though keep in mind the specification, and implementations are still somewhat in a state of flux. Here's some articles and other online resources I have found very helpful -

Overviews and specifications
Tutorials and how-tos
Critiques and gotchas

as we know, all is not yet perfect in the world of the offline web just yet. Here are a couple of critiques of the current, and collections of gotchas discovered by offline pioneers.

Tools

We've already mentioned ManifestR, but you should find the The Cache Manifest Validator another really useful tool. Remember, for appcaching to work, every resource you list in your manifest must be available, or nothing will be cached. The Cache Manifest Validator can make sure all your resources are available.

Compatibility

Probably the best place to keep up to date with the ever changing field of HTML, CSS3 and other new web technology support in all modern browsers is When Can I Use?. You can find a snapshot of current browser support above.

" ["post_title"]=> string(13) "Get off(line)" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(11) "get-offline" ["to_ping"]=> string(0) "" ["pinged"]=> string(146) "http://www.standardista.com/html5/offline-applications-application-cache-manifest-files http://hacks.mozilla.org/2010/01/offline-web-applications/" ["post_modified"]=> string(19) "2011-08-07 14:35:54" ["post_modified_gmt"]=> string(19) "2011-08-07 04:35:54" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3475" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(2) "31" ["filter"]=> string(3) "raw" } [5]=> object(stdClass)#121 (25) { ["ID"]=> int(3467) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-07-01 15:19:37" ["post_date_gmt"]=> string(19) "2011-07-01 05:19:37" ["post_content"]=> string(16740) "It's been a while since we posted anything particularly technical to the Web Directions blog, but that's something we plan on changing. Here's the first in a series of technical articles on CSS3 features (along with tools to help you lean and use them).We're starting with linear gradients. We'll take a look at where they come from, how to use them, and the current level of browser support. Ironically although webkit introduced gradients, until version 5.1, Safari has supported a different syntax from that described here - so, if you are using a version of Safari other than 5.1 (currently in beta) you won't be able to see the examples.

A little history

webkit first introduced the proposed gradient feature of CSS3 way back in 2008, enabling the browser to generate a gradient to be used where images are in CSS - most commonly as a background image, but also potentially for list items images, border-images, and generated content. Firefox 3.6 followed suit, but introduced a couple of challenges. It introduced a different syntax (now adopted as the proposed CSS3 gradient syntax), and gradients were only available as background images (this restriction is still true today). Not surprisingly, the webkit based Chrome supports gradients, as does Opera since version 11.1 (though only linear gradients (more in a second) are currently supported). What of Internet Explorer you ask? Well, version 10 in fact supports gradients!

Don't be too alarmed by the two different syntaxes - webkit now supports the same syntax as other browsers, as of Safari 5.1 (we'll also look at how to ensure maximum browser compatibility in a moment as well).

How they work

Enough history, let's play with them. There are in fact, as mentioned above, two kinds of gradients (linear and radial gradients). In this article, we'll focus on linear gradients - and return to radial gradients in an upcoming article.

Gradients aren't properties (like color), but are a computed values of CSS, something you might not be too familiar with. We use them where we'd typically use a url pointing to an image (most commonly background-image). In essence, the browser generates an image and uses that.

Here's one in action

OK, so I've cheated a little and added a bit more style, but that subtle gradient is all done with CSS. Try increasing the text size - and see how the background gradient continues to fill the element.

Here's what the CSS looks like.

background-image: linear-gradient(top, #eff6fb, #d3e4f3 68%);

(I said don't panic for a reason - if you are interested in the underlying concepts, read on. But if you are a more hands-on kind of learner, simply head to the gradient tool I've built, and start playing.)

The linear-gradient starts at the top of the element (we'll see shortly there are other places it can start) and runs vertically to the bottom of the element. At the top, the initial color is #eff6fb. At 68% down the element, the color is #d3e4f3, and the browser generates a gradient image that smoothly transitions from #eff6fb to #d3e4f3. From 68% down the element, to its bottom, the color is a solid #d3e4f3.

gradient in action

BTW, "#d3e4f3 68%" is called a color stop - and gradients can potentially have many stops.

Before we go on, let's recap. A gradient is value, starting with the keyword linear-gradient, and then containing a number of values inside parentheses. These values specify the direction of the gradient (in this case from top to bottom), a starting color, and then one or more color stops. A color stop is a color value, with an optional length or percentage value (for example, we can have a stop at 1em, 20px and so on).

Here, for example is a gradient with numerous stops

background-image: linear-gradient( left, #FF0000, #FFA500 13.0%,#FFFF00 26.0%,#0000FF 39.0%,#008000 52.0%,#4B0082 65.0%,#EE82EE 78.0%)

The gradient direction

We specify the direction of the gradient in one of two ways. We can specify where it starts horizontally with the keywords left and right, and vertically with the keywords top and bottom. Let's look at each of these (just follow the link to see each)

We can also combine keywords - to create diagonal gradients from the top left, bottom left, top right and bottom right:

But gradients would be pretty dull if they could only be horizontal, vertical, or diagonal, so there's a second way to specify the gradient direction-degrees. (You use keywords or degrees, not both together).

To specify a gradient angle, we use the format 90deg (0deg has the gradient start at the left, 90deg at the bottom, 180deg at the right, and 270deg at the top. So, we can think of degrees as going counter-clockwise from 9 o'clock (0deg).)

As usual, the simplest way to understand this is to play with it - so head over to the gradient tool I've built expressly for this purpose, and vary the angle to see what happens.

background-image: linear-gradient(126deg, #FF0000, #FFA500 13.0%,#FFFF00 26.0%,#0000FF 39.0%,#008000 52.0%,#4B0082 65.0%,#EE82EE 78.0%)

Repeating gradients

Is your head full of complex stuff yet - color stops, gradient angles, and so on? Well, let's add to that, with repeating gradients. That's right, you can repeat a gradient. Here's how that works. If your last color stop is before the "end" of the element (so, for example if the gradient goes from left to right, the last stop is less than 100% of the width of the element), then the gradient will be repeated from the location of the last color stop. If we have a simple gradient like this

background-image: linear-gradient(0deg, #FF0000, #FFA500 50%)

then we change the value name from linear-gradient to repeating-linear-gradient, then we'll have the gradient repeat itself from 50% to 100% of the width of the element, like so

background-image: repeating-linear-gradient(0deg, #FF0000, #FFA500 50%)

Forget the math, here's a tool

As I mentioned above, there's no need to remember all the syntax and concepts - as I've developed the linear gradient tool to make life easier for you. (In fact I significantly overhauled the version I developed something like 2 years ago, to provide widespread browser support, and support the new syntax more fully.)

There are some other good gradient tools out there as well, including ColorZilla. I've designed this (and my other CSS3 tools) to closely follow the concepts of CSS gradients, to be as much a tool for learning, as for producing fine looking gradients.

It also has some additional features you might like.

  • You can tweet a link to a gradient you've created by simply clicking a button
  • You can copy the url of your gradient, and send it to someone via email, put it in a link (like I've done for many of these examples) or otherwise share it
  • Via the magic of HTML5 localStorage, it remembers your most recent gradient, and other settings next time you visit
  • It adds vendor prefixes for all modern browsers as an option
  • It adds the start color as a background color for older browsers
  • There's a related tool for creating old style Safari gradients
  • It provides up to the minute browser compatibility information
  • It looks really pretty, all thanks to CSS gradients of course

So give it a go, and tell me what you think.

Backwards compatibility

Now, you might be asking yourself, what about the backwards compatibility issues with older browsers and are there any accessibility challenges in using gradients? Luckily, gradients are really straightforward to use in an accessible, backwards compatible way, across multiple browsers provided you keep a couple of things in mind.

Firstly, ensure you have a background color (or image) for the element to ensure color contrast with the text. Where gradients aren't supported, the browser will ignore them, and use the color or image.

At present, all browsers require vendor specific extensions for gradient values. The gradient tool will create those for you. Make sure that you include a gradient value with no vendor extensions, and make this the last of the properties you specify (as we know, if CSS, the last property trumps earlier ones in the rule). So for example

background-color:#AB1364;
background-image: -moz-linear-gradient(114deg, #AB1364, #52FF26 11%);
background-image: -webkit-linear-gradient(114deg, #AB1364, #52FF26 11%);
background-image: -o-linear-gradient(114deg, #AB1364, #52FF26 11%);
background-image: -ms-linear-gradient(114deg, #AB1364, #52FF26 11%);
background-image: linear-gradient(114deg, #AB1364, #52FF26 11%)

For older versions of Safari, we'll need to have a different background-image property. Not only is the syntax different, the concepts are too, so you might like to use my old style CSS3 Linear Gradient generator to help you out.

And, wth the exception of webkit, gradients are only applicable to backgrounds, (webkit browsers support gradients anywhere images are used.)

Browser Support Notes

A quick summary of current browser support for CSS Linear Gradients.

  • Safari 4 introduced linear gradients, though as noted with a different syntax from that detailed here. The vendor prefix -webkit- is required for gradients (e.g. -webkit-linear-gradient)
  • Safari 5.1 introduces the syntax detailed here, as well as continuing to support the older style syntax. Again, the -webkit-vendor prefix is required.
  • Firefox 3.6 was the first browser to support the current gradient syntax. The -moz- prefix is required, and it's currently only supported on backgrounds.
  • Chrome 10 and up (and probably earlier versions) supported the syntax for gradients detailed here. The -webkit- prefix is required.
  • Opera 11.1 introduced linear gradients, once again with the vendor prefix, -o- required. Currently gradients are only supported on backgrounds.
  • Internet Explorer 10 also features CSS gradients, using the prefix -ms-, and also only supported on backgrounds.

And just to make life easy, there is talk at the W3C CSS Working Group of changing the syntax yet again.

More links, examples, and so on

To do on the Generator

  • At present, the generator only supports hex color values. Enabling rgba and color keywords (particularly transparent) are important next steps.
  • Support for multiple background gradients on a single element, used extensively at the CSS Gradient Gallery
  • Automatic generation of older webkit style syntax.
  • Taking requests - let me know what you'd like to see
" ["post_title"]=> string(21) "CSS3 Linear Gradients" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(21) "css3-linear-gradients" ["to_ping"]=> string(0) "" ["pinged"]=> string(75) " http://www.webdirections.org/resources/lea-verou-mastering-css3-gradients/" ["post_modified"]=> string(19) "2011-08-07 14:38:53" ["post_modified_gmt"]=> string(19) "2011-08-07 04:38:53" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3467" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(2) "12" ["filter"]=> string(3) "raw" } [6]=> object(stdClass)#122 (25) { ["ID"]=> int(3400) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-06-11 08:38:36" ["post_date_gmt"]=> string(19) "2011-06-10 22:38:36" ["post_content"]=> string(685) "I'd not heard of Jack Draws anything, a wonderful initiative by the 6 year old Jack Henderson who will draw whatever you want, for a donation that goes to the Sick Kids Foundation. So far he's raised £20,000!Bruce Lawson, one of the great presenters at @media asked Jack to draw a picture of big bad DRM, to be used as part of his presentation on HTML video and audio.Jack was thrilled to see the picture on the big screen.If you'd like to donate to the cause, you can do so here." ["post_title"]=> string(29) "Jack Draws anything at @media" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(28) "jack-draws-anything-at-media" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-06-11 08:38:36" ["post_modified_gmt"]=> string(19) "2011-06-10 22:38:36" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3400" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "1" ["filter"]=> string(3) "raw" } [7]=> object(stdClass)#123 (25) { ["ID"]=> int(3292) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-05-23 19:57:00" ["post_date_gmt"]=> string(19) "2011-05-23 09:57:00" ["post_content"]=> string(3169) "
What:
Random Hacks of Kindness
Where:
Swinburne University of Technology, Advanced Technologies Centre
When:
Sat June 4 and Sun June 5 2011
Who:
Designers, developers, IxD and UX experts, students and professionals
How Much:
Free! But please RSVP
You've got the skills, and they pay the bills. But, wouldn't it be great to put those skills to work on the side to solve some of the really big problems?Enter Random Hacks of Kindness in Melbourne, which Web Directions is helping run.A worldwide event, happening simultaneously in 20 plus cities around the world, and supported by the World Bank and a number of the biggest names in Tech, RHoK brings together experts in design and development, and volunteers with a broad set of skills in software development and design. The goal is to produce practical open source solutions to development problems. RHoK events give the community an opportunity to sprint on projects, but the community continues to collaborate around the year.The next RHoK event (and first one with major Australian participation) is coming up in Melbourne, June 3 and 4, and had a focus on responding to disaster risk, major crisis (like bush fires, floods and earthquakes), and the challenges of climate change.If the thought of working on challenging, worthwhile projects, with amazing people in a fantastic environment (and the prospect of great prizes too) sounds like something you'd like to do, then sign up now.And make plans to be in Melbourne on the weekend on June 4 and 5.If you've been to a hack event before, you'll know what it's all about, and if it's your first time, don't worry, we'll take great care of you - all you need to do is show up with your skills, and enthusiasm, ready to make the world a little better place.So, whether you are a graphic or web designer, web mobile or software developer, UX, IA or IxD expert or project manager (cat herders are always very useful at these events), you'll be in great demand.Now, as this is the first RHoK event in Australia, we've got a couple of big goals. Let's show the world what the Aussie developer community can do, by1. having the biggest turnout of the 20 locations around the world 2. having the highest percentage of women involved (at best, events have 20% women participating, we can really hit that one for six) 3. let's produce the the best outcomes on the dayDon't be shy, or regret not participating in a truly inspiring event, come hack for good at RHoK. " ["post_title"]=> string(69) "Make the world a little better place at RHoK, Melbourne, June 4 and 5" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(67) "make-the-world-a-little-better-place-at-rhok-melbourne-june-4-and-5" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-05-23 19:57:00" ["post_modified_gmt"]=> string(19) "2011-05-23 09:57:00" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3292" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" } [8]=> object(stdClass)#124 (25) { ["ID"]=> int(3232) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-05-14 02:25:17" ["post_date_gmt"]=> string(19) "2011-05-13 16:25:17" ["post_content"]=> string(339) "Toda's closing keynote session by Jason Grigsby will be streamed live, courtesy of our excellent friends at pinch/zoom.So pop by at 4pm Pacific Time (midnight GMT, 9am Australian east coast, 8am Tokyo) for what will be a fantastic session." ["post_title"]=> string(40) "Unplugged closing keynote streaming live" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(40) "unplugged-closing-keynote-streaming-live" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-05-14 02:25:17" ["post_modified_gmt"]=> string(19) "2011-05-13 16:25:17" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3232" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" } [9]=> object(stdClass)#125 (25) { ["ID"]=> int(3229) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-05-06 10:03:50" ["post_date_gmt"]=> string(19) "2011-05-06 00:03:50" ["post_content"]=> string(1028) "If you've missed the twitter and other announcements, tomorrow, Web Directions is running an event with the NSW State Library, Mashup the Mitchell, as part of the month-long LibraryHack event run by the state libraries, plus Australian and NZ National Libraries.Now, in this always on world, Libraries don't always have the most up to date reputation - but forget dusty books, libraries are enormous collections of vital, fascinating images, maps, diaries, official records and much more.Whether you're a designer, developer, student, or old hand, come along for a day of creativity. It's free, and we'll make sure you're well fed and watered, and there's even a swag of prizes to be won.So, come create a digital media mashup, or app using some truly wonderful amazing resources available from the State and other libraries around Australia and NZ tomorrow at Mashup the Mitchell." ["post_title"]=> string(48) "Come Hack the NSW State Library with us tomorrow" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(48) "come-hack-the-nsw-state-library-with-us-tomorrow" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-05-06 10:03:50" ["post_modified_gmt"]=> string(19) "2011-05-06 00:03:50" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3229" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" } [10]=> object(stdClass)#126 (25) { ["ID"]=> int(3226) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-05-05 16:44:32" ["post_date_gmt"]=> string(19) "2011-05-05 06:44:32" ["post_content"]=> string(2709) "We've just published the first "State of (Mobile) Web Development" Report, analysing the results of our recent survey of over 1,300 developers. In previous years, we've published a single report covering the entire survey, but this year, with the rise in interest in HTML5 and mobile development, we're also publishing this more focussed report. We'll be following it up with the complete report in the coming weeks.Download the PDF

Some Key Findings

  • 2010 saw an explosion of interest and activity by developers in HTML5, and developing native apps for mobile platforms like iOS and Android using web technologies.
  • Android gains dramatically on iPhone as developers' regular mobile browsing platform
  • There is a correlation between the devices and platforms developers use, and those they develop for.
  • Web site testing across a wide range of mobile devices jumps significantly.
  • JQuery Mobile leads from JQTouch and SenchaTouch in a still immature mobile frameworks market place.
  • Three quarters of respondents expressed an interest in developing native apps using web technologies in the coming year, with 30% likely to do so.
  • iPhone, iPad, along with Android phones and tablets all show strong interest from developers, while other platforms have their work cut out to woo web developers.
  • Web developers express confidence in developing native apps using HTML5, with reservations about application performance and user experience.

Jump straight to the results, or background on the survey and audience.

The survey was conducted by Web Directions, and supported in part by WAC, Sencha and Microsoft.

Contents: Report Introduction Browsers HTML5 Native Apps Platform Choice The Wrap

" ["post_title"]=> string(40) "State of (Mobile) Web Development Report" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(38) "state-of-mobile-web-development-report" ["to_ping"]=> string(0) "" ["pinged"]=> string(173) "http://www.webdirections.org/sotmw2011/browsers-and-platforms/ http://www.webdirections.org/sotmw2011/browsers-and-platforms/ http://www.webdirections.org/sotmw2011/the-wrap" ["post_modified"]=> string(19) "2011-05-05 16:44:32" ["post_modified_gmt"]=> string(19) "2011-05-05 06:44:32" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3226" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "7" ["filter"]=> string(3) "raw" } [11]=> object(stdClass)#127 (25) { ["ID"]=> int(3149) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-03-10 12:16:23" ["post_date_gmt"]=> string(19) "2011-03-10 02:16:23" ["post_content"]=> string(1250) "We've just launched our third State of Web Development Survey, where we ask web practitioners, designers and developers, what technologies and practices they currently use. This year, the survey has undergone quite an overhaul, with an additonal focus on HTML5 and application development, alongside our focus on web page and site design and development.If you have a few minutes spare to participate, we'd love to hear your thoughts, and we also have some great prizes, including Samsung Galaxy S smartphones, and tickets to Web Directions conferences to give away, and there's also a very nice discount to our upcoming Unplugged HTML5 focussed conference in Seattle for anyone who participates!Thanks in advance for your participation, and like previous surveys, all (anonymized) results will be published in full, and we'll also provide our own analysis, and comparison with previous years. So over lunch, a cup of tea or coffee or indeed a beer or glass of wine, sit back, and let us know about the State of Web Development in 2011. " ["post_title"]=> string(43) "3rd Annual State of Web Development Survey " ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(42) "3rd-annual-state-of-web-development-survey" ["to_ping"]=> string(0) "" ["pinged"]=> string(37) " http://www.webdirections.org/sotw10/" ["post_modified"]=> string(19) "2011-03-10 12:16:23" ["post_modified_gmt"]=> string(19) "2011-03-10 02:16:23" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3149" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" } [12]=> object(stdClass)#128 (25) { ["ID"]=> int(3144) ["post_author"]=> string(1) "2" ["post_date"]=> string(19) "2011-03-08 08:18:13" ["post_date_gmt"]=> string(19) "2011-03-07 22:18:13" ["post_content"]=> string(263) "We did a quick survey of Web Directions conference attendees reactions, observations, opinions, rants and praises on the latest tech tools: HTML 5 and iPad … so is it Hot or Not? Check out how your peers rate them! http://www.youtube.com/watch?v=WRMJbUSF3N8 " ["post_title"]=> string(26) "iPads? HTML5? Hot, or not?" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(22) "ipads-html5-hot-or-not" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-03-08 08:18:13" ["post_modified_gmt"]=> string(19) "2011-03-07 22:18:13" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3144" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" } [13]=> object(stdClass)#129 (25) { ["ID"]=> int(3138) ["post_author"]=> string(1) "2" ["post_date"]=> string(19) "2011-02-23 11:08:45" ["post_date_gmt"]=> string(19) "2011-02-23 01:08:45" ["post_content"]=> string(1555) "Following on from last week's James Bridle interview, this week we continue the books theme as Danielle interviews Craig Mod. Craig is a writer, designer, publisher and developer concerned with the future of publishing & story­telling. He is co-author, designer and publisher of Art Space Tokyo, and is currently living in San Francisco, working for Flipboard.Title: E-Books and PublishingBy: Craig ModFavourite Quote: Digital is blurring of the notion of the artifact Table of contents:
  • translating analog into e-publishing
  • Wikipedia, books and analytics
  • Books, kindle and iPad
Appendix: Listen to Craig’s talk from Web Directions South 2010, How Digital Affects Books and Publishing.http://www.youtube.com/watch?v=thctFihkRbU" ["post_title"]=> string(45) "Craig Mod interviewed at Web Directions South" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(45) "craig-mod-interviewed-at-web-directions-south" ["to_ping"]=> string(0) "" ["pinged"]=> string(84) " http://www.webdirections.org/blog/james-bridle-web-directions-south-2010-interview/" ["post_modified"]=> string(19) "2011-02-23 11:08:45" ["post_modified_gmt"]=> string(19) "2011-02-23 01:08:45" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3138" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "0" ["filter"]=> string(3) "raw" } [14]=> object(stdClass)#130 (25) { ["ID"]=> int(3127) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-02-22 14:19:50" ["post_date_gmt"]=> string(19) "2011-02-22 04:19:50" ["post_content"]=> string(4623) "On Saturday, we had the privilege of running apps4nsw, for the DSTA, the NSW Department of Services, Technology and Administration, at the Powerhouse Museum. Over 150 developers, designers and others turned up from 8am for 12 hours of brainstorming, app building, presentations, and prizes. More than 40 projects were entered for judging in 5 categories, all using NSW Government data, but running on all kinds of devices, from Android to iOS, and of course a great many web apps. It was a great day all round - check out JJ Halans' photoset on Flickr. apps4nsw in full swingReal time bus location data proved a very popular source, with a dozen or so apps built using the RTA's PTIPS data.Also very popular was a brand new data set - only released the afternoon before - featuring information on all the pets in NSW. So popular was this data, we decided to create a special prize category just for it!Overall winner of the day, and winner of the Transport Category was Next Bus, which like a number of the transport apps, helps you find the nearest busses to you in real time. You'll never have to look at a time table again!Congratulations to all the winners and prize getters, and a huge thanks to the various NSW government departments making their data available - and here's to much more of it in the future.

Energy/Environment Category

Winner

  • Cats and Dogs
  • Simon Wright, Tai Elliott
  • Used NSW Stormtracker data
  • Tells you if you need an umbrella if you are going outside (a great, fun experience)

2nd Place

  • Shape of my Burb
  • Andrea Lau and Jack Zhao
  • Used the BASIX dataset - Building Sustainability Index Data

3rd Place

General Category

Winner

  • Suburb Search
  • Sam Gentle
  • ABS data

2nd Place

  • Hot and Healthy
  • Raul Caceres
  • Used: NSW Health Survey program
  • Uses the data to present a visualisaiton of how healthy your local area is, feeds in information to help you find local gyms and parks etc.

3rd Place

  • Data Loco
  • Eric Bae and Xiangwei Meng
  • An app that makes it easy for anyone with any data that has location info in it to upload this data and then visualise it on Googlemaps.

Companion Animals Category

Winners

  • Petrified
  • Alfred Lo, Steven Ringo, James Martin, Ralph Lengler, Valery Yuschenko, William Parry
  • NSW Companion Animals Register
  • Overly of pet data on Google maps so you can quickly see how popular names and dog types are.

2nd Place

  • Doggie Wars
  • Tim Lucas, Lisa Miller, Brett Goulder, Carl Woodward
  • API for the data - a clean reusable interface for the data for all developers to use. Doggie Wars is a fun way of looking at numbers of each breed across the state.

3rd Place

  • Dog Guide
  • John McCann, Luke Du, Peter Pham, AJ Dyka
  • Data visualisation so people can see dog names are most popular by breed.

Spatial Category

Winners

  • Topolive
  • Matt Mcclelland
  • Renders a NSW topographical map on Google Earth, Generate Tographical maps for offline use on the iphone

Equal 2nd Place

  • Spot It
  • Corey Rosevear
  • Display information for a specific location - layering data over LPMA maps.

Equal 2nd Place

  • Fancy PDF

Transport Category

Winners
  • Next Bus
  • Chris Broadfoot, Luke Mahe
  • Find out what buses are coming to a stop near you.

2nd place

  • Tripmate
  • Dan Aschwanden
  • Smartphone app - Live data for buses displayed graphically on a map

3rd Place

  • What bus?
  • Graham Weldon
" ["post_title"]=> string(16) "apps4nsw Wrap up" ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(16) "apps4nsw-wrap-up" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-02-22 15:08:28" ["post_modified_gmt"]=> string(19) "2011-02-22 05:08:28" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3127" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "5" ["filter"]=> string(3) "raw" } } ["post"]=> object(stdClass)#116 (25) { ["ID"]=> int(3631) ["post_author"]=> string(1) "3" ["post_date"]=> string(19) "2011-08-22 10:52:32" ["post_date_gmt"]=> string(19) "2011-08-22 00:52:32" ["post_content"]=> string(1749) "

McFarlane Prize 2007

In 2006, Maxine and I started a prize for excellence in Australian Web design in honour of Nigel McFarlane, Australian web and open source pioneer.Unlike many awards, it's not about popularity, it's about excellence - as assessed by a Jury of genuine experts in the fields of design, coding, accessibility and user experience. It's all about recognising best practice, and sites that go that little bit more.We've just launched this year's prize nomination period. You've got month to nominate a site you've worked on, or a site you think is worthy of the prize.The criteria for entry are straightforward
  • it must be a site developed by an Australian individual or team
  • it must have launched or been significantly upgraded between September 22nd 2010 and September 23 2011 (you have another month to finish your site or upgrade!)
And, there's no cost to enter.The shortlist of 6 finalists will be announced early October, and the overall winner, as has become tradition, at Web Directions South, on October 13th, with all shortlisted finalists receiving recognition for their achievement, as our guests at the closing keynote session day 1. Help show the strength of the Australian Web Industry and enter your work. You can enter as many sites as you like!" ["post_title"]=> string(65) "The 2011 McFarlane Prize for Excellence in Australian Web Design " ["post_category"]=> string(1) "0" ["post_excerpt"]=> string(0) "" ["post_status"]=> string(7) "publish" ["comment_status"]=> string(4) "open" ["ping_status"]=> string(4) "open" ["post_password"]=> string(0) "" ["post_name"]=> string(64) "the-2011-mcfarlane-prize-for-excellence-in-australian-web-design" ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" ["post_modified"]=> string(19) "2011-08-22 10:52:32" ["post_modified_gmt"]=> string(19) "2011-08-22 00:52:32" ["post_content_filtered"]=> string(0) "" ["post_parent"]=> int(0) ["guid"]=> string(36) "http://www.webdirections.org/?p=3631" ["menu_order"]=> int(0) ["post_type"]=> string(4) "post" ["post_mime_type"]=> string(0) "" ["comment_count"]=> string(1) "1" ["filter"]=> string(3) "raw" } ["queried_object"]=> object(stdClass)#113 (16) { ["term_id"]=> &string(1) "1" ["name"]=> &string(4) "Blog" ["slug"]=> &string(4) "blog" ["term_group"]=> string(1) "0" ["term_order"]=> string(1) "0" ["term_taxonomy_id"]=> string(1) "1" ["taxonomy"]=> string(8) "category" ["description"]=> &string(0) "" ["parent"]=> &string(1) "0" ["count"]=> &string(3) "543" ["cat_ID"]=> &string(1) "1" ["category_count"]=> &string(3) "543" ["category_description"]=> &string(0) "" ["cat_name"]=> &string(4) "Blog" ["category_nicename"]=> &string(4) "blog" ["category_parent"]=> &string(1) "0" } ["queried_object_id"]=> int(1) }

Blog

The 2011 McFarlane Prize for Excellence in Australian Web Design

McFarlane Prize 2007

In 2006, Maxine and I started a prize for excellence in Australian Web design in honour of Nigel McFarlane, Australian web and open source pioneer.

Unlike many awards, it’s not about popularity, it’s about excellence — as assessed by … Read more »

Let the Web move you — CSS3 Animations and Transitions

A brief history on Animation of the Web

If you’ve been developing for, or even just using the web for more than about 15 years, you’ll likely remember a time when animated effects were the bomb. Animated GIFs adorned just about every page, spinning globes, little men with jack hammers, self-​​folding … Read more »

Getting Sourcey — native HTML5 Audio and video

Hard perhaps to believe, but the world wide web began without an image element. That’s right, there was no way to include images as part of the content of a web page before Mosaic implemented them (here’s Marc Andreesen proposing the img element at the beginning of 1993). The … Read more »

CSS3 Radial Gradients

Getting your head around CSS3 radial gradients

We recently took a detailed look at linear gradients in CSS3. If you’ve not read that, you might like to spend a few minutes doing so, as the concepts are very similar, and I don’t spend quite as much time in this article … Read more »

Get off(line)

Taking your web sites and apps offline with the HTML5 appcache

There’s a general (and understandable) belief by even many developers that web sites and web applications can only be used when the browser has a web connection. Indeed, this is routinely cited as one of the real advantages of “native” … Read more »

CSS3 Linear Gradients

It’s been a while since we posted anything particularly technical to the Web Directions blog, but that’s something we plan on changing. Here’s the first in a series of technical articles on CSS3 features (along with tools to help you lean and use them).

We’re starting with linear gradients. We’ll take … Read more »

Jack Draws anything at @media

I’d not heard of Jack Draws anything, a wonderful initiative by the 6 year old Jack Henderson who will draw whatever you want, for a donation that goes to the Sick Kids Foundation. So far he’s raised £20,000!

Bruce Lawson, one of the great presenters at @media asked Jack to … Read more »

Make the world a little better place at RHoK, Melbourne, June 4 and 5

What:
Random Hacks of Kindness
Where:
Swinburne University of Technology, Advanced Technologies Centre
When:
Sat June 4 and Sun June 5 2011
Who:
Designers, developers, IxD and UX experts, students and professionals
How Much:
Free! But please RSVP

You’ve got the skills, and they pay the bills. But, wouldn’t it be great to … Read more »

Unplugged closing keynote streaming live

Toda’s closing keynote session by Jason Grigsby will be streamed live, courtesy of our excellent friends at pinch/​zoom.

So pop by at 4pm Pacific Time (midnight GMT, 9am Australian east coast, 8am Tokyo) for what will be a fantastic session.

Come Hack the NSW State Library with us tomorrow

If you’ve missed the twitter and other announcements, tomorrow, Web Directions is running an event with the NSW State Library, Mashup the Mitchell, as part of the month-​​long LibraryHack event run by the state libraries, plus Australian and NZ National Libraries.

Now, in this always on world, Libraries don’t … Read more »

State of (Mobile) Web Development Report

We’ve just published the first “State of (Mobile) Web Development” Report, analysing the results of our recent survey of over 1,300 developers.
In previous years, we’ve published a single report covering the entire survey, but this year, with the rise in interest in HTML5 and mobile development, we’re also publishing … Read more »

3rd Annual State of Web Development Survey

We’ve just launched our third State of Web Development Survey, where we ask web practitioners, designers and developers, what technologies and practices they currently use.
This year, the survey has undergone quite an overhaul, with an additonal focus on HTML5 and application development, alongside our focus on web page … Read more »

iPads? HTML5? Hot, or not?

We did a quick survey of Web Directions conference attendees reactions, observations, opinions, rants and praises on the latest tech tools: HTML 5 and iPad … so is it Hot or Not? Check out how your peers rate them!

Craig Mod interviewed at Web Directions South

Following on from last week’s James Bridle interview, this week we continue the books theme as Danielle interviews Craig Mod. Craig is a writer, designer, publisher and … Read more »

apps4nsw Wrap up

On Saturday, we had the privilege of running apps4nsw, for the DSTA, the NSW Department of Services, Technology and Administration, at the Powerhouse Museum. Over 150 developers, designers and others turned up from 8am for 12 hours of brainstorming, app building, presentations, and prizes. More than 40 projects were entered … Read more »