Test-Driven Progressive Enhancement

by Scott Jehl

24 Reader Comments

Back to the Article
  1. I had looked at this technique upon reading about it on javascript guru John Ressig’s blog.
    An interesting and potentially very useful approach to browser sniffing.
    If you have to accomodate a wide variety of user-agents old and new, check it out.
    Thought-provoking at the very least.

    Copy & paste the code below to embed this comment.
  2. This is a very informative and a nice idea for sites that use a lot of JavaScript. I think the testing code would be overkill for smaller sites that aren’t using a great deal of JavaScript. Definitely something I’ll be looking into more though, and I’m a big fan of the progressive enhancements.

    Copy & paste the code below to embed this comment.
  3. Clearly using Javascript to test the browsers capability is clever and useful but what about users who do not have JS enabled? They end up seeing the basic version even though their browser may cope with the boxmodel or any other CSS perfectly well.

    Copy & paste the code below to embed this comment.
  4. @M Bruce: Good question and thanks for commenting. It’s true that enhancements that make use of the test script will not reach JS-disabled users, regardless of how advanced their browser may be. Assuming your site or application is functional in its “basic” mode, you might decide that this is acceptable, but keep in mind that it’s up to you to decide where the experience divisions are made and how extreme they may be. For example, your “basic” version might look quite similar to your enhanced version, aside from some more complicated enhancements that would require a blend of proper CSS and JS support (such as our sliders in demo 3).
    This technique provides a framework for making experience divisions in a clean and separated manner, but how and where you make them is entirely up to your discretion.

    Copy & paste the code below to embed this comment.
  5. This is great.  I’ve always coded with standards and degraded properly, but since recently getting a Sidekick and browsing the web more often while I’m out, graceful degradation has a renewed importance to me.  It sucks when I want to look up some basic information that happens to contained in Flash.

    But related to this article, it definitely sucks when I load a page that renders rather perfectly, but the status bar tells me that its forever loading a script, and eventually I’m prompted that the script should die.

    It’d be useful to make Javascript checks for functions and such before trying to throw them around.

    Copy & paste the code below to embed this comment.
  6. If you use JS to hide something that you would want to show to a client without JS, then you don’t ever run into the issue of it being inaccessible, and at the same time, you don’t have to worry about testing for effects. (ie, you have a cool animation on hover – well, put CSS :hover on like the animation doesn’t exist, and then use JS to override the whole operation.)

    Copy & paste the code below to embed this comment.
  7. The testUserDevice.js code has the following test for getElementById support:

    getById: function(){ return document.getElementById ? true : false; }

    Note that in IE Mobile 5, this will throw a JavaScript exception, because IE Mobile 5 doesn’t support this type of object checking. One example, but testing solely on object support forces you to make a lot of assumptions about the user agent which might not be true.

    Another example: Google Chrome, like all WebKit browsers supports border-raduis, but “you wouldn’t want to use it”:http://www.flickr.com/photos/kurafire/2822606444/ .

    I think Yahoo’s “Graded Browser Support”:http://developer.yahoo.com/yui/articles/gbs/ is a far better idea. It’s just not efficient to do this kind of testing, as your results will still be sub-par.

    Copy & paste the code below to embed this comment.
  8. Lately, I’ve been making extensive use of psuedo classes like :hover and :focus knowing very well that they won’t be supported in all browsers.

    The thing is, knowing that I’m going to do this influences my design, so I make sure that design is clear enough where these sort of CSS filigree don’t break the user experience in the slightest.

    My €.02 also thinks that sniffing for a mobile device on the server side can provide a richer experience with less effort. Mbta.com spits out a rich site when viewed on the desktop, but simple text when viewed on a mobile device. Then they’re only upkeeping a few extra templates specifically designed for mobile, whereas this solution involves juggling javascript, stylesheets, etc.

    Copy & paste the code below to embed this comment.
  9. Something about sniffing for device capabilities seems so ancient from a design standpoint.
    We used to do this for browsers and deemed it as irrelevant and futile.
    Why would we do this for devices when we have alternatives via good, standards based code and CSS media styles?

    Sounds like another solution to a design problem that really doesn’t need to be “fixed”.

    Copy & paste the code below to embed this comment.
  10. I’ve been exploring the web via iPhone.  Here, Example 3 delivers sliders to my iPhone, but the sliders are not functional on the iPhone.

    Copy & paste the code below to embed this comment.
  11. @Ryan Cannon: Thanks for commenting. You brought up some good points and I’m glad you mentioned Yahoo’s Graded Support.  I think an ideal approach could be a combination of capabilities testing AND following a browser support matrix such as Yahoo’s. Correct me if I’m wrong, but to my understanding, Yahoo’s Graded support acts as more of a list of browsers in which a site has been fully QA’d to support, but anything beyond those may or may not receive a usable website, and they fall into groups C or X. It’s more of a support disclaimer than an attempt to provide a usable experience for all. In other words, without some sort of capabilities testing in place, browsers in groups C or X might actually get a completely unusable website instead of a usable one with less bells and whistles.  But even if you are conditionalizing your features with capabilities testing of some sort, you’ll surely still have a set of target browsers to support, and that’s where something like Yahoo could come in. This technique just aims to give users with a C or X grade browser a working experience of some sort.

    As for the IE mobile 5 object detection error, that’s good to know, and something I wasn’t aware of. Of course, you can decide which tests to run based on your needs. Perhaps there’s a way to write those particular tests to make sure Mobile IE 5 is included when it should be. We’ll look into this further.

    Copy & paste the code below to embed this comment.
  12. @Steve: The problem lies in how that “good, standards based code” will function on Grampa’s computer * . You’re in good company saying that sniffing for user agents is generally considered bad form. This approach is different from sniffing in that we’re never asking what browser you’re using, we just care if it works well enough to handle a certain feature.

    @Erika: We tested the demos in iPhone and deemed them usable. Try tapping on each slider scale to move the handles. In a real implementation though, you might decide these would be better left as select menus for iPod users. After all, you aren’t really “sliding” them anyway, and they might even be easier to use that way on iPhone. This would just mean conditionalizing the slider enhancements with a stricter test.

    *sorry, Grampa :)

    Copy & paste the code below to embed this comment.
  13. …sorry for the bold text. Apparently asterisks don’t render out in this system.

    Please place mental asterisks after “Grampa’s computer” and before “sorry, Grampa”… sigh :(

    Copy & paste the code below to embed this comment.
  14. I’ve looked into progressively enhancing forms a little bit of late, the only concern I have is how best to provide an opt-out for those who may be reliant upon screen readers etc where AJAX seems to be a hit and miss affair.  What is a best practice here?  Provide a link that sets a cookie, pages then check if cookie exists and enhance based upon preference?

    Copy & paste the code below to embed this comment.
  15. Progressive enhancement does sound like a good idea to me. Reading through all the comments it seems that there is a mixed response. My thoughts are that anything to ensure the end user/visitor gets a good experience that reflects well on the organisation the site represents is a good thing.

    The use of CSS media types is a good idea – we are already doing this for printing (I hope) so why not use it for mobile devices. However, there are limitations with this in that it is an all or nothing approach to the problem. Is there some way of combining the CSS media type solution with the use of this JS? If we had the stylesheets loaded correctly at the start then the technique in this article could be applied over the top – the default, or fall back, stylesheet would then be correct for the media type.

    I hope that makes sense – I’ve not been up long and my coffee has run out.

    Copy & paste the code below to embed this comment.
  16. Shouldn’t the Progressive enhancement run something like:
    HTML -> CSS -> JavaScript -> (Flash / Ajax / Silverlight / etc)
    Doesn’t this method skip to step three to test step two?

    I’ve always found that CSS media type solves the mobile devices issue and IE’s non-standard conditional comments fix their own shocking CSS support. The ONLY issue I have is Safari which has the odd bug but is impossible to target without hacks. (As far as I know?)

    As long as you test for each object / method you use in you JavaScript before implementing the code, there shouldn’t be any problems there either.

    Everything else is bells and whistles and shouldn’t hamper the user experience.

    Copy & paste the code below to embed this comment.
  17. To my understanding, Yahoo’s Graded support acts as more of a list of browsers in which a site has been fully QA’d to support, but anything beyond those may or may not receive a usable website, and they fall into groups C or X. It’s more of a support disclaimer than an attempt to provide a usable experience for all. In other words, without some sort of capabilities testing in place, browsers in groups C or X might actually get a completely unusable website instead of a usable one with less bells and whistles.

    This isn’t quite right. YGBS limits browsers to three scenarios:

    1. You’re ok, we’ll give you everything and fix the bugs we find.
    2. You’re terrible. You get no CSS/JS, just a sparse but usable Web site, and we’ll make sure you can use it.
    3. We don’t know you, but there’s no way we can cover all the bases. If you act like the standards and precedences say you should, then everything should be ok.

    So there’s much less guesswork than trying to plan for many different types of failure secenarios.

    Perhaps there’s a way to write those particular tests to make sure Mobile IE 5 is included when it should be. We’ll look into this further.

    I didn’t want to pimp my own blog here, but I did some of that work for you in my article “The Mobile Dollar”:http://ryancannon.com/2008/07/10/the-mobile-dollar-dipping-a-toe-in-device-javascript .

    Copy & paste the code below to embed this comment.
  18. @Scott Jehl, Thanks for the navigation hints. :)

    First, a disclaimer: iPhone is the first mobile browser I’ve used, and I’ve only had it a week.  Though IMO that makes me a perfect tester. ;)

    Second, yes! the “sliders” work on iPhone if you click the location you want them to “slide” to.  Indeed, they do not actually slide, but on the desktop browser, it all seems relatively intuitive (to me).  On the iPhone, it is not intuitive (to me).  I guess that certain Javascript events are going to be different on the mouse-less device. In general, I feel more basic, intuitive, or at least, “de facto standard” navigation elements make sense to a mobile device.  And should be delivered with a media-type stylesheet…?

    Also, this article, and the iPhone, is making me think that the concept of “progressive enhancement” is now something of a misnomer, or at least, only part of the issue.

    iPhone Safari (for example) is not a lesser, but a different browser.

    While it is !important that a browser understands the DOM (and iPhone Safari offers some really neat functionality around block-level elements)—once that part is out of the way, there are a whole lot of other important things.  What are the special needs of the user, and how is the device/software delivering content?  And once you know you can do something … should you?

    With the renewed focus on Javascript… I think we should also keep our focus on usability as a very important part of the design/development process, especially when dealing with highly interactive elements, like forms.

    Just some thoughts, tangentally related… 

    Copy & paste the code below to embed this comment.
  19. I meant “tap”—of course!

    Copy & paste the code below to embed this comment.
  20. Isn’t it enough if we know which browsers we are targetting rather than the specific features of the browser that in loading at the user’s end?

    What is the advantage of this over simply getting the browser useragent? Would be great if we had a practical example!

    Copy & paste the code below to embed this comment.
  21. @Erika Meyer: I agree with you. Perhaps the demos should have resulted in a different experience for iPhone users (via media type, sure). I intended the demo page to simply illustrate the idea of test-driven enhancement in a way that seemed somewhat easy to follow. How a site will actually implement their enhancements across devices is left to the developer and the test cases they choose to include. Thanks for your insight, though. As I’d said earlier, one might decide that iPhone users would be better off using select menus, particularly due to the nice native wheel interface that iPhone provides!

    @Divya Manian: It’s a good question. User agent sniffing is a different approach and comes with its disadvantages. For one, the approach is limited to browsers you actively sniff for, and doesn’t attempt to cater to the experience of users on devices that aren’t in your set of agent strings. Feature (or bug) detection is a different approach in that it acts upon capabilities of a browser, regardless of what that browser it is. We’re seeing javascript libraries like jQuery moving towards feature/bug detection rather than user agent sniffing for this very reason. Feature detection is also forward-looking in that it adapts to bug fixes in browsers as they happen. For instance, if you were to fork some code based on a known implementation difference in IE7 using a user agent sniff, and IE7 releases an update with a fix to that bug, the browser will no longer will need that fork. A user agent check would continue to direct IE7 to that forked code, as opposed to feature/bug detection, which would direct it to the code that aligns with its updated implementation.

    Copy & paste the code below to embed this comment.
  22. This is a pretty cool idea brought to fruition! It really brings Javascript and browser detection to a whole new level. I’m surprised this CSS detection technique hasn’t been mentioned as often as it should be.

    Thanks for the update! =)

    Copy & paste the code below to embed this comment.
  23. There is one thing that bothers me. The markup has to be written for the most basic browser that we want to support. Since the markup is static how can our application get advantage of new semantic tags that are going to be introduced in the future releases of html?

    Copy & paste the code below to embed this comment.
  24. The techniques first described in this A List Apart article have since been refined and built into a small JavaScript framework called EnhanceJS. EnhanceJS allows you to easily include scripts and stylesheets in browsers deemed capable of rendering them properly, and comes with an extensible API for running custom capabilities tests and taking advantage of several advanced features.

    Info on EnhanceJS:

    • “EnhanceJS project site”:http://enhancejs.googlecode.com]
    • “EnhanceJS Intro article”:http://filamentgroup.com/lab/introducing_enhancejs_smarter_safer_apply_progressive_enhancement/

    Copy & paste the code below to embed this comment.