Accessibility is about making websites usable for everyone, benefiting not only people with disabilities but also those using mobile devices or having slow network connections.
Inspired by
This article draws significant inspiration from the “Accessibility” section of MDN Web Docs. It summarizes the practices in my own words and provides examples of both good and bad code.
Always use the right HTML elements for the right purpose
HTML elements come with some default styles and they are keyboard-friendly. For example, users can move between buttons using the Tab key and activate their selection using Space, Return, or Enter.
❌ Bad
<div> Play video </div>
✅ Good
<button> Play video </button>
Care for descriptive content
Descriptive content helps Screen Readers, which are tools for people with visual impairments. These tools change text into speech, letting users hear and navigate the content.
Structure the content with headings, paragraphs, and lists.
❌ Bad
<span style="font-size: 3em">Heading</span>
<br /><br />
This is my content.
<br /><br />
<span style="font-size: 2.5em">Subheading</span>
<br /><br />
This is my subcontent.
✅ Good
<h1>Heading</h1>
<p>This is my content.</p>
<h2>Subheading</h2>
<p>This is my subcontent.</p>
Use clear language
Use full words. Instead of 5-7, write 5 to 7. Avoid abbreviations. Instead of writing Jan, write January.
❌ Bad
<a href="whales.html">click here</a>
✅ Good
<a href="whales.html">Learn more about whales</a>
Update the styling to fit your design, but ensure it still functions as expected
While CSS allows for extensive customization of HTML elements, maintaining user expectations through correct semantics is crucial. Elements should be styled to fit the design, but not to the extent that they no longer behave or appear as expected.
Emphasis elements
The standard bold and italic text conventions are recognizable.
❌ Bad
strong, em {
font-style: normal;
font-weight: normal;
}
✅ Good
em {
font-style: italic;
}
strong {
font-weight: bold;
}
Abbreviations
The recognized styling convention for abbreviations is a dotted underline.
❌ Bad
abbr {
text-decoration: none;
}
✅ Good
abbr {
text-decoration: underline dotted;
}
Links
Standard link conventions include underlining and color changes based on the link’s state. Interaction with the link should provide user feedback, and changes in states should be noticeable. The pointer cursor and outline are essential for accessibility and should not be removed.
❌ Bad
a {
text-decoration: none;
color: black;
cursor: default;
}
a:hover {
color: black;
}
✅ Good
a {
text-decoration: underline;
color: blue;
cursor: pointer;
}
a:hover {
color: red;
}
Form elements
While it’s possible to style form focus/hover states for consistency across browsers or to match page design, it’s crucial not to eliminate the visual feedback form elements receive when focused, as users rely on these cues.
❌ Bad
input:focus {
outline: none;
}
✅ Good
input:focus {
outline: 2px solid blue;
}
Tables
Ensure table headers are prominent (typically bold) and use zebra striping for easier row parsing.
❌ Bad
table {
width: 100%;
}
th {
font-weight: normal;
background-color: white;
}
tr:nth-child(even) {
background-color: white;
}
✅ Good
table {
width: 100%;
}
th {
font-weight: bold;
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
Ensure good contrast between text and background colors
Use online contrast checking tools, like WebAIM’s Color Contrast Checker, to conform to WCAG criteria. High contrast also improves readability on glossy screens in bright environments. Don’t solely rely on color for information; use symbols, like asterisks, for important markers.
❌ Bad
p {
background-color: lightgray;
color: white;
}
✅ Good
p {
background-color: white;
color: black;
}
Use unobtrusive JavaScript
Basic functions should ideally work without JavaScript, using built-in browser functionality where possible. Unobtrusive JavaScript, which enhances rather than builds functionality, is recommended.
As the friends at GOV.UK rightfully say there are plenty of reasons why JavaScript fails. A browser extension could block it, the visitor might be on a flaky network, there could be a DNS issue, … the possibilities are endless. That’s why progressive enhancement should be at the core of your web development
Source: New on the web: How to detect disabled JavaScript in CSS
❌ Bad
JavaScript is directly embedded into the HTML markup through the onsubmit
attribute. If JavaScript is disabled or not supported, the form validation will not work at all.
<form onsubmit="return validateForm()">
<input type="text" id="inputID">
<input type="submit" value="Submit">
</form>
<script>
function validateForm() {
let input = document.getElementById('inputID');
if(input.value === '') {
alert('Form field cannot be empty!');
return false;
}
return true;
}
</script>
✅ Good
We are using unobtrusive JavaScript to validate a form. If JavaScript is disabled or not supported, the form will still submit, but without client-side validation.
document.getElementById('formID').addEventListener('submit', function(e) {
let isValid = true;
let input = document.getElementById('inputID');
if(input.value === '') {
isValid = false;
alert('Form field cannot be empty!');
}
if(!isValid) {
e.preventDefault();
}
});
Limit mouse-specific events
Consider mouse-specific events like mouseover
, mouseout
, dblclick
may not be keyboard-accessible. Pair them with similar keyboard events like focus and blur.
❌ Bad
// Only works for mouse users
element.onmouseover = function() {
// Show zoomed image
};
element.onmouseout = function() {
// Hide zoomed image
};
✅ Good
// Works for both mouse and keyboard users
element.onmouseover = element.onfocus = function() {
// Show zoomed image
};
element.onmouseout = element.onblur = function() {
// Hide zoomed image
};
Use WAI-ARIA features only when necessary
WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) is a specification written by the W3C, defining a set of additional HTML attributes that can be applied to elements to provide additional semantics and improve accessibility wherever it is lacking.
❌ Bad
There is no form tag, and the div doesn’t provide any semantic information about its content. The input field lacks a type, placeholder, or aria-label, making it less accessible and harder for users to understand its purpose.
<div>
<input type="text">
</div>
✅ Good
The form has a clear role attribute of “search”, making it accessible. The input field has the type “search”, a placeholder to guide users, and the aria-label attribute to provide a descriptive label for screen readers.
<form role="search">
<input type="search" name="q" placeholder="Search query" aria-label="Search through site content" />
</form>
❌ Bad
There are no aria-live
or aria-atomic
attributes. This means that screen readers will not announce updates to the content, making it potentially confusing for users with visual impairments.
<section>
<h1>Random quote</h1>
<blockquote><p></p></blockquote>
</section>
✅ Good
The aria-live="assertive"
attribute will ensure screen readers announce updates to the content immediately, and the aria-atomic="true"
attribute ensures the entire contents of the section are read out as one unit.
<section aria-live="assertive" aria-atomic="true">
<h1>Random quote</h1>
<blockquote><p></p></blockquote>
</section>
Create custom audio and video controls
Most browsers do not provide keyboard-accessibility for audio and video controls
. Additionally, the native controls’ styling and functionality vary across different browsers.
❌ Bad
<video src="video.mp4" controls></video>
✅ Good
<div>
<video id="myVideo" src="video.mp4"></video>
<button onclick="playPause()">Play/Pause</button>
</div>
<script>
var myVideo = document.getElementById("myVideo");
function playPause() {
if (myVideo.paused)
myVideo.play();
else
myVideo.pause();
}
</script>
Don’t disable zoom
Avoid using user-scalable=no
or user-scalable=0
in the viewport
, as many users rely on zoom to view website content. If zooming disrupts the user interface, consider an alternative such as a control to increase the text size without breaking the UI.
❌ Bad
<meta name="viewport" content="width=device-width, user-scalable=no">
✅ Good
<meta name="viewport" content="width=device-width">
Summary
Make sure the app is easy to see for people with low vision, color blindness, or who are blind. Also, don’t forget to make it keyboard-friendly. Just remember, accessibility is all about doing your best, not about being perfect 100% of the time, which, let’s be real, is pretty much impossible.
1 comment