Accessibility and all these JavaScript frameworks
Asked Answered
B

4

67

I've been investigating a few of the JavaScript frameworks such as Backbone.js and Batman.js for a while and whilst I really like them, I have one niggling thing that I keep coming back to. That issue is accessibility.

As a web developer I've always tried to make my websites and applications with accessibility in mind, especially using the idea of progressive enhancement.

Clearly out of the box these new JS frameworks don't gracefully degrade, so I was wondering what are other developers thoughts on this issue and what are you doing about it. After all the accessibility of a website / app isn't really an optional thing as it's part of the law in many countries.

Maybe I'm just being overly zealous on this subject, and not appreciating how far things have come in terms of accessibility.

Bach answered 10/9, 2011 at 6:32 Comment(0)
B
60

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)

Bregenz answered 10/9, 2011 at 12:19 Comment(16)
nice thing with this as well, is that you can design your page for non-js at first. (not having to think about js-navigation, etc. from the beginning). Afterwards you can 'progressivly enchance' your code to incorporate points 5-7. Your server-side code is already in place for the ajax-calls (just have to write 1 line of code per server-side controller to distinguish between ajax and non-ajax calls)Bregenz
+1 for the practical examples and advice, especially about having a templating language that works on both the server and client side. I use Soy myself, but that's because I'm stuck in Java-land D:Stonefish
This strategy is absolutely spot on. Great explanation of the implementation too. Reusability of templates is huge in terms of getting developers to buy into "accessibility isn't that hard."Kyongkyoto
@Chris: using Java here as well. Mustache has a java implementation.Bregenz
this is pretty much how I create web apps, except I just use jQuery AJAX calls. I do something very similar to pjax. I'm just wondering if using Backbone.js has any advantages over something like pjax?. Ta for the excellent response though.Bach
@John: Well most important, to me at least, is not so much the provided functionality (I've extended quite a lot in spine.js) but more the seperation of concerns (mvc) you are 'required' to work with. As an example I recently implemented a kind of virtualization layer, decoupling models fetched from models displayed. This allows for, say, fetching 20 models, but displaying only 10 at a time making any other paging-call free (no need for an ajax-call) . Also back-paging is free. Not having had SoC from the start, this would have cost me quite some refactoring, now it was done in an hour.Bregenz
@Bregenz yep that's a fair point actually. Also a framework does guarantee some level of consistent code style.Bach
That's why vcard and other microformats are so great - the more commonplace, the more reliably you can account for that kind of content in things, like screen-readers :)Stonefish
@Geert-Jan: First, in point 5.2) you say you render on client side -- is this to say you overwrite what was rendered on the server-side, or that you just enhance it in some way? Second, with Mustache do you not have to duplicate some transformation logic in JS and server-side code so that the data you pass to your Mustache templates works properly? For example, I find that specifying which option in a select is the default requires me to attach an 'isDefault' boolean to each row since Mustache is logicless.Groovy
@RenderIn: I do a complete overwrite, because, in my situation, there's some event-binding on the dom-objects going on as part of the client-render flow (binding dom-elements to client-side models). Of course it's possible to have a seperate code-path that binds the created client-side models to the already existing dom-elements (as rendered server-side), so without doing a client-side rerender. That would give a slight performance gain. However, I like the cleanness of not needed this seperate code-path at all.Bregenz
@RenderIn: as to your second question: indeed I sometimes need to provide some state to discriminiate between products being rendered client-side or server-side respectively. In this example, for example (hmm :)), client-side rendering need to render out hashbang-urls while server-side rendering renders-out 'normal' urls. I solve this on the client-side by mixing-in (or overriding) properties of the js object-literal that represents the products. So for the change in urls, I simply override the product.url property for each product.Bregenz
Wouldn't it be better to use HTML5 pushState that falls back to hash-bangs if the browser doesn't support it? That way your client-side routes can match your server-side routes exactly, no need to change the href to hashbangs on page load, only intercept the link click and render the corresponding view.Quiteria
@Scott: Yes indeed, it's a nice additional progressive enhancement. I haven't considered SEO implications thoroughly with this though. What if your client-side rendering was clearly different from server-side for whatever reason. (as opposed to the strategy above). This would give 2 different results under the same url depending on whether javascript is enabled or not. Would this be considered cloacking/bad practice from google's standpoint? In any case in the above situation it would work great.Bregenz
I also wonder about the "cloaking" issue. I guess the best solution would be to render the same content by using the same exact templates both server-side and client-side. This seems to me to be the direction the web is heading, and it would be unfortunate if Google penalized someone for taking progressive enhancement to the next level.Quiteria
well, to me, "render the same content by using the same exact templates both server-side and client-side" (as my answer above does) can never be considered cloaking, as the content is the same. So what is there to cloak? Only when things are different could this potentially be a problem imo.Bregenz
So do we have a recommendation for a JS 'framework' that can assist with PE? I have a server rendered site with PE but the JS is in danger of getting unwieldy and I feel like some kind of framework/clear pattern for handling AJAX responses, redirects, session management etc would help greatly. I don't think i need the 'power' of a full-blown client-side framework such as Backbone, Angular, Ember etc.Nicolette
K
24

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.

Kyongkyoto answered 10/9, 2011 at 15:0 Comment(3)
completely agree with this, JS is a layer that should be added later, and not necessary for a functional site (progressive enhancement). Unfortunately I've recently had discussions with developers who feel that web apps are different to websites and for web apps a user has to expect JS for it to work.Bach
have you had any experience with bootstrapping the views with server-generated templates, and then using the JS for subsequent renderings? batman.js, specifically...Kerouac
So question for you @stackoverflow.com/users/107134/brian-hogan, if we use the aria-live with items that appear or change would we also use aria-expanded for divs that appear on click such as with jQuery Show/Hide? We are required to be 100% accessible no exceptions.Magnien
S
16

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? :)

Stonefish answered 10/9, 2011 at 9:21 Comment(4)
completely agree with this. I suppose my concern is that the popularity of things like Backbone.js are really taking off, and yet no one seems to be talking about the accessibility issue. It's either developers don't care, or simply they want to play with sparkly new tools.Bach
By and large, the uninitiated will never exercise due care for accessibility; it's something they don't see, hear or know about, and they may either not understand or simply not care. People who write frameworks are just as susceptible to this as the people using them or writing javascript in general.Stonefish
There's a few vocal individuals in the scene trying to bring the accessibility issue in to the foreground. Steve Faulkner and Bruce Lawson are two such individuals. On the whole, though, I don't think it will ever become a common practice to exercise due care for accessibility. It's such an iceberg of a topic and so hard to get right in the general case.Stonefish
mm started to enter a comment, but I'll write an answer instad.. Have to write something here, because I can't delete this..Bregenz
E
2

Chris Blouch (AOL) and Hans Hillen (TPG) had a good presentation on this regarding jQuery, including the work they do in reviewing for accessibility. Making Rich Internet Applications Accessible Through JQuery That and another related presentation on Accessibility of HTML5 and Rich Internet Applications (http://www.paciellogroup.com/training/CSUN2012/) should be of interest to you.

My money is on choosing the most accessible framework: jQuery provides a great deal of graceful degradation or progressive enhancement fallback as well as an overall pretty good focus on accessibility. Also, indirectly I help test and review several systems that leverage jQuery (Drupal public and Intranet websites) such that defects found for accessibility are found and routed back to the project for fixes.

Effectuate answered 1/10, 2012 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.