Skip to content

Instantly share code, notes, and snippets.

@jonathantneal
Last active November 5, 2023 05:42
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jonathantneal/435478e415bfe4f54d06 to your computer and use it in GitHub Desktop.
Save jonathantneal/435478e415bfe4f54d06 to your computer and use it in GitHub Desktop.
Practical ARIA Tabs: Creating fully accessible tabs

Practical ARIA Tabs

This is a small guide to marking up fully accessible tabs. Consider using PostHTML ARIA Tabs as a practical solution.

The Rules

  1. Add tablist role to the <ul> to indicate it contains tabs.
  2. Add presentation role to each <li> to bypass its list item state.
  3. Add tab role to each <a> to incidate it is an actual tab.
  4. Add href and aria-controls to each <a> to reference its tab panel.
  5. Add id to each <a> as a reference for its tab panel.
  6. Add aria-selected="true" to the active <a> tab.
  7. Add tabpanel role to each <section> to indicate it is a tab panel.
  8. Add id to each <section> as a reference for its tab.
  9. Add aria-labelledby to each <section> to reference its label.
  10. Add hidden to each inactive <section> to indicate it is hidden.

The Markup

<ul role="tablist">
	<li role="presentation">
		<a id="foo-tab" href="#foo" role="tab" aria-controls="foo" aria-selected="true">Foo</a>
	</li>

	<li role="presentation">
		<a id="bar-tab" href="#bar" role="tab" aria-controls="bar">Bar</a>
	</li>

	<li role="presentation">
		<a id="qux-tab" href="#qux" role="tab" aria-controls="qux">Qux</a>
	</li>
</ul>

<section id="foo" role="tabpanel" aria-labelledby="foo-tab">
	...
</section>

<section id="bar" role="tabpanel" aria-labelledby="bar-tab" hidden>
	...
</section>

<section id="qux" role="tabpanel" aria-labelledby="qux-tab" hidden>
	...
</section>

For a fully accessible implementation, this JavaScript should be included somewhere in the front-end.

Citations

Notes

  • Internet Explorer 10 and below require explicit CSS to support [hidden], e.g. [hidden] { display: none; }.
  • <ul> and <li> elements are used for source readability and (to a much lesser extent) progressive enhancement. While both of their implied semantics are overwritten, these elements best represent a collection of items.
@b2whats
Copy link

b2whats commented Dec 27, 2018

Firefox on mac dont work
Links not receive focus

@adodge1
Copy link

adodge1 commented Jan 17, 2019

<ul role="tablist">
 <li role="presentation"><a href="#section1" tabindex="0" role="tab" aria-controls="section1" aria-selected="true">Section 1</a></li>
 <li role="presentation"><a href="#section2" tabindex="-1" role="tab" aria-controls="section2">Section 2</a></li>
 <li role="presentation"><a href="#section3" tabindex="-1" role="tab" aria-controls="section3">Section 3</a></li>
</ul>
<section id="section1" role="tabpanel">...</section>
<section id="section2" role="tabpanel" aria-hidden="true">...</section>
<section id="section3" role="tabpanel" aria-hidden="true">...</section>

@kajyr
Copy link

kajyr commented Jan 18, 2019

The tab a element should instead be a button, since it's not linking to a different page.

@DonGissel
Copy link

The tab a element should instead be a button, since it's not linking to a different page.

Actually, a-tags are perfectly valid here, since they can also signify jumping to different anchors/sections on the page. A tab would constitute a different section, even though it's more or less in the same space as the others. So semantically, it makes perfect sense. :-)

@pbb72
Copy link

pbb72 commented Mar 4, 2019

Actually, a-tags are perfectly valid here, since they can also signify jumping to different anchors/sections on the page. A tab would constitute a different section, even though it's more or less in the same space as the others. So semantically, it makes perfect sense. :-)

Not really. While technically the a elements are linked to sections on the page, functionally they are showing/hiding content. From a functionality perspective, I agree buttons are more appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment