Buttons & Links

It's very easy to lose implicit semantic meaning of buttons and links, or to forget to provide it for other elements that need to be interactive.

The Problem

Expected keyboard controls and screen reader output are omitted without proper semantics.

The Solution

Ensure semantic meaning is provided in cases where it is not implicit. Four examples below.

Related Articles

Live Examples

Before illustrates the problem, After illustrates the solution. Click the header to see it larger in a modal.

before

after

Code Comparison

Code diff between the before and after examples above to show the changes necessary. To copy the final source click on the 'after' path link before the diff.

source

Comparing /examples/semantics/buttons-and-links/before/index.html to /examples/semantics/buttons-and-links/after/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Accessibility Solutions - Semantics - Buttons and Links</title>
<link rel="stylesheet" href="../../../presentation.css">
<link rel="stylesheet" href="buttons-and-links.css">
</head>
<body>
<h1>Buttons and Links example</h1>
<h2>Implicit Semantic Meaning</h2>
<p>We lose implicit semantic meaning when using a tag other than <code>&lt;a&gt;</code> or <code>&lt;button&gt;</code> for interactive controls.</p>
<
spabutton class="btn span-btn">This is a span pretending to be a button</spabutton>

<h2>Keyboard Triggering</h2>
<p>Links are triggered with the Enter key, buttons are triggered with the Space or Enter key. Links with a button role should account for that.</p>
<a href="#anchor" class="btn link-btn" role="button">This is a link with a button role</a>

<h2>Pointer Cursor</h2>
<p>The pointer cursor shouldn't be on anything but links, because of their weak affordance. <sup>[<a href="https://www.w3.org/TR/CSS21/ui.html#propdef-cursor">1</a>]</sup></p>
<button class="btn pointer-btn">This is a button, not a link</button>

<h2>Last Resort</h2>
<p>There are times when you absolutely can't use <code>&lt;a&gt;</code> or <code>&lt;button&gt;</code>, in these cases you must provide the semantic meaning and functionality.</p>
<div class="btn div-btn
" role="button" tabindex="0">This is a div pretending to be a button</div>

<script src="buttons-and-links.js"></script>
</body>
</html>

styles

Comparing /examples/semantics/buttons-and-links/before/buttons-and-links.css to /examples/semantics/buttons-and-links/after/buttons-and-links.css

.btn {
border: 1px solid #333;
border-radius: 5px;
color: #333;
cursor: pointer;
font-size: 16px;
font-weight: normal;
padding: 8px;
}

.div-btn {
display: inline-block;
}

.link-btn {
color: #333;
text-decoration: none;
}

.link-btn:visited {
color: #333;
}

.span-btn {

cursor: default;

display: inline-block;
}

javascript

Comparing /examples/semantics/buttons-and-links/before/buttons-and-links.js to /examples/semantics/buttons-and-links/after/buttons-and-links.js

(function() {
'use strict';

var divBtn = document.querySelector('.div-btn');
var linkBtn = document.querySelector('.link-btn');
var pointerBtn = document.querySelector('.pointer-btn');
var spanBtn = document.querySelector('.span-btn');

// Set up example event listeners and click events
divBtn.onclick = clickEvent;
linkBtn.onclick = clickEvent;
linkBtn.addEventListener("keydown", activateEvent);
pointerBtn.onclick = clickEvent;
spanBtn.onclick = clickEvent;
spanBtn.addEventListener("keydown", activateEvent);

function clickEvent() {
alert("Hey, you clicked a button-like element!");

}

function activateEvent(e) {
if ( e.keyCode === 13 || e.keyCode === 32 ) {
e.target.click();
}

}
}());