Skip to main content

Web Accessibility Quick Guide

Welcome to my Quick Guide!

This is a guide focused on "old-style" websites, like those commonly found here on Neocities. There are a ton of guides on web accessibility out there (and I've linked to several of them on my Resources page!), but most of them are written with "modern and conventional" websites in mind. This guide is a work-in-progress, and I plan to add more sections over time!

This is not a comprehensive guide. My goal is to give you simple accessibility tips that you can use without wrecking your vision for your webpage. Small changes can make a really big difference.

I'm also not here to tell you that you have to do everything on this page. If you can only do one thing, that's better than doing zero things! This is about people, not compliance.

Broadly speaking, the guide is divided into two sections: tips that can be applied without changing the visual design at all, and tips that may require changing the design slightly. Of course, these tips will not cover every scenario. I recommend reading the glossary if any words or acronyms I use are unfamiliar.

Now, without further ado...

Glossary (click to expand)
ARIA
Stands for Accessible Rich Internet Applications . It's a set of tools for making webpages more accessible, mostly for people who use screen readers. The most commonly used tools for simple websites are labels and roles.
ARIA label
ARIA labels are attributes (defined below) that you can use to provide extra information to screen readers. Things like images and buttons can be given a label to describe their purpose.
ARIA role
Like labels, ARIA roles are also attributes that you can add to your HTML elements. You can give any HTML element an ARIA role. They help screen readers know what kind of content they are "looking" at. For example, using <div role="navigation"> will tell a screen reader that the <div> is a navigation menu.
Attribute
Used to add information or functions to an HTML element. For example, in a line like <img src="example_image.jpg">, src is an attribute that modifies the <img> element.
Element
The technical term for the HTML "building blocks" that you use to code a webpage. Things like <p>, <img>, and <div> are elements.
Interactive element
Elements that can be, well, interacted with. Things like links, buttons, and checkboxes. If you can click on it and it does something, it's interactive.
Keyboard focus ∕ focusable
You can move between interactive elements on a page using the tab key. Use tab to move forward and shift+tab to move backward. Most elements can be interacted with using either enter or space. Usually, an outline will appear around whatever element you're "standing" on. That element is called your current keyboard focus. "Focusable" means that focus can be moved to an element by tabbing to it.
Media query
A CSS tool that can apply different styles based on the device (computer, phone, etc.) being used to view a webpage. They can check things like screen size and system settings.
Screen reader
A program that "reads" the contents of a webpage out loud. They're commonly used by blind people and by people who can't see very well.
Semantic elements ∕ semantic markup
HTML elements that clearly describe their function, not just how they look. Elements like <div> and <span> are not semantic; you can't tell what they're "for" just by the HTML tag. <nav> is a semantic element: you immediately know that anything inside that tag is part of a navigation section.

Part One: Invisible Fixes

Page Language

This one's super easy! The <html> element at the top of your page should have a valid lang attribute.

If your page is in English, a simple <html lang="en"> will suffice. If you change languages in the middle of a page for whatever reason (say, to use an idiom in another language), you should also wrap that in another element (such as a <span>) and give that its own lang attribute as well.

Why does my page need a lang attribute? (click to expand)

Screen readers use the lang attribute to decide which language's pronunciation rules to apply. If no lang is specified, the screen reader will use the default language its user set, which may or may not be English. If a screen reader tries to read text in one language using the pronunciation rules of another, the result is garbled nonsense! Imagine trying to read English, but pronouncing every letter as you would in Spanish. It would be almost impossible to understand.


Landmarks

Landmarks are used by screen reader users to figure out what section of a webpage they are in. People who use screen readers will often pull up a list of landmarks on the page and jump between them. Modern HTML has several types of landmarks built in, including <header>, <nav>, <main>, and <footer>, among others.

If you already have a layout that doesn't use those landmarks, you can also "retrofit" elements of your page using ARIA. For example, using <div role="navigation"> will add a navigation landmark. You can put your navigation links inside of that <div> and it will be the same as putting them in a <nav> element. Note, though, that using built-in (or "native") HTML landmarks is preferable to using ARIA.

Here's a table with a few common HTML landmarks and their corresponding ARIA roles. There are more landmarks than I've listed here; these are just the most common ones:

HTML5 ARIA Role
<header> role="banner"
<nav> role="navigation"
<main> role="main"
<footer> role="contentinfo"

Semantic Markup

People with sight can identify the purpose of elements on a page just by looking at them. If something looks like a heading, we can easily tell that it's a heading. If something looks like a list, we can easily tell that it's a list, et cetera.

People who use screen readers can't identify elements of a page by looking at them. That's why semantic markup is important: it tells screen readers what an element is and what it's for. Non-semantic elements like <div> and <span> convey no information. That doesn't mean you should never use these elements! It's just good practice to avoid them when appropriate semantic alternatives are available.

Anything that functions as a heading should be marked as a heading (<h1>, <h2>, <h3>, etc). Anything that functions as a list should be marked as a list using <ul> or <ol> and <li> elements. Landmarks (described above) are also semantic. There are a lot of other semantic elements, but headings, lists, and landmarks are probably the most important.

It's also important to not use semantic elements purely for styling. If you just want big bold text, you shouldn't use a heading tag. Screen reader users will often pull up a list of headings on a page and use them to navigate quickly. Text that's semantically marked as a heading but isn't actually a heading can be very confusing! In this case, using CSS is better.


Keyboard Focus

Every interactive element on your webpage needs to be focusable using a keyboard. Most interactive HTML elements are focusable "out of the box". If you're using custom JavaScript, you may have to do a bit more work. Note: Elements that aren't interactive (headings, paragraphs, etc) should not be focusable.

By default, using tab will focus elements in the order they're written in the HTML. You want to make sure that page elements get tabbed to in an order that makes sense. That usually means left-to-right, top-to-bottom. Make sure to avoid cases where the focus gets "stuck" on an element. That's called a keyboard trap. If someone is stuck in a keyboard trap, they won't be able to tab to any other element on the page!

Most browsers will default to showing a blue or dotted outline around the currently-focused element. Depending on your color scheme, that can be pretty hard to see. It's recommended (but not required) to create an extremely obvious style for keyboard focus using CSS.

At a minimum, please never remove the default focus styling (e.g. by setting a:focus {outline: none;}) without replacing it. If you do that, keyboard users won't have any way to tell what element they're currently focused on. That can make your website nearly impossible to use.

What about tabindex? (click to expand)

The tabindex attribute lets you manually change the tab order. Giving an element a tabindex of 0 makes sure that it is keyboard focusable. Using a tabindex of -1 will make it not focusable, which is sometimes useful.

You can also give things a positive tabindex (greater than 0). The tab order will follow the numbering: first 1, then 2, etc. Any element with a positive tabindex will come first in the tab order, before anything that doesn't have a positive tabindex. This means that if ANY interactive element on your page has a positive tabindex, ALL of them have to.

In 99.999% of circumstances, you shouldn't use a positive tabindex. Screen readers typically read things in the order they're written in the HTML. If you manually change the tab order of elements on the page, it can make the tab order not match the order they're read by a screen reader. That can make webpages very confusing and hard to use. Tabindexes are also really hard to maintain because you'll have to change them all every time you add something new to your website.


Tables

Tables that are used to display data or information should have proper semantic markup. This can get complicated, and there are plenty of guides on it, so I won't go into detail here. The most important thing is to use an actual <table> element instead of "faking it" using <div>s. Use <th> for table headers and <td> for regular table cells.

Important: If you use <table> elements just for arranging things on a page (not for displaying data), they should not use data table markup. That means you need to avoid <caption>, <summary>, <th>, scope, and headers. They should also be given an ARIA role atrribute: <table role="presentation">. The "presentation" role makes screen readers ignore the table and treat it as regular text instead.


Image Alt Text

Still working on this section!


Part Two: Somewhat Visible Changes

Page Title

This one won't change the design of your page, but it will affect how its title is displayed in a browser tab. Every page should have a meaningful <title>. This should be placed inside the page's <head>. If the URL changes, the title should change, too. Try to make your titles unique and short. If you use a title style (like I do) that includes both the title of the page and the title of your website, you should place the title of the page first. That makes moving between browser tabs much simpler.


Navigation menus should be put in a <nav> element or a <div role="navigation">. It's a good idea to use a list (<ul> or <ol>) inside the <nav> for your navigation links. That will make them easier to use with a screen reader.

If you have a navigation bar at the top of the page (or a navigation sidebar that comes before the page content in the HTML), it's a good idea to include a keyboard-functional "skip navigation" link at the very top. You can make it completely invisible unless focused with a keyboard. This website has one, and you would never know it unless you use a keyboard! Just refresh the page and then press tab to see mine. Making a hidden link can be a bit complicated, so I recommend following a tutorial online. (I might make one later.)

Why add a "skip navigation" link? (click to expand)

The point of a "skip navigation" link is to let keyboard users jump straight to the main content of your page. It's basically there to make your website less annoying to use, especially if you have a long list of navigation links. You wouldn't want to have to tab through the entire navigation list every time you refresh or go to another page.


Links that have visible text should have meaningful text. Screen reader users can pull up a list of links on a webpage and use them to find their way around. Links with text like "Click Here" or "Learn More" make no sense out of context.

There are other ways to provide meaningful labels for links if needed. Link tags (<a>) that contain only an image element will read the alt text of the image to someone using a screen reader. If you absolutely have to use non-descriptive link text, you can provide alternate link text with ARIA. Using the aria‑label attribute will leave the visual text untouched and give alternative text to screen readers.

Bad Example: <a href="https://example.com">Click Here</a>
Good Example: <a href="https://example.com">Example Website</a>
Decent Alternative: <a href="https://example.com" aria‑label="Example Website">Click Here</a>


Flashing Images

Animations that flash more than three times per second can cause seizures. I want to be perfectly clear: If you choose to use rapidly-flashing GIFs or animations, you take on the responsibility for making sure that no one gets hurt.

There are many ways to handle this, and they all have pros and cons. Here are a few suggestions, ranked by my opinion of best to worst:

  1. Don't use rapidly-flashing images at all. That's the safest option, and it's what I recommend.
  2. Keep them small. A tiny blinkie could cause a seizure, but it's extremely unlikely to.
    Important caveat: Having a bunch of small blinkies on the same page is still dangerous.
  3. Keep the flashing images turned off by default and add a toggle button to turn them on. You'll have to make the button text very clear. There should be no question about what the button does.
  4. Put the flashing images behind a "flash warning" page. This can either be the homepage of your site or put in as a "gateway page" when people click on certain links. That's definitely better than nothing, but there is a big problem with it. People might come directly to "flashy" pages through a link on another site, completely bypassing your warning. For that reason, I really don't recommend using a warning page as your only safety measure.

Animation

Some people are sensitive to motion on the screen. Nausea and headaches are the most common problems.

Most devices have "reduced motion" settings that turn off animations. You can tap into this using the prefers-reduced-motion media query. Here's a CSS snippet that disables CSS animations, transitions, and GIFs when the setting is turned on:

Media Query Example (click to expand)
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation: none !important;
        transition: none !important;
    }

    /* Give your GIFs an "animated" class and hide them */
    img.animated {
        visibility: hidden;
    }
}

Note that if you use this code to hide animated GIFs, they won't show up at all. If you'd rather "pause" them, there are a number of ways to do it! I have a "Pause GIFs" button tutorial that shows what I use. That page also has links to some of the other methods out there.

Some motion-sensitive people don't use this setting. They might not know it exists, it might not work on their device, or they might only want to pause some animations and not others. Because of that, it shouldn't be the only thing you use to hide rapidly-flashing images (see the "Flashing Images" section above).

A couple final notes for more advanced coders: Anything on the screen that moves (including autoplay, JavaScript animations, marquees, carousels, etc.) should be pausable. If you use parallax or smooth scrolling, you'll also need to add code to turn those off. You should know that parallax effects are my worst enemy. If you use them without a way to turn them off, I will hunt you down. (jk lol)


Back to Top