Skip to content

24 ways to impress your friends

How Tabs Should Work


Comments are ordered by helpfulness, as indicated by you. Help us pick out the gems and discourage asshattery by voting on notable comments.

Got something to add? You can leave a comment below.


Hi, Remy.

Cheers for the detailed post.

Just wanted to add that truly conventional, accessible tab interfaces have a specific way of handling keyboard operation: Only the left and right arrow keys should switch tabs and – simultaneously – reveal the associated panel. The TAB key is preserved for moving between the active TAB and the open panel. This means inactive tabs should have tabindex=”-1” and be focused/activated only programmatically (via the aforementioned arrow keys).

The reason for this is that keyboard and AT users should be afforded a direct route to the chosen content without having to cycle through all the tabs in the tablist each time. I have a demo of this here: (This doesn’t so far implement your other suggestions RE hashchange etc :-( ). There’s a note on widget keyboard interaction here:


Why on earth do you want the back button/back key command to open the last tab? A tab is a ui element. The back button should go to the previous page you visited. This is a standard. You cannot change a standard and expect people to like it.

Rodney Rehm

Thanks for this article!

The presented ideas can be taken further to cover the entire navigation of a “single page application”, as explained by Heydon in Reimagining Single-Page Applications With Progressive Enhancement

While on the topic of tabbed panels, maybe the panels and panelsets proposal is interesting in this context?

I’m not an accessibility expert, but as far as I understand screen reader users might expect a bit more keyboard support than Tab and Enter when confronted with @role=“tabpanel”@, as suggested by [ARIA Practices](

Thierry Koblentz

I do not think jump links are the best fit for creating tab panels. Actually, I’d argue that such solution forces SR users to create a more complex mental model than necessary. A “KIS” approach shows that there is no need for JavaScript nor for ARIA roles:

David Hund

Thanks for this good intro on Tabs, Remy.

There’s obviously some things that you’ve not dealt with (like you mention yourself) such as multiple tabs on a page, etc.

One other feature I often miss is keyboard arrow access. While it’s easy to tab through the tabs (wow…), it’s often nice to be able to use the left/right arrows too. A small enhancement.

Apart from those I noticed one bug: when you navigate from “Dizzy” (no hash) to “Ninja” the Back button does not work as expected. This is, of course, because the first tab “Dizzy” is active without a hash. To enable back-button functionality you’d have to initialize the first tab with a hash (or something like that).

Also: you can re-create much of this tab functionality with CSS and the `:target` pseudo-class. This would show/hide the tab panels even when JS is off/errs.


Nice writeup! I like the no-click-events approach.

However, I noticed that middle/scrollwheel-clicking (which I use to open stuff in new tabs) breaks the panel in the original window. Possibly because the id never gets re-added to the panel in this case?


Nice approach, I had almost the same for my tab plugin :)

The biggest issue is the keyboard management (the Design Pattern is quite complicated at the first reading : and some keys are impossible to use), but once you got the logic behind, it is ok. ;)

Vladimir Andrijevikj

Another way to avoid the page jump without breaking right-click, Shift-click, and other clicks, is written up at

Instead of the remove-and-return-id technique above, this technique checks whether we are dealing with a left click in the click handler, and only then does it override the default behavior (returning false, and avoiding the jump). For all other clicks, it falls back to the browser default.

Anthony Moendir

Hi Remy, awesome stuff! When I look at the ARIA practices page the interaction for Tabs is slightly different. Arrows are used to navigate between tabs which will also show the corresponding tabpanel and only the active tab and tabpanel are in tab order. Adding this might make your tabs even more accessible. See:


Hi Remy great article, I only have some concerns on the ARIA part :
- first you have to choose to follow or not the aria tabpanel design pattern (and it isn’t always a good idea since it’s an application design pattern who no always fit in a website and who are not very mobile friendly)
- if you choose to follow it you article and demo are wrong on keyboard navigation (only the active tab can get focus with tab key, then you need to use arrow key to switch tabs) and you need a role=“presentation” on the

  • elements
    - if you doesn’t want to follow it it’s best to not use the role tab and tabpanel but simply a list of button or in your case with an aria-expanded attribut. Also in that case you don’t need tabindex since you use element with href attribut it’s focusable by default and it can be a good idea to add a link to the list of button at the end of each panel to allow keyboard/screenreader user to go back the list quickly

  • Peter Hentges

    You’ve done some good work here and obviously care a lot about how things work. You’re missing one little ARIA thing: Your elements with role=tab need to have a container with role=tablist. You could also work on adding the keyboard interactions suggested in the ARIA authoring practices: But that’s probably another article on its own!


    Great article! One thing I noticed in your live example, if you cmd+click a tab to a new (browser tab) the image on the original page gets lost. E.g., start on the first tab #dizzy, cmd+click the second tab #ninja, then just click on the second tab (ignoring focus on the other browser tab). This is because your ID gets removed. Chrome/OS X.


    We’ve decided to deprecate tabs altogether since they were being so badly abused by our content editors; who essentially treat them as pages within pages and overload them with content.

    One major issue I have with tab implementations that make all tab content on the page accessible to search engines is that a search result may lead to a page where the relevant tab content isn’t immediately visible, and worse still the keyword used in the search isn’t findable via a browser search (since it’s on a hidden tab). Are there any tab implementations out there that address this limitation?

    Impress us

    Be friendly / use Textile