11.6 Accessibility Best Practices for Links and Buttons
1. Use the Right Element Semantically
-
<a> for navigation: Use
<a>when the control moves the user to another resource or URL. -
<button> for actions: Use
<button>for actions on the current page (e.g., opening dialogs, submitting forms, toggling state).
2. Provide Clear, Descriptive Text
-
Link text or button text should describe its purpose out of context.
Avoid generic phrases like “Click here” or “Learn more.” -
If the visible text isn’t descriptive enough, add an accessible name with
aria-labeloraria-labelledby.
Example: Descriptive link
<a href='/report'>Click here</a> <a href='/report'>View the annual financial report (PDF)</a>
Example: icon-only button with accessible name
<button aria-label='Close dialog'>
<svg role='img' aria-hidden='true' width='16' height='16'>
<use href='#icon-close'/>
</svg>
</button>
3. Keyboard Accessibility
-
Ensure focusable elements (
<a>,<button>, or any element withtabindex='0') are reachable by Tab. -
Avoid using
tabindex>0on too many elements. Prefer native controls when possible. -
If you convert a non-interactive element (e.g.,
<div>) into a button or link:- Give it
role='button'orrole='link'. - Add
tabindex='0'so it’s in the tab order. - Listen for both
keydownEnter and Space keys.
- Give it
Example: custom link
<div role='link' tabindex='0' onclick='goToSection()'
onkeydown='if(event.key==='Enter'){ goToSection(); }'>
Jump to Overview
</div>
4. Visible Focus Indicator
Rely on the browser’s default focus outline so users navigating by keyboard know which element is active.
Example: focused link/button
<a href='#section2'>Read more details</a> <button>Submit form</button>
5. ARIA Attributes for Enhanced Semantics
- aria-label: Adds an accessible name if visible text is insufficient.
- aria-labelledby: References other element IDs for the name.
- aria-pressed: Indicates toggle buttons state (
trueorfalse). - aria-disabled: Marks non-interactive state, in addition to
disabled.
Example: toggle button
<button aria-pressed='false' id='muteBtn'>
Mute sounds
</button>
<script>
var btn = document.getElementById('muteBtn');
btn.addEventListener('click', function() {
var pressed = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', String(!pressed));
btn.textContent = pressed ? 'Mute sounds' : 'Unmute sounds';
});
</script>
6. Indicating External Links
For links opening in a new window or to external sites:
- Add
target='_blank'andrel='noopener noreferrer'. - Indicate it in the link text or include visually hidden text with
aria-label.
<a href='https://external.com' target='_blank' rel='noopener noreferrer'
aria-label='External site (opens in new tab)'>
External Resource
</a>
7. Disabled State
Use the native disabled attribute on <button>.
For links, manage disabling via scripting and aria-disabled='true'.
<button disabled>Submit</button>
<a href='/next-step' aria-disabled='true' tabindex='-1'>
Next step
</a>
8. Skip Redundant or Repetitive Links
When multiple links point to the same destination in one context (e.g., table rows), consider:
- Making only the row container clickable.
- Ensuring only one accessible name per link.
<table>
<tr tabindex='0' role='link' onclick='location.href='/details/1''>
<td>Item 1</td>
<td>Description 1</td>
</tr>
<!-- No extra link inside, so keyboard users won’t tab multiple times -->
</table>
9. Testing and Validation
- Use screen readers (NVDA, VoiceOver) to verify link/button names and roles.
- Audit with accessibility tools (axe, Lighthouse) for missing names or roles.
- Check keyboard-only navigation: Tab, Shift+Tab, Enter, Space, and Esc.
By following these guidelines—choosing the correct HTML element, providing descriptive text and ARIA attributes, ensuring keyboard accessibility and visible focus, and correctly managing disabled states—you make links and buttons usable by all users, including those relying on assistive technologies.
Leave a Reply
You must be logged in to post a comment.