I use a js-framework (spine.js in my case) in my latest site. Still I make sure that non-js browsers (certainly not over zealous: think SEO) can navigate my site and digest the contents.

As an example I'm going with a search-page with products being shown. Products can be paged, filtered, sorted. Of course this is an example of the generalized idea.

PREREQ: use a template-engine that can both render server-side and client-side. (I use Mustache) . This makes sure you can render models without js- through server-side templating, and render models with js through client-side templating.

  1. Initially: render the products using server-side mustache-template. Also include a 'bootstrapJSON'-object which contains the same products in JSON-format.

  2. Initially: all links (product-detail page, paging, sorting, filtering) are real server-side urls (no hashbang urls)

  3. The end-result is a page which can be navigated 100% with paging, sorting, filtering without the use of JS.

  4. all paging,sorting, filtering urls result in a request to the server, which in turn results in a new set of products being rendered. Nothing special here.

  5. JS-enabled - on domload:

    • fetch the bootstrapJSON and make product-models from it (use your js-framework features to do this) .
    • Afterwards rerender the products using the same mustache-template but now doing it client-side. (Again using your js-framework).
    • Visually nothing should change (after all server-side and client-side rendering was done on same models, with same template), but at least now there's a binding between the client-side model and the view.
    • transform urls to hashbang-urls. (e.g: /products/#sort-price-asc ) and use your js-framework features to wire the events.
  6. now every (filtering, paging, sorting ) url should result in a client-side state-change, which would probably result in your js-framework doing an ajax-request to the server to return new products (in JSON-format) . Rerendering this again on the client should result in your updated view.

  7. The logic part of the code to handle the ajax-request in 6. on the server-side is 100% identical to the code used in 4. Differentiate between an ajax-call and an ordinary request and spit out the products in JSON or html (using mustache server-side) respectively.

EDIT: UPDTATE JAN 2013 Since this question/answer is getting some reasonable traction I thought I'd share some closely-related aha-moments of the last year:

  • Spitting out JSON and rendering it client-side with your client-side mvc of choice (steps 6. and 7. above) can be pretty costly cpu-wise. This, of course, is especially apparent on mobile-devices.

  • I've done some testing to return html-snippets on ajax (using server-side mustache-template rendering) instead of doing the same on the client-side as suggested in my answer above. Depending on your client-device it can be up to 10 times faster (1000ms -> 100ms) , of course your mileage may vary. (practically no code changes needed, since step 7. could already do both)

  • Of course, when no JSON is returned there's no way for a client-side MVC to build models, manage events, etc. So why keep a clientside MVC at all? To be honest, with even very complex searchpages in hindsight I don't have much use for client-side mvc's at all. The only real benefit to me is that they help to clearly separate out logic on the client, but you should already be doing that on your own imho. Consequently, stripping out client-side MVC is on the todo.

  • Oh yeah, I traded in Mustache with Hogan (same syntax, a bit more functionality, but most of all extremely performant!) Was able to do so because I switched the backend from java to Node.js (which rocks imho)


Since I'm a visually-impaired user and web developer, I'll chime in here.

These frameworks, in my experience, haven't been a problem provided the appropriate steps are taken with regard to accessibility.

Many screen readers understand JavaScript, and we as developers can improve the experience using things like HTML5's aria-live attribute to alert screen readers that things are changing, and we can use the role attribute to provide additional hints to the screenreaders.

However, the basic principle of web development with JavaScript is that we should develop the underlying site first, without JavaScript, and then use that solid, working, and tested foundation to provide better features. The use of JS should not be required to purchase a product, receive services, or get information. And some users disable JavaScript because it interferes with the way their screenreaders work.

Doing a complete Backbone.js or Knockout site from the ground up without regard for accessibility will result in something akin to "new Twitter" which fails extremely hard with many screenreaders. But Twitter has a solid foundation and so we can use other means to access the platform. Grafting Backbone onto an existing site that has a well-crafted API is quite doable, and an awful lot of fun, too.

So basically, these frameworks themselves are no more of an accessibility issue than jQUery itself - the developer needs to craft a user experience that works for everyone.


Any webpage that requires javascript in order to get the content out of it will likely be met with accessibility-related challenges. The accessibility of JavaScript frameworks is definitely an issue of contention, though really, any web application suffers drawbacks when content is provided dynamically, regardless of the framework used.

There's no silver bullet to ensure your site will be accessible, and I certainly can't account for every JavaScript framework. Here's a few thoughts about how you can prevent your site from being totally inaccessible when using JavaScript:

  • Follow the guidelines from WCAG 2.0 on client-side scripting, and WCAG 2.0 in general.

  • Avoid frameworks that require you generate the page's UI, controls and/or content entirely through javascript such as Uki.js, or ones that use their own proprietary markup, like Jo. The closer you can stick with static(-ish), semantic HTML content, the better off you'll be.

  • Consider using ARIA roles such as role="application" and the aria-live attribute to indicate the areas of your page which are dynamic. More and more aria roles are being supported by assistive devices as time goes by, so using these aria attributes makes sense when you can add them to your app appropriately.

    In terms of JS libraries, check their source and see if they output any aria roles. They might not be perfectly accessible, but it would demonstrate they're considering assistive devices.

  • Wherever possible, treat JavaScript as an enhancement rather than a necessity. Try to provide alternative methods or workflows to accessing the important information that don't require dynamic page updates.

  • Test and validate your app with your users! Do some user testing sessions with people who use assistive devices or have other difficulties using web software. Nothing will help you prove your site is accessible more than watching real people use it.

The last point is the most important, though many try to escape it. Regardless of the technology, the fact remains that you're developing an application that people will use. No machine or theory will ever be able to perfectly validate your application as being usable, but you're not building it for machines anyway. Right? :)