In his recent post on web standards and progressive enhancement, Zeldman notes:
When a site like Facebook stops functioning when a script forgets to load, that is a failure of education and understanding on the part of those who created the site.
This has me rethinking the way I’ve approached progressive enhancement.
How I do progressive enhancement
When I write scripts that hide or manipulate content on a page, I make all content visible by default, and use a feature test to add a
.js class to the
<body> element. I only hide and manipulate content when that class is present, esnuring that no one is ever prevented from seeing the content. (Learn more about how I use feature tests.)
Unfortunately, this can cause FOUC.
FOUC, or flashes of unstyled content, happen when markup is loaded before the styles of scripts that style it.
I load my scripts in the footer for better performance. Because no content is hidden or manipulated before those scripts load (progressive enhancement), visitors will often see the page build before them, with all of the drop-down navigation elements visible and tab content stacked on top of each other. Once the script loads, everything looks normal.
A simple way to avoid this is by putting the feature test up in the
<head> element, which is what I now do on all of the sites that build. Since it loads before any of the markup is painted, there’s no FOUC.
So we’re good, right? Well, not exactly…
Failure to Load
The Zeldman quote at the beginning of this piece identifies a giant hole in this approach. If a browser supports the appropriate API’s but fails to load a JS file, the content is hidden, but the script that would allow a user to manipulate and view it isn’t there.
I’ve encountered this countless times, especially on mobile devices where things just time out because they take too long. Not being able to view the content you want is a terribly frustrating user experience—one far worse than a momentary flash of unstyled content.
On Building Escalators
Unfotunately, it feels like progressive ehancement and FOUC are a bit at odds with each other. You could just load all of your scripts in the
<head>, but then your left with flashes of no content, which is even worse.
For now, I plan on updating all of my scripts to run the feature test as part of the JS file itself. It will introduce some FOUC, but if the file doesn’t download, users can still access the content. If anyone can come up with a better solution—one that removes FOUC and ensures users always have access to the content—let me know!