Accessites.org

Graceful Degradation & Progressive Enhancement

Posted February 6th, 2007 by Tommy Olsson

Graceful degradation and progressive enhancement are two sides of the same coin. Both are — in this context — applied to make a web site accessible to any user agent, while providing improved aesthetics and/or usability for more capable browsers. The difference between the two is where you begin your approach.

Some time ago I wrote an article here about two very different approaches to : Visual Vs. Structural. The concepts of graceful degradation and progressive enhancement relate closely to those two approaches.

Graceful Degradation

Graceful degradation is the older of the two concepts. The term is also used in fields other than web design, such as fault tolerant mechanical or electrical systems.

The premise for graceful degradation is to first build for the latest and greatest, then add handlers for less capable devices. In other words, focus on the majority before catering to those outside the mainstream. This is quite similar to the visual approach of web design, where the first priority is to make it look good to most visitors.

A familiar example of graceful degradation is the alt attribute for images. When used properly it provides a text equivalent that conveys the same information as the image to users who cannot perceive the image itself. The text equivalent is most likely not as aesthetically pleasing, and an image can say more than a thousand words, so the user experience is slightly degraded.

Using layout tables may be seen as one form of graceful degradation: if the CSS styling cannot be applied — e.g., in really old browsers — at least the basic page layout is retained. But it doesn’t work very well for text browsers like Lynx and some mobile phone browsers, which do not support tables.

Another common occurrence in sites built from the graceful degradation point of view is the noscript element. You provide some feature based on JavaScript and add a more basic version for user agents that do not support JavaScript or have client-side scripting disabled. One example could be the ubiquitous drop-down or fly-out menu:

Example One

The JavaScript function may create a menu where “Products” and “Services” have sub-menus that drop down, fly out or expand when the user’s mouse pointer hovers over the main items. The non-JavaScript alternative provides immediate access only to the main items, while the sub-menus are (presumably) included in similar noscript elements on the respective interior pages.

This approach is designed for mainstream users — those with a graphical browser that supports JavaScript — but it degrades gracefully so that it works in even the humblest of text browsers. It also adds the benefit of proper HTML anchor links to non-JavaScript user agents like search engine spiders, thus negating the critical SEO disadvantage of JavaScript menus.

There is one problem with noscript, though. I may use a browser that supports JavaScript and has it enabled, but there could be a company firewall that strips incoming JavaScript for security reasons. In this case the noscript element will not be rendered (because my browser supports scripting) but the JavaScript code that should create the menu won’t be applied either, because it gets stuck behind the firewall.

Sorry. Comments are closed.

Copyright © 2005-2011, Accessites.org. Some rights reserved

2 of 2 Accessites.org

Graceful Degradation & Progressive Enhancement

Posted February 6th, 2007 by Tommy Olsson

Not-So-Graceful Degradation

Unfortunately the concept of graceful degradation sometimes deteriorates way past the point where the adjective “graceful” can reasonably be applied. The worst case is code like this:

Example Two

Please upgrade to a browser that supports JavaScript.

This is unacceptable for any serious web site, but may be forgiven on a small amateur site whose target audience is friends and family.

We, as web designers or developers, have no right to tell our visitors which browser they “should” use; nor do we have the right to tell anyone to “enable JavaScript.” We don’t know why this visitor uses Lynx or why that visitor has disabled client-side scripting. They may not even have the option of “upgrading” or “enabling JavaScript” because of bandwidth, hardware or budget constraints; IT department policy; or because they are not even using their own computer.

Graceful degradation is far better than having a site that is completely inaccessible to some users, but it is not the best approach. As with the visual design approach, it is often difficult to begin with all the features and then remove them one by one, without everything falling apart.

Progressive Enhancement

Progressive enhancement became known — at least under that name — in 2003, when Steve Champeon began using it on Webmonkey and during the SXSW conference. It starts at the opposite end from graceful degradation: begin with the basic version, then add enhancements for those who can handle them. Again, comparing it to the design approaches: this is the same basic thought as in structural design. That starts with the markup and adds styling on top of that, which is progressive enhancement all by itself.

The most common occurrence of progressive enhancement is probably the external CSS style sheet. It is ignored by non-CSS browsers — which thus get only the plain markup and render it according to their own built-in style sheets — but it is applied by modern graphical browsers, thus enhancing both the aesthetics and the usability for mainstream and advanced users.

1 of 4 Other examples of progressive enhancement are the various image replacement techniques, the Flash satay method and (sometimes) .

Progressive enhancement when it comes to JavaScript is becoming more common these days. The key to this is known as unobtrusive JavaScript. An unobtrusive script is silently ignored by user agents that do not support it, but is applied by more capable devices. Just like an external style sheet.

Let us revisit the navigation menu we examined as an example of graceful degradation. How would that be done using progressive enhancement?

We would begin by creating our markup, aiming for the lowest common denominator: HTML. A navigation menu is, semantically, a list of links. The order of those links does not affect the meaning of the list as a whole; thus it is an unordered list.

Example Three

This will work in everything from Lynx and Mosaic 1.0 to the latest versions of Opera, Firefox and Safari. Googlebot and its arachnoid cousins will also love it.

The next step is to add enhancements for the vast majority of users whose browsers support CSS. We add rules in an external CSS file to style the menu. After adding a link element with a reference to the external style sheet, it looks a lot better to most visitors, but it is in no way detrimental to those Lynx users or to the Googlebot. (OK, they’ll have to download a few more bytes, but it will be negligible even on a slow dial-up connection or a GSM mobile phone.)

But we can enhance this further by adding drop-down or fly-out or expanding sub-menus to the main items, using unobtrusive JavaScript. To reduce the amount of script code, we begin by assigning ids to the list items:

Example Four

  • Products
  • Services
  • Then we create a separate JavaScript file with a couple of functions:

    Example Five function addProducts() { // Find the li element to which we will add a sub-menu var parent = document.getElementById("products");

    // Make sure it exists (fail silently) if (parent) {

    // Create a nested unordered list var ul = parent.appendChild(document.createElement("UL"));

    // Add the list items and links

    2 of 4 var items = [ ["Blue Widgets", "blue"], ["Red Widgets", "red"] ];

    for (var i = 0; i < items.length; ++i) { var li = ul.appendChild(document.createElement("LI")); var a = li.appendChild(document.createElement("A"));

    a.href = "/products/" + items[i][1]; a.appendChild(document.createTextNode(items[i][0])); } } }

    The addServices() function would look very similar. Then we need to be sure that the browser can handle those DOM functions:

    Example Six function createSubMenus() { // Make sure that the DOM functions we will use are supported // (fail silently) if (typeof document.getElementById != "undefined" && typeof document.createElement != "undefined" && typeof document.createTextNode != "undefined") { addProducts(); addServices(); } }

    This function makes sure that the main DOM functions used by addProducts() and addServices() are supported by the browser. If not, the function does nothing; it causes no harm and there will be no JavaScript error message or warning icon. This approach is called object detection and is infinitely better than the old-school browser sniffing scripts that stopped working as soon as a new browser (or a new version of an existing browser) was released.

    Finally, to get the browser to call those functions as soon as the page has loaded.

    Example Seven if (window.addEventListener) { window.addEventListener("load", createSubMenus, false); } else if (window.attachEvent) { window.attachEvent("onload", createSubMenus); } else { window.onload = createSubMenus; }

    Note that this piece of code is not enclosed in a function. It will add an event listener for the window’s “load” event, calling our menu-creating function immediately after the HTML document has finished loading. (We need to wait for that, so that the id attributes are available.)

    Modern browsers will use the addEventListener() function specified in the DOM Level 2 (Events) specification, while Explorer will use its proprietary attachEvent() function.

    The last catch-all is not perfect: it will replace any existing onload handler created by a previous

    3 of 4 script. That is hardly unobtrusive. In real life we would need a slightly more complicated solution for this case, but I don’t want to make the examples unnecessarily complicated.

    We will add a script element in the HEAD section of our document to load the external JavaScript file:

    As a final step we would add CSS for those sub-menus and JavaScript event listeners to display or hide them, making sure to handle both mouse and keyboard activation, of course.

    Sorry. Comments are closed.

    Copyright © 2005-2011, Accessites.org. Some rights reserved

    4 of 4 Accessites.org

    Graceful Degradation & Progressive Enhancement

    Posted February 6th, 2007 by Tommy Olsson

    Form Validation

    Form validation is a common use for JavaScript, but one can obviously not rely on it. If we did, someone who has disabled client-side scripting could submit invalid data, and a nefarious script could abuse our form for who-knows-what.

    Validating form data is something which must always take place on the server side, but for efficiency reason we may wish to use client-side validation in addition to that. It will benefit users by giving quicker feedback and it will benefit us because it reduces the number of requests to our servers.

    Using the methods outlined above, we can add our JavaScript validation unobtrusively and with object detection. A modern browser with JavaScript enabled will enhance the validation process, while we still retain our back-end validation for the script-challenged minority (and to preserve our own mental health).

    Ajax

    AJAX became an important buzzword last year. Everyone must use it, whether they really needed it or not. Sometimes I get the feeling that it is an answer in search of a problem, but there is no denying that it is a useful technique for some common situations.

    Consider a form with two or more select elements (drop-down lists or list boxes) where each select is dependent on the previous one. Typical examples are drill-down choices for type/subtype or country/state. Depending on what you select in the first list, the content of the second list should change. How can we make this work as well as possible for all users?

    We will once again begin with the basics. Do not think about client-side scripting at this stage; think only about HTML support:

    Example Eight (in HTML)

    Product Type



    Our primary list (Type) is populated with our product types: widgets and gadgets. The secondary list (Subtype) is empty and disabled, and the main submit button (Show Products) is disabled. A user needs to choose a product type and then activate the other submit button (”Select”). The form is submitted to our server-side script (products.php), which will then redisplay the form with the subtype list populated with the subtypes of the selected type (or a friendly error message if no type was specified).

    The user can then select a subtype and submit the form using the “Show Products” button (which is not disabled this time). If she changes her mind and wants to select another type, she will have to activate the “Select” button again to load the correct subtypes.

    This is not the most user friendly form in the world, and it needs some rather tedious (but straightforward) server-side scripting, but it works in virtually all browsers. Even Lynx handles forms like this one.

    But we would like to make it faster and easier to use. It would be nice to populate the secondary list as soon as the selection changes in the primary list. This requires JavaScript. More often than not the choices of types and subtypes are dynamic and need to be retrieved from a database rather than being hard-coded, which makes this a likely candidate for an AJAX solution.

    We would use unobtrusive JavaScript to detect support for the necessary features (mainly XMLHttpRequest). If supported, we would add an event handler for the primary list using addEventListener() or attachEvent(), depending on the user’s browser. Then we would remove the “Select” button using the removeChild() DOM function, because it is no longer necessary and would only be confusing.

    The added event listener would open an asynchronous connection to our server and post an HTTP request specifying the selected type. The server script would query the database and return an XML reply containing the available subtypes, which we would then parse and use to populate the subtype list (with DOM functions). Then we could enable the subtype list and the main submit button.

    A JavaScript-enabled browser that lacks support for AJAX could submit the form automatically to a server-side script that would redisplay the form with a populated secondary list, much like the non-scripted version but without requiring the user to activate an extra button.

    This is progressive enhancement: it works for everyone, but users with modern browsers will see a more usable version. We are, in a way, rewarding them for choosing to use a good browser, without

    2 of 3 being rude to Lynx users or employees of companies with paranoid IT departments. We don’t even have to trust the unreliable noscript element, and since we would use object detection rather than browser sniffing we don’t have to keep updating the JavaScript for every new browser version.

    Sorry. Comments are closed.

    Copyright © 2005-2011, Accessites.org. Some rights reserved

    3 of 3 Accessites.org

    Graceful Degradation & Progressive Enhancement

    Posted February 6th, 2007 by Tommy Olsson

    Choosing a Method

    Both graceful degradation and progressive enhancement obviously assist in making a website accessible, yet providing additional usability for those who can take advantage of it. So which one should we choose?

    Progressive enhancement is usually preferable to graceful degradation, for the same reason that structural design usually leads to better accessibility than visual design: it starts with the simple basics and adds embellishments on top of that. When designing something from scratch, we should definitely think in terms of progressive enhancement.

    If we are maintaining an existing site, trying to improve accessibility and standards conformance, the situation is different. Unless we want to rewrite everything, our only choice is to provide graceful degradation as best we can.

    Of course it is also possible to mix both methods on one site, or even on the same page. Progressive enhancement is what we should strive for, though, if we have a choice.

    Testing

    Testing the accessibility is much easier with progressive enhancement than with graceful degradation.

    If we work from the point of view of progressive enhancement, we can simply create the basic version and verify that it works. Then we add the enhancements and verify that they work. Okay, this is somewhat simplified: when testing the enhancements we may need to verify that they don’t break the basic version.

    If we use graceful degradation (or when we verify that added progressive enhancements don’t cause problems in less capable user agents) we need a different approach. Now the advanced features are already present and can be readily tested. To verify that they really do degrade gracefully, we must disable the support for those features. Sometimes that will require testing in a different browser, but some things — like text equivalents or JavaScript/plug-in support — can be checked using the accessibility features of Opera or with the Web Developer Toolbar in Firefox.

    Besides…

    1 of 2 Accessibility evangelists like myself are sometimes accused of being reactionary zealots, new Luddites who abhor anything that makes the Web more enjoyable and entertaining. Some of those who disagree with us claim that we do not allow JavaScript or Flash to be used on a website.

    I hope this article will prove them wrong once and for all. Anything that improves usability or aesthetics is a good thing. What I (and many others) wish to point out is the danger of relying on non-standard, proprietary or platform-dependent technology. All that should be required for accessing information on the Web is a user agent that supports HTTP and HTML. Such a user agent should be able to access the vital information on any professional site.

    If the user agent supports CSS, JavaScript, Flash, MathML, SVG, embedded video and so on, that is great! Those users will benefit by seeing a better-looking site which is also easier to use. There may even be non-critical content that won’t be accessible to that bare-bones browser, but which the more advanced users can enjoy.

    Graceful degradation, to some extent, but especially progressive enhancement make this dichotomy possible. It is possible to eat your cake and have it, too. It requires a bit more work, sometimes, but it is often worth it.

    (Get this article as plain text.)

    Sorry. Comments are closed.

    Copyright © 2005-2011, Accessites.org. Some rights reserved

    2 of 2