Progressive Enhancement Using Comments

Most methods of progressive enhancement involve setting various DOM elements to display:none and then making them visible from JavaScript, or building new document nodes and inserting them.

In the former case you end up with lots of brittle snippets of code for traversing the DOM and toggling elements. In the later case you often end up having to write the same markup twice: Once in your web application, and once in the JavaScript which enhances your code.

I recently read a blog post by James Padolsey that suggested creating comment nodes with HTML inside and then promoting their contents to real nodes within their parent elements. Neat.

The comments for this article on Hacker News quickly moved to performance however: As you can’t natively scour the DOM for comments, it is necessary to iterate over every DOM element from JavaScript – checking its type and manipulating it if applicable. An expensive business.

If performance really is an issue, but you like the idea of baking your HTML directly into the page as comments, you can replace the DOM traversal with an atomic regular expression replace and an innerHTML assignment. Both of these operations occur in the underlying DOM implementation and are run at native speeds:

document.body.innerHTML = document.body.innerHTML.replace(/(?:<!--\[enhance\]>)|(?:<!\[enhance\]-->)/g, '');

Wrapped up into a tidy rails helper, you can use this to create blocked out elements which will only render if the user has JavaScript enabled:

def enhancement(&block)
  concat("<!--[enhance]>#{capture(&block)}<![enhance]-->")
end
<% enhancement do %>You have JavaScript enabled<% end %>

Obviously it’s not quite as flexible as the DOM-based solution — especially as James seems to be branching out into a fully-blown templating system called JSHTML — but I think it works as a speedy way to encapsulate JavaScript-only functionality.