Thursday, February 25th, 2010

EnhanceJS: A library to progressively enhance

Category: Accessibility, JavaScript, Library

EnhanceJS is a new library from the Filament Group, who are serious about progressive enhancement and accessibility.

What is EnhanceJS?

EnhanceJS is a new JavaScript framework (a single 2.5kb JavaScript file once minified/gzipped) that that automates a series of browser tests to ensure that advanced CSS and JavaScript features will render properly before they’re loaded to the page, enabling you to build advanced, modern websites without introducing accessibility problems for people on browsers that aren’t capable of supporting all advanced features. It’s designed to be easily integrated into a standard progressive enhancement workflow: just construct the page using standard, functional HTML, and reference any advanced CSS and JavaScript files using EnhanceJS to ensure they’re only delivered to browsers capable of understanding them.

So, you have simple markup, if you pass the test you will get “enhanced” with new CSS and JavaScript behaviour additions to take things to the next level. You can even do conditional CSS for IE:

  1. <script type="text/javascript" src="enhance.js"></script>  
  2. <script type="text/javascript">
  3.     enhance({
  4.         loadStyles: [
  5.             'css/enhancements.css',
  6.             {href: 'css/print.css', media: 'print'},
  7.             {href: 'css/ie6.css', iecondition: 6}
  8.         ], 
  9.         loadScripts: [
  10.             'js/jquery.min.js',
  11.             'js/enhancements.js'
  12.         ]
  13.     });  
  14. </script>

There are detailed docs:

Go to the bottom of their blog post and click on the low-bandwidth version to see it in action.

Posted by Dion Almaer at 6:42 am

2.6 rating from 58 votes


Comments feed TrackBack URI

I haven’t looked at this implementation to judge for its quality. But stitching web-pages together on the back of a JavaScript dependency is bad practice no matter how cleverly you do it

Comment by PeteB — February 25, 2010

@PeteB, seems you haven’t read a single word in the article either or simply don’t know the term ‘progressive enhancement’.

Comment by BenGerrissen — February 25, 2010

@Ben I do know that term, I also know the term ‘graceful degradation’.

It may be more convenient to load assets dynamically like this, but it isn’t a very good service to users with JavaScript disabled; a better, although less slick, alternative is the conditional comments that most people are already using.

Comment by PeteB — February 25, 2010

Looks like to be an alternative to Modernizr

Comment by vjeux — February 25, 2010

@PeteB The whole point of this library is so browsers with less capable engines don’t get content they can’t handle. So a user with JavaScript disabled will get a proper, functioning site without any CSS/images/HTML that are only designed for JavaScript functionality. It seems to me that this *enhances* the experience for no-JS users.

Comment by posaune — February 25, 2010

Nice! But that’s yet another js include :(

Comment by stoimen — February 25, 2010

Seems like the code contradicts the purpose. A library that feature tests for potential enhancements, yet sniffs out IE?

Comment by RyanMorr — February 25, 2010

– include non-js dependant files normally.
– use EnhanceJS to load js dependant files and css.
You know, display an Accordion as a list of articles without JS.
Add css files dynamically to transform an Accordion to an actual accordion.
Add Accordion behaviour through JS and kickstart the Accordion css by adding an js css class to the accordion container.
‘progressive enhancement’ means building sites with bare minimum dependencies FIRST and then progressively enhance it through JS. It’s even better to only load the needed JS/CSS files when JS is actually present.
Furthermore, as a bonus, EnhanceJS adds files in such a way, your normally included css and html rendering doesn’t get blocked/stalled.
Faster page load, smarter achitecture, better maintenance, faster development, faster working version for clients to see.
Gracefully degrading is not a technique, it’s a result, progressive enhancement is THE technique to make sites gracefully degrading. If you don’t get the benefit of EnhanceJS or similar frameworks, then you don’t get ‘Progressive enhancement’ at all and will be stuck with conditional comment abominations (which is a good technique that works, but worst choice of all the options at your disposal) and painful backwards enginering to make all your sugar and spice work without JS.

Comment by BenGerrissen — February 25, 2010

@RyanMorr, some people are not so skilled in CSS, hate degrading css hacks or have pixel perfect demanding clients and have a need for an IE6 only stylesheet. A lot of IE6 css quirks cannot be feature detected. (you don’t need IE6 only stylesheets if a few pixels difference isn’t an issue)
ps. I am in no way tied to EnhanceJS, but it’s disturbing to see lack of common knowledge… Most frameworks are headed in this direction, not just EnhanceJS… It’s not a fringe idea, it’s becomming a standard… Get with the program.

Comment by BenGerrissen — February 25, 2010

Scott from Filament Group here (authors of EnhanceJS). Thanks, Ajaxian for covering our post!

A while back, I thought the same thing, but the more we built sites with progressive enhancement, the more we saw that including unqualified, advanced CSS and JS on a page can be disastrous for users on older browsers and mobile devices (both old and new). Unfortunately, the norm these days is to test for the latest browsers (IE6-8,FF2+,Safari 2+, etc) and then turn a blind eye to the rest, assuming the page will probably “just work” in other browsers, even if it’s not quite perfect. Unfortunately, browser support for CSS and JS is not as clean as support/doesn’t support split, and when certain properties are improperly or incompletely supported, we often see a perfectly usable page get *enhanced* into a non-functional, unusable mess, and this is happening in browsers that are widely used today (particularly in developing nations). These days, the enhanced version of a site usually requires a tight synchronization of CSS and JS. If either isn’t supported well, the experience often breaks. For example, imagine creating a slider control, a dialog overlay, or client-side tabs without great CSS and JS support. This isn’t limited to highly functional apps either – the problem exists in ordinary website layouts too, and plenty of popular sites offer up a broken experience to users who don’t have the latest browsers.

The goal of EnhanceJS is universal accessibility, and applying progressive enhancement *only* when we know it’ll work seems to be effective in achieving that that goal. As @Ben mentioned, there are other benefits to using EnhanceJS such as page load speed, since mobile devices won’t have to download the JS and CSS they won’t use. The “low-fi toggle link” even lets you cookie yourself for a low-fi experience if you have a browser that would normally pass, which is nice for iPhone users who just want a quick load, for instance. I know I’d much prefer a perfectly functional, but less designed, page over a broken one. So our goal is trying to deliver the appropriate experience to the right browser. Sorry for the plug… you can read much more about all this in our new book :P

Comment by ScottJehl — February 25, 2010

@RyanMorr: The IE sniff part is *only* there if you need to mimic a conditional comment. In other words, if your page uses an IE-only CSS file or something, EnhanceJS has a mechanism to support that for you. That detection is only used in that one case, so for all of the testing it only uses feature detection.
Anyway, we agree that it’d be nice to find a different way to include IE-only assets, and we’re working on possibly using JS to inject conditional comments instead.

Comment by ScottJehl — February 25, 2010

@BenGerrissen – ‘faster development’; oh…so by restructuring the whole way I architecture my websites and then adding this extra code, I will be able to develop faster? :)

Comment by sixtyseconds — February 25, 2010

It is great to see another framework that makes it easier for people to follow progressive enhancement best practices.

There is another option for companies that don’t want to make client-side changes or have a framework that would make it difficult to manage. You can conditionally exclude JS/CSS server-side based on UA. Following Yahoo graded browser support as a model you create whitelists and blacklists for who gets what.

We choose to always deliver a full set of CSS or JS if the UA wasn’t on the blacklist. This allows feature detection and conditional comments in the browser, but allows us to skip markup and external assets for browsers we know it won’t work for.

Comment by AdamGoldstein — February 25, 2010

I highly doubt that it has positive impact for performance. The demo’s also feel more suggly because you sometimes see a FUOC. Makings the perceived performance allot slower than it actually is.
Nice library but i highly doubt i would ever find a real use case for it.

Comment by V1 — February 25, 2010

@Adam: Glad you like the framework. However, we find a lot of faults in the UA testing approach when compared to feature detection. The main problem we see in the Yahoo GBS model is that Grade X browsers get the same experience as Grade A. A whole lot of browsers (new and old) can be considered “Grade X”, and quite often, serving those browsers CSS and JS as if they are “Grade A” means the user receives a “Grade F” experience. :P

UA testing also means updating that whitelist every time a capable browser comes out, and assumes you know about every browser out there that should be getting enhancements.

@V1: There’s pretty simple way to prevent a FOUC with EnhanceJS. Check out this docs page if you’re interested:

Comment by ScottJehl — February 25, 2010

@vjeux – they seem to be pimping it as a companion to modernizr – a comment from the blog post reads
“[Modernizr] provides a great suite of tests for HTML5 features, and its tests could be integrated with EnhanceJS if you wanted to enhance a page based on proper support for HTML5 features. ”

Personally, I’m feeling lazy and I want a prefab integration ;-)

Comment by rdza — February 25, 2010

@DavidMark – Thanks for taking the time to thoughtfully and politely air your views. :)

Comment by sixtyseconds — February 26, 2010

@sixtyseconds: Was that sarcastic? I genuinely can’t tell. I thought David’s post was both thoughtful and polite.

Comment by timdown — February 26, 2010

@timdown – It was sincere! :)

Comment by sixtyseconds — February 26, 2010

@David Mark

The bit about loading scripts without blocking is a major red flag though.

Read Steve Souders articles. You’re absolutely right if your application/page is JS dependant, but thats the whole point, making your pages work without JS and cutting down on useless load times. Offering content sooner in an opted or forced low tech environment.

And (contrary to popular opinion) in browser scripting, the context-specific solution will always trump generalizations in terms of size, speed and maintainability.

Hmm, yes and no. YUI3 and Dojo for example allows context-specific script loading solutions and is more maintainable and pluggable. Libs like OP offer partial solutions, pretty much like $LAB for libraries that either pollute the global scope or are namespaced nightmares. Size and Speed are relative to conditions and environments, maintainability depends on how you architecture your code and is thus a strawman argument.
There are many ways that lead to Rome.

Comment by BenGerrissen — February 26, 2010


Hello from Rome! Lovely this time of year.

I have no comment on Steve Souders, YUI or Dojo at this time. I’ll just leave it at that. :)

Comment by DavidMark — February 26, 2010

No one is in Rome yet, neither are you ;) We still have some ground to cover, but the foundations are being laid down.
Had a look at your MyLibrary documentation, will have to look at code soon, but looks interresting. The collection of utility is rather impressive, though it needs some API organisation to become mainstream. API clarity is paramount and whilst the method names are very descriptive, they are all attached to a single namespace, might as well throw it all in the global scope that way…
David, luckily your MyLibrary is not mainstream, that means you can tinker it to perfection still. The code probably doesn’t need changing, just the organisation for clarity and usability. In fact, the documentation shows a very low level API, meaning there’s room for an higher level API abstracting functionality further.
It’s obviously all to your own discretion, it’s your library afterall ;) but somehow I get the feeling you want us to use it as well and that means altering it a bit to make it more attractive for a larger audience. It’s the only way you can break free from anonymity if thats your intent.

Comment by BenGerrissen — February 27, 2010

Leave a comment

You must be logged in to post a comment.