Sunday, June 12, 2011

The art of progressive enhancement

For some developer javascript is just a toy for adding fancy effects to a web page. This approach brings to poor developing practices. Inline javascript is one of those. But I don't want to point out on this now.


In the last few years the javascript community develop some simple design principle that It's better to keep in mind.

Separation of concerns
One of the most important design principle is separate the semantic (html), style (css) and behaviour.
The consequencies of this statement are to keep our html free of logic and style and enforce the semantic inside the html.


and consequences
Another important principle is called "progressive enhancement" and is a direct consequences of the previous. This could be translated in "keep the basic functionality in html and use Javascript to add usability".
The main reason to follow this principle is to keep untouched the semantic of the document.
This is better both for accessibility and search engine optimization.


An example of a right use of progressive enhancement is fancybox. This jquery plugin implements a lightbox effect when a user clicks on an image.


You can link an external image like this one:


<a id="single_image" href="image_big.jpg"><img src="image_small.jpg" alt=""/></a>

or you can use an internal link:


<a id="single_image" href="#image_big"><img src="image_small.jpg" alt=""/></a>
...
<div id="image_big"><img src="image_big.jpg" /></div>

The semantic is clear and simple and the page works even without javascript (without the effect obioviously).


The next example shows the wrong approach.

This is jquerytools overlay markup (taken from an example on the jquerytools website)


<img src="thumbs/barcelona-pavilion.jpg" rel="#mies1"/>

<div class="simple_overlay" id="mies1">

 <!-- large image -->
 <img src="photos/barcelona-pavilion-large.jpg" />

 <!-- image details -->
 <div class="details">
  <h3>The Barcelona Pavilion</h3>

  <h4>Barcelona, Spain</h4>

  <p>The content ...</p>
 </div>

</div>

In this example the img element is connected to a div through a rel attribute (rel="#mies1"). But the image tag purpose is not to link a resource. And this is not what the rel attributes is intended for.
The rel attribute (http://www.w3.org/TR/html4/struct/links.html) is used to specify the relations between two resources and not the resource itself.
This markup semantically doesn't make sense and without Javascript is even useless.


Progressive enhancement tricks

As a matter of fact the browser renders the page while is loading the DOM tree. The scripts see the DOM node right after the loading.
When you use javascript to enhance a web page you often add markup and inline styles to elements.
Thus, following this approach, you could see the page while changing.

For example in the previous examples you can see the overlay content before the javascript manage to hide it.


You can avoid this hiding the overlay container in the css (using display:none).


For other effect you can hide like the previous example and then shows only after adding the style and markup (for example with .show() method of jquery).
Another nice effect is to remove the element opacity in the styleshhet and, at the end of the script, animate the opacity with a fade-in effect.


This approaches have a drawback: if someone is not using javascript (and search engines) the area will be empty. This issues can be easily fixed adding a css rule in a noscript tag (display: block !important).