Last week I spent my Friday afternoon trying to get my head around how to apply ARIA properly to a tabbed interface. I even got so far as to map it out on my whiteboard and snap a photo so I could mull it over during the weekend.
And then the very next day Marco Zehe, responsible for accessibility quality assurance at Firefox, posted Advanced ARIA tip #1: Tabs in web apps and suddenly my weekend of snow shoveling turned into fiddling.
Marco's post included sample HTML for tabs and an outline of how the script to control it should function, but did not include the necessary styles or script to make it behave as tabs. Since I was marking up a tab list anyway to incorporate ARIA, I'm sharing my code here for others to try, enhance, and so on. It's also on CodePen, so you can fork it and fiddle there.
The HTML
My code has minor differences from the example. For instance, I add a return false;
at the end of the event handler. I also call the function that activates the first tab at the bottom of the page, so all tabs start as un-selected and no tab panels are visible until that function fires. You can just as easily put the logic into your HTML and CSS to have one pre-selected and skip that function call altogether.
<ul class="tabList" id="tabs" role="tablist">
<li role="presentation"><a id="tab1" href="#panel1" onclick="showTab(1);return false;" role="tab" aria-controls="panel1" aria-selected="false">Tab 1</a></li>
<li role="presentation"><a id="tab2" href="#panel2" onclick="showTab(2);return false;" role="tab" aria-controls="panel2" aria-selected="false">Tab 2</a></li>
<li role="presentation"><a id="tab3" href="#panel3" onclick="showTab(3);return false;" role="tab" aria-controls="panel3" aria-selected="false">Tab 3</a></li>
</ul>
<div class="tabPanels">
<div id="panel1" role="tabpanel" aria-labelledby="tab1">
<p>
Nulla tincidunt pharetra tortor. In dapibus ultricies arcu. Suspendisse at purus eu est tincidunt feugiat. Praesent et sapien. Vivamus fermentum, diam vel ornare vestibulum, nibh massa imperdiet lectus, eget tincidunt urna urna nec erat. Curabitur interdum. Nam lorem nunc, posuere quis, suscipit eu, hendrerit vitae, nisi. Etiam hendrerit tincidunt felis.
</p>
</div>
<div id="panel2" role="tabpanel" aria-labelledby="tab2">
<p>
Vestibulum id eros eu lorem tincidunt sollicitudin. Suspendisse ligula. Sed nisi magna, elementum at, ultricies in, tincidunt imperdiet, quam. Nulla semper. Suspendisse potenti. Sed sollicitudin dolor aliquet purus. Aliquam dui. Proin arcu metus, porttitor eget, pulvinar nec, molestie dapibus, ligula.
</p>
</div>
<div id="panel3" role="tabpanel" aria-labelledby="tab3">
<p>
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam vel erat. Vestibulum egestas purus ut felis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>
</div>
</div>
<script>
showTab(1);
</script>
The CSS
This CSS presumes you've already set your typefaces, your page background, and everything works as you want. I have put the minimum styles to make it visually look like tabs. You may notice that I use two different selectors for both a selected tab and for a hidden tab panel. One is by a class name, the other is by the value of the appropriate aria-
attribute. Use the first for broader (older) browser support and the latter if you don't care. If you do target just current browsers, then you may adjust the script below to skip writing class
es.
.tabList {
list-style-type: none;
padding: 0;
margin: 0 auto;
}
.tabList a {
display: block;
float: left;
border: .1em solid #000;
padding: .25em 2em;
margin: 0 0 -1px .25em;
border-radius: .5em .5em 0 0;
background-color: #aaa;
}
.tabList a:link, .tabList a:visited, .tabList a:hover, .tabList a:focus, .tabList a:active {
text-decoration: none;
color: #000;
}
.tabList a:hover, .tabList a:focus {
background-color: #ccc;
}
.tabList a.selected {
background-color: #fff;
border-bottom: 1px solid #fff;
}
.tabPanels div {
clear: left;
margin: 0 auto;
padding: 1em 2em;
border: 1px solid #000;
border-radius: .25em;
background-color: #fff;
display: none;
}
.tabPanels div.selected, div[aria-hidden=false] {
display: block;
}
.hide, div[aria-hidden=true] {
display: none;
}
The Script
The following script toggles classes for the tabs and the tab panels, as well as adjusting the aria-selected
and aria-hidden
attributes. There is no keyboard functionality in it at all, but I am always willing to take some from a kind donor. As I noted above, if you use solely the aria-
attribute as a CSS selector, you can drop the part that changes the class
for each element.
var OpenTab;
function showTab(num) {
try{
if(OpenTab!=undefined){
var OldTabID = document.getElementById('tab'+OpenTab);
var OldPanelID = document.getElementById('panel'+OpenTab);
OldTabID.className = '';
OldPanelID.className = 'hide';
OldTabID.setAttribute('aria-selected', false);
OldPanelID.setAttribute('aria-hidden', true);
}
var TabID = document.getElementById('tab'+num);
var PanelID = document.getElementById('panel'+num);
TabID.className = 'selected';
PanelID.className = 'selected';
TabID.setAttribute('aria-selected', true);
PanelID.setAttribute('aria-hidden', false);
OpenTab = num;
}catch(e){}
}
An Example
The following is an embedded version of the tabs on CodePen. Because of how CodePen works, you'll see a few minor differences in styles, but this is at least a functional example which you can fork and tweak.
For example, on CodePen, the function to enable the first tab must be called in the block of script
itself, but I prefer to call it at the bottom of the page.
For reasons I cannot figure out, the tabs on the embedded version of this Pen do not work. Visit the tabs directly on CodePen to see them in action.
Check out this Pen!
Wrap-up
That's it, pretty simple. If you have suggestions, corrections, or are a regular AT user and can offer further insight, please feel free to share in the comments or tweet me on the Twitters.
Update, August 6, 2012
Marco Zehe, the guy who wrote the article Advanced ARIA tip #1: Tabs in web apps (which I link above) offered some adjustments to make to my sample code. In essence, dump the aria-hidden
from the HTML and use the CSS style visibility: hidden;
in its place. His explanation:
@aardrian That would definitely be preferred over aria-hidden, since aria-hidden is not supported by all screen readers.
— Marco Zehe (@MarcoInEnglish) August 2, 2013
@aardrian Especially older versions of JAWS, which you'll still find a lot, will ignore it.
— Marco Zehe (@MarcoInEnglish) August 2, 2013
@aardrian So use visibility: hidden; in addition to display: none;, and you should be good. Leave aria-hidden out completely.
— Marco Zehe (@MarcoInEnglish) August 2, 2013
0 comments:
Post a Comment