How to Accessibly Rotate Contents with jQuery

By Aurelio De Rosa

Together with the parallax scrolling effect, rotating content is another example of an effect that you often see implemented in websites. You can see it used to rotate news, tweets, Facebook posts, and so on. When built using jQuery, often developers create the widget employing the hide() and the show() methods (or the similar methods such as fadeIn()/fadeOut() and slideUp()/slideDown()). The problem with them is that, after performing the animation (if any), these methods change the value of the display property of the selected element(s) to none and back to the original value respectively. This behavior leads to an accessibility issue.

In this article we’ll describe what the issue is and how you can use different jQuery’s methods to achieve the same effect but taking care of accessibility.

The Problem

Some people, usually but not limited to visually impaired people, use the TAB key to navigate a website. If you’re not familiar with this concept, what happens is that every time a user hit the TAB key a focusable element of the page is focused. The order in which the elements are focused follows the the order they appear in the DOM (exceptions apply) starting from the very beginning of the page. Some examples of focusable elements (learn more in When Do Elements Take the Focus?) are links, input fields, buttons, and everything that has a value for the tabindex attribute greater than or equal to 0 (learn when and how to use tabindex). The important point to understand is that an element hidden by setting its display property to none is not focusable.

With this in mind you can see that if a TAB user is focusing an element (for example a link) that has been hidden using the hide() method and then the user presses the TAB key, there is a problem. Being hidden in that way is like the element has been temporarily removed from the DOM, so there isn’t a next element to focus. What browsers do in this case is to reset the position, usually focusing the URL of the page. This causes a lot of frustration to the users because they have to start from the beginning of the page every time they reach this death zone. Even more, some of your users can’t even see your awesome rotating effect – all they want to do is access your content easily.

Show Me the Code

To give you a better handle on this situation, consider the following markup:

<div class="rotating-content">
   <p>This is a text with a <a href="#">link 1</a> and <a href="#">another link 1</a></p>
   <p>This is a text with a <a href="#">link 2</a> and <a href="#">another link 2</a></p>
   <p>This is a text with a <a href="#">link 3</a> and <a href="#">another link 3</a></p>
   <p>This is a text with a <a href="#">link 4</a> and <a href="#">another link 4</a></p>

To rotate the content of the div you might write code like this:

$elements = $('.rotating-content').find('p');

setInterval(function() {
   $elements.filter(':visible').fadeOut('slow', function() {
      $next = $(this).next();
      if ($next.length === 0) {
         $next = $elements.first(); 
}, 4000);

Putting everything into action results in the following demo:

Accessible Rotating Content

To solve this accessibility issue while achieving the same effect, we need to employ a different jQuery method, fadeTo(), and one of my favorite CSS helper classes ever, usually called visuallyhidden or visually-hidden. The code of this helper class is shown below:

   border: 0;
   clip: rect(0 0 0 0);
   height: 1px;
   margin: -1px;
   overflow: hidden;
   padding: 0;
   position: absolute;
   width: 1px;

Adding this class to any element will visually hide the element without setting its display property to none.

Now, instead of using the hide() method to hide the element or the show() method to show it, we’ll add or remove the visually-hidden class as needed. Besides, to recreate the nice animation we’ll use the fadeTo() method. The latter allows you to set the opacity you want the element to reach but when it has completed its task, it won’t update the display property (to learn more about this method you can refer to the official documentation). So, we’ll pass to it the value of 0 when we want to hide the element and 1 when we want to show it. Finally, we’ll also set the initial opacity value to 0 to all the elements we want to animate.

The resulting code is shown below:

$elements = $('.rotating-content').find('p');
   .css('opacity', 0);

setInterval(function() {
   $elements.filter(':not(.visually-hidden)').fadeTo('slow', 0, function() {
      $next = $(this).addClass('visually-hidden').next();
      if ($next.length === 0) {
         $next = $elements.first(); 
      $next.removeClass('visually-hidden').fadeTo('slow', 1);
}, 4000);

Putting everything into action results in the following demo:

With this simple change in the code we’ve created a more accessible widget to show rotating content. To see the difference between the two demos I invite you to use the TAB key to navigate the page.


In this article I’ve described an important accessibility issue that can be found in some code used to create a rotating content effect. Some of you may have unintentionally added it to a website built in a widget like the one discussed, but there is nothing to be ashamed of. Everyone ignores a lot of important notions before they learn about them. Yours truly discovered this important issue not so long ago (thanks to the work of people like Steve Faulkner and Léonie Watson).

While learning this simple trick may help you, the main take away lesson here is that when you develop any feature of a website, you should also verify that is accessible, otherwise you risk locking some of your users in an inferno of frustration and inaccessible content.


Hmm... I don't think "rotating" is the right word to use here. When I hear "rotating", I think of CSS transforms or equivalent JS methods.

But I honestly can't think of anything that really describes it well. I guess "carouselling" would have been the most recognizable word, but that's kind of weird.... Maybe something like "swapping out content". Hard to say, but I can definitely say I had something else in mind when I saw the title of this one.


"Rotate through", perhaps?


So here's the thing ... I hate to be critical with people who clearly put an effort into accessibility (I generally save that for people who can't even be bothered to try). But ...

What you've created is not much better than it was before. Yes, you've avoided the situation where focus is reset to the top, but you've now created a situation where lots of elements in the Tab order are no longer visible.

That's fine for screenreaders, it wouldn't make any difference to them, but for sighted keyboard users it means that it now takes 8 Tabs to move through the content, but only 2 of those Tabs are visible.

In practise, you can sometimes get away with the odd 1 or 2 links that are hidden this way, because it only takes 1 or 2 Tabs to get back to something visible (so it tends not to be a big problem with pages that have a single skip link, for example). But in this case, it could take a user up to 6 Tab presses to orientate themselves back onto the visible screen (all the while wondering where tf the focus is!)

So basically, the visually-hidden / offleft approach is not really suitable for elements which are in the Tab order.

I would suggest, for this example, that you go back to the display based implementation, but then you script it so that you're monitoring exactly where the focus is. If the focus is inside an element that you're just about to hide (at the point when you hide it), then you programatically move the focus to the next item. To make that robust, the paragraphs themselves should be in the Tab order, so that the focus() command moves focus to the whole paragraph (then it wouldn't matter if some of the items didn't have any links in them).

I'd also suggest looking at some ARIA markup to enhance it, probably aria-hidden for each paragraph (true if it's hidden, false if it's displayed). And you should provide mechanisms for users to expand the whole thing (so they can see all the items all at once), and to pause the animation (so they don't have to hurry to read it).



Let me reply point by point

If I didn't want to hear the opinion of other people I had to stop writing, so comments are welcome.

To be honest I have never heard or seen any sighted person navigate a website using the TAB key. I've seen people that, like me, use the TAB to move along fields of a form but never to navigate the whole website. I think it's so hard to navigate through TAB that is basically impossible to do that: so many links, so many focusable elements. If you're powered by a screen reader at least you can skip some contents and jump from a section to another thanks to heading or by jumping to the main menu, and so on. For a sighted person is so much natural and easier to navigate through the mouse or the arrows. Even more I think that most people ignore this possibility, so I don't see a real problem here. However, this is just my opinion/experience, so you might have a different experience that suggest you that many users do that which is completely fine.

I don't agree. This would mean increase the weight of the JavaScript to create a functionality nobody will use (maybe the 0.000001% of the users).

Because of the reasons above I don't see the need for that. As you said, this is only needed if a developer doesn't follow my article and wants to implement another technique.

This comment has nothing to do with the article itself, here you're arguing against carousels (carousels-ish in this case). Many people, including me, know that they aren't good or effective in most cases and that they should be avoided most of the times. Still, many developers use them and that's the main topic of the article: let that a website has a carousel-ish thing in place, let's improve its accessibility".


I'm not so sure being "sighted" and using a mouse are always a pair,
AFAIK having trouble using a mouse has more to do with motor control impairment than it does visual impairment.

True, while many use TAB as a "quick short-cut" some may do so as the easiest path of least resistance.

I'm sighted (such as it is) and a mouser so I'll ping a couple that are more knowledgeable than I .
@TechnoBear @Stomme_poes


You've never heard of sighted users navigating with the keyboard? So you've never considered parkinson's disease, or motor neurone disease, or hand tremors, or stroke-related movement problems, or any of a hundred different conditions that make it difficult or impossible for someone to use a mouse with any degree of precision?

Sorry if that sounds sarcastic, but you're promoting accessibility at the same time as denying of its principle audiences. It staggers me to hear that. And that you further claim -- the fact that most developers ignore this issue means that the problem doesn't exist -- is simply astounding.

I never argued against carousels, I simply pointed out that you have a long way to go before your solution is accessible. You wrote this article to encourage developers to take a more accessible approach to this particular kind of script, but you haven't actually produced a better solution. It's better in one way (not resetting focus), but it's worse in another (hidden links in the tab order), and it's just as bad in another (no control over the timing).

You have learned much, but you are not a Jedi yet sunny


To be fair to AurelioDeRosa, I believe this highlights a problem most of us relatively "normal" and "non-challenged" techs have in trying to see the world from the many possible perspectives that others may face. Being Aware is the first step. And working towards Improvement is meritable, small steps though they may be.


I agree, and fair enough. I don't want to make anyone feel like their efforts are inadequate.

But it is unreasonable to expect a higher standard from someone who's paid to write an article about accessibility?

Or at least, for them to take on board the issues that arise, rather than trying to deny their existence and trivialise their impact.


Please stop this "you are not a Jedi yet." thing. I never stated to be an accessibility master, not a ninja, not a Jedi. With this article I'm proposing a better solution to a problem, not a 100% bullet-proof approach. I've never said that this solution will make everyone in the world happy, even those with some disease I've never heard of. It simply improves the accessibility of a widget that is often used in websites and at least for me, doing something is better than doing nothing.

You say:

this is false. With the normal approach you have hidden links too that you can't reach with the TAB key or any other key. You have to be lucky enough to focus the link you're interested in when you press the TAB key. For example if you're already in the widget focusing a link, you can't go to another link and you have to start again. It's like the skeet shooting, you have to calculate the right timing. With the solution I've proposed in the article the user can reach the content at any time. So, even if a user has to press the key more times as you said, he/she still can access the links which is an improvement. Maybe not the best solution in the world and that work in every case possible but still an improvement that everyone can achieve with a few lines of JavaScript.


If you're talking about timing, yes you are talking about carousels and their usual features of being automated and set to a given speed/timing which causes issue to many people. Once again, this is an issue that affects all the carousels in the world, at least the automated ones with no arrows to change the content. In the article I'm describing these kind of widgets. If the article were titled "How to create an accessible carousel" I'd say you're right on this point and that I missed it. But what I'm discussing here is different. The problem of carousels isn't timing, is that they shouldn't exist at all in most cases.


I'm not trying to attack you or patronise you, I simply wanted to suggest some ways in which your solution could be improved. I don't understand why you won't accept the relevance of anything I've said. You don't have to defend what you've done, but you appear not to want to improve it either.

Your solution doesn't improve the accessibility of the widget, it simply solves one problem by creating a different one. You might think it's less important, but you're mistaken.

I know your intentions are good, but you're inadvertently promoting a kind of "ghetto accessibility". You focus on one group of users (screenreader users), and one solution (visibly hidden) to one problem (undisplaying resets the focus), and in doing so, you end up applying the wrong solution to the wrong problem. Using display was not the issue with the original example; its issue was not managing the focus properly.

There's nothing wrong with carousels, or with using display:none, if it's done properly.


Several of us here on the forums, actually. And everyone who needs to use for example Dragon Naturally Speaking, or people like Chris, an Apple-certified Final Cut Pro video editor using switch controls and the like. You may not know people using switch controls (I used to not know any), but I can assure you they exist, and they be internettin' with the rest of us, cleverly hidden behind standard browsers. "On the internet, nobody knows you're a dog."

Keyboard means more than keyboard. Keyboard is generally the replacement for many other computer access methods, meaning when something isn't keyboard-accessible, it's often not accessible with other softwares either. And a lot of those users of other softwares can and do see, but this can go along with the "accessibility means blind people/screen readers/ARIA" fallacy which I myself have fallen into. The accessibility community has started to even worry a bit about that. The largest group of whatever we want to call "disabled" tends to be more motor and cognitive than blind or low-vision, and people who are losing their vision or just have very very bad vision tend to still use their vision as much as possible (noses pressed against the monitor with the computer resolution down to 600x800 and using high contrast settings, even if a screen reader or magnification software would be so much easier to use).

I'll give you visually impaired/dyslexic with something like ZoomText too: you can turn on the Reader function, to also hear where you're either mousing over or where you're tabbing, depending on which method works best for you. It's generally a Good Thing when what you see on the screen matches what you hear and where you are. Hearing stuff you can't see freaks out plenty of people, because users have expectations and that's one of them.

Lastly I'll throw out blind colleagues who often need to be able to work with their sighted colleagues and figuratively, but I guess also literally, have to be on the same page : ) Ha ha, look, I pun. You laugh. potato, okay, moving on.

It is, but usually for other reasons (though the article addresses one, focus going back to the top each time something deep in the page is activated... arg!): autofocus on inputs, lack of focus rings/styles, getting stuck in jQuery autocompletes and AddThis/ShareThis craptastic icons-links are actually way, way worse. Tabbing through an otherwise well-built site is totally doable, especially if you must (I am not limited to keyboard, but it's usually the first thing I start with on sites). You should see what switch users do: they get a little control panel where the focus moves one thing or maybe chunk or row at a time, and you select the one you want with your switch when the focus gets there. Would be damn tedious to me as well, but if I did it every day, well. Would rather be internettin' or mailin grandma or whatever. If you need keyboard, what's your other option?

I agree screen readers make things nice, which is why I'm still hanging a deathgrip on my old Opera12... you can move focus by headings, and form-control focus is separate from link focus. Pretty kewl. Wish this existed today as more than yet-another-slow-your-browser-down Firefox plugin.

Just because carousels are crappy doesn't mean anyone gets automatic exemption from Good-Devs-Try-To-Follow-WCAG (SC 2.2.2): pausing stuff that moves is a sort of requirement anyway-- no code examples should leave it out, because we all know developers copy code examples. Good or bad, it's how it is.

(This caused a bit of a kerfluffle recently when a Google team released a polymer Gmail demo complete with pretty box shadows and stuff. Many in the community pointed out that, especially with the name Google behind it, this demo will become the basis of many other developers' Polymer code, despite not working with keyboard.)

I didn't read the article as anything other than trying to be helpful to devs. But here in the comments, I rather dislike the "you usually eat poop so eating dogfood is better right?" vibe I'm feeling (maybe it's just me, I don't want to put words in anyone's mouth, especially not the word 'poop'). Yeah, it's better, but we want people-food. And when I'm duckduckgo-ing for "accessible carousels" as a conscientious developer, this article ought to turn up (being recent, and on SitePoint, and having a somewhat-well-known author to boot).

This could be a part 1 of however-many articles series for "jQuery accessible carousel" where in this one, the point is how to stop focus from being super annoying. So many people are looking for how to do this, especially with jQuery-- so I'm definitely looking forward to more articles on this. They're not easy, but then again if we as devs are forced to build a carousel anyway, then we should take it like adults and admit that yeah, we're going to be adding a bunch of JS-crap for manual focus management and whatnot... we do this already with our accessible modal dialogs (good god), accessible dropdown menus (ug) and accessible tab-panels (lord on a stick). They suck to code. We do it anyway. And we all want to see How Should We Do It. So write more!


Nicely put.

And you make an important point about "keyboard" not necessarily meaning a keyboard, it could be any kind of focus-actuation. The comparison I tend to think of there is the Sony PSP -- it has a browser which can navigate with the D-Pad, and click things using the fire button! But conceptually (and programatically) it's the same as Tab and Enter.

You're brave sticking with Opera 12! I was a die-hard fanboy, but even I've stopped using it now. It was hard enough to get developers to support it while it was still the latest version!


btw -- Russ Weakley and I are doing a Learnable course next year, looking at some of the most popular widgets and talking about how to do them accessibly. The three things you mentioned (modal dialogs, dropdown menus, tab panels) are all included smile


I just want vendors to build some of those into the browser. At least modals. I'm currently using the silly trick of invisible keyboard traps (listening for event parent doesn't seem to always work when shift-tabbing) coupled with aria-hidden on the rest of the website, which will fail the moment I get a modal that for whatever reason cannot sit outside the main page element.

We have Javascript and chrome alerts already. Built-in, with focus control and names. Gimme.


I do it by tracking Tab events. You've got a bunch of focusable elements within the modal which are in tab order -- when you receive a Tab keydown on the last one, move focus to the first one; when you receive Shift+Tab on the first one, move focus to the last one.

You can't do it with blur events (or DOM equivalents) because you have no way of knowing where the focus is moving to.

But I've not had any problems with the Tab approach ... have you?


I've never done a Tab Event approach-- i've tried that thing where you look at the parent of the target to see if it's the modal (I've seen lots of code out there doing this), but I've always been able to Shift-tab out of those when I build them, so I must be doing something wrong.


The Tab approach is the only reliable way I know. Focus/blur based approaches are unreliable, because they don't have enough information to be sure of where the focus is going to.

Although, the other way you can do it is to set tabindex -1 on every other page element while the modal is open ... but that's a brutal hack!


That's becoming popular: the modal is a direct child to the body and sibling to the page. The page gets aria-hidden and all the other junk, as if the modal is the only thing around on the site now. I'm wary of aria-hidden anyway, but if the modal can always be outside the page it seems usable along with keyboard traps.

Here's an example of what I was talking about

<div class="container">
    ...whole page...
    <div id="zee_lightbox">
        <button class="button-close">closey</button>
    more page...

$('.container').on('focusin',function() {                           
            if (!$('#zee_lightbox')) {                    

something like that, I may be writing it wrong, this is from some crappy code I found somewhere. I end up using manual traps.

As it is I'm usually (with carousels) grabbing chunks of lists and setting tabindex to -1 on everyone, then determining who is visible, and giving them tabIndex 0 back, with every carousel click (my carousels don't move on their own). It's a metric crap-ton of code (those are smaller than US crap-tons I think) but as a keyboarder I love knowing I can just tab through only the article or item or whatever who's visible and won't go off to whoever's offscreen-but-not-display-none links. I use a "frame" technique where the outer element merely only shows one panel/item/article/thingie at a time, instead of display: nonning the rest. It degrades nice without JS, you just have a visible, vertical, scrollable list.


Yeah I've been using similar tabindex tricks here and there -- I believe the general principle is known as "roving tabindex", i.e. adjusting which elements are in the tab order according to the current context and activity, to minimize unnecessary tabbing. It works quite well, but can take a lot of code to get it right, and obviously has to be exactly right and thoroughly tested, to avoid causing problems for the user.

(I think a metric crap-ton is 0.568261 US crap-tons :-D)

But monitoring the focus position relative to a parent is not reliable enough, in my experience. There's too much browser variation in their bubbling behaviour, and focus changes don't necessarily mean keyboard navigation anyway.

The only situation I know of where Tab keypress monitoring doesn't work, is when using Spatial Navigation in Opera 12 (since that uses Shift + Arrow Keys). But ... well you know, Opera 12 is a dead browser! I don't think it's worth spending time trying to support it anymore.

Oh, and there's Firefox in fullscreen mode -- since FF has an "allow fullscreen" dialog with OK and Cancel buttons, if you use the Tab-key approach within the fullscreen element, then you make it impossible to Tab to that dialog. So I use the approach of setting everything else to -1 (but only for Firefox, since other browsers either don't have that dialog, or don't put it in the tab order anyway). Though really, fullscreen content should be treated as modal by the browser, but that's a whole other world of issues!


Must've been what I was hitting.

Ah well I'll hold off building anything that breaks my favourite browser until
a) the new blinky Opera supports keyboard like that
b) can be installed on 32-bit Linux (this is where it's not dead, 12.06 is latest for 32-bit still)

The firefox fullscreen thing sounds scary, because then who else (tvs and kiosks and weird things) will do similar?

Actually, re-reading this, I once tried to implement something similar, meaning first I had to get a list of "focusables" and when I coded it it was slow and hoggy (for a dropdown menu for companies who want all 3000 product sub-categories on one page, I guess in the belief that it's good for the googles or that people still hold to the max-3-click-rule or something...).

So instead for each keypress I'd check direction (is e.shiftkey?) and see if there was simply a "next" or "prev" focusable within the parent... if not, go to first/last.
It works okay, except the last of the last and getting out-- I have to be able to know who will come next after the element I'm managing focus on. So it's not an agnostic script I can throw into anything, which I'd rather have. Would be nice if there was a command in Javascript to tell the browser "take over from here like you normally would" regarding focus.



Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.