Website fixes: accessibility

A site everyone can use.

Accessibility is about people being able to use your site however they browse: with a screen reader that reads the page aloud, with a keyboard instead of a mouse, or zoomed right in. These entries refer to WCAG, the Web Content Accessibility Guidelines, and WCAG 2.2 at level AA is the common target.

Check your site freeAll website fixes

Images have no alt text

What it means. Alt text is a short description of an image, kept in its alt attribute. Screen readers (software that reads a page aloud for people who are blind or have low vision) read it in place of the picture, and browsers show it if the image doesn't load. These images have no alt attribute at all.

Why it matters. Without it, many screen readers read out the file name instead ("IMG underscore 4021 dot jpg") or skip the image without a hint of what it showed. When the image is a link or button, such as a logo, people can't tell what it does. Google also uses alt text to understand images. This is WCAG success criterion 1.1.1 Non-text Content, level A.

How to fix it. Give every image an alt attribute that fits its job. The W3C's alt decision tree helps with tricky cases.

  • An image with information in it: describe what matters in a few words, such as alt="Finished bathroom with grey floor tiles".
  • An image that's a link or button: say where it goes or what it does, such as alt="Smith Plumbing home".
  • A purely decorative image: use an empty alt="" so screen readers skip it. Leaving the attribute out isn't the same.
  • WordPress, Wix, Squarespace and Shopify have an alt text box in each image's settings. Images placed by a theme, like a logo, may need the theme's settings.

How the check spots it: It counts each <img> tag in the HTML with no alt attribute; an empty alt="" counts as a deliberate choice. Three or more missing make it Worth fixing; fewer, Nice to have. Google's Lighthouse test checks the same thing in a real browser, including images added by scripts, and if it finds them too, the report keeps whichever rating is higher, which for missing alt text is usually Fix first. Its result is listed here too. For alt text that's there but unhelpful, see alt text that says nothing useful.

Form fields have no label

What it means. A label is the text that says what a field is for, such as "Your email", connected to the field in the page's code. These fields have none, and often rely on placeholder text (the grey hint inside the box) instead.

Why it matters. A screen reader announces an unlabelled field as something like "edit text", so people filling in your enquiry form have to guess what goes where. Some browsers and screen readers read a placeholder as a fallback, but it vanishes as soon as someone starts typing. A connected label also makes its text tappable, a bigger target on a phone. WCAG covers this in 3.3.2 Labels or Instructions and 4.1.2 Name, Role, Value, both level A.

How to fix it. Give each field visible text in a <label> tag whose for attribute matches the field's id, or wrap the field inside the label. The W3C's forms tutorial shows both.

  • A connected pair: <label for="email">Email</label> then <input id="email" type="email">.
  • Where there's no room for visible text, such as a lone search box, an aria-label gives the field a name screen readers can say.
  • Form plugins and builders usually add labels. If yours has a "hide labels" or "placeholders only" option, switch it off and check again.

How the check spots it: It reads each <input>, <select> and <textarea> in the HTML, leaving out hidden fields and buttons. A field counts as labelled if it sits inside a <label>, a <label for> points at its id, or it has an aria-label, aria-labelledby or title. A placeholder doesn't count. Three or more unlabelled fields make it Worth fixing; fewer, Nice to have. Google's Lighthouse test checks labels in a real browser too; its result is listed here, and the report keeps whichever rating is higher.

The page stops people zooming in

What it means. The viewport tag, a line in the page's <head>, tells phones how to size the page. Here it includes user-scalable=no, or a maximum-scale that limits how far people can pinch to zoom.

Why it matters. Plenty of people zoom to read small print or look closely at a photo, not only people with low vision. If they can't, your prices or phone number may be out of reach. WCAG 1.4.4 Resize Text (level AA) asks that text can be enlarged to 200% without losing content, and blocking zoom works against it. Safari on iPhone ignores the setting, but many Android browsers obey it unless the person switches on an accessibility option.

How to fix it. Change the tag to <meta name="viewport" content="width=device-width, initial-scale=1">, without user-scalable or maximum-scale. The setting was often added to stop iPhones zooming in when someone taps a form field; Safari does that when the field's text is under 16 pixels, so 16px form text solves it without blocking zoom. On WordPress the tag usually comes from the theme, and on Shopify it's in the theme's code. On Wix and Squarespace the platform writes it, so ask their support.

How the check spots it: It reads the <meta name="viewport"> tag and flags user-scalable=no or user-scalable=0, or a maximum-scale below 2, matching the 200% in WCAG 1.4.4. Pages with no viewport tag get a separate finding about phones. Google's Lighthouse test makes a similar check, and its result is listed here too.

Buttons have no readable name

What it means. These buttons have no text, no alt text on an image inside, and no aria-label or title. They're usually icon buttons: the three-line menu button on phones, a search magnifier, a close ×, slider arrows or a play button.

Why it matters. A screen reader announces each one as just "button", so people have to press it to find out what it does. If the phone menu button has no name, someone using a screen reader may struggle to reach the rest of your site. WCAG 4.1.2 Name, Role, Value (level A) asks that every button has a name.

How to fix it. Add an aria-label that says what the button does, such as <button aria-label="Open menu">. Name the action, not the picture: "Close", not "X". Text that's hidden from view but still read out works too; WordPress themes usually have a style for it, often called screen-reader-text. These buttons almost always come from the theme or a plugin, so check for an update first, then ask whoever maintains it.

How the check spots it: It counts the <button> tags in the HTML with no text inside (alt text on an image inside counts) and no aria-label, aria-labelledby or title. It only looks at <button> tags, not links or other elements styled as buttons. Google's Lighthouse test checks button names in a real browser too, and its result is listed here.

The page's language isn't set

What it means. The <html> tag at the top of a page should carry a lang attribute naming its language, such as lang="en-AU" for Australian English. This page has none, or it's empty.

Why it matters. Screen readers use it to pick a voice and pronunciation. Without it they use the visitor's default language, so someone whose device is set to Vietnamese may hear your English read with Vietnamese pronunciation. Browsers use it to offer translation and for things like hyphenation. WCAG 3.1.1 Language of Page (level A) asks for it on every page.

How to fix it. Change the opening tag to <html lang="en-AU">, or lang="en". The W3C explains more in declaring language in HTML. WordPress prints it from the Site Language in its general settings, as long as the theme includes it. Wix, Squarespace and Shopify set it from the site's language settings; if it's still missing, ask the platform's support or the theme's developer.

How the check spots it: It reads the lang attribute on the page's <html> tag and flags it when it's missing or empty. It doesn't check that the language matches the page's words. A code in the wrong format is covered in the page's language code isn't valid. Google's Lighthouse test checks this too, and its result is listed here.

Sound starts playing by itself

What it means. The page has an audio or video player set to start on its own (the autoplay attribute), and it isn't muted.

Why it matters. Sound that starts unexpectedly startles people, embarrasses them in a quiet office or on a train, and talks over screen readers. Many people simply close the tab. WCAG 1.4.2 Audio Control (level A) requires a way to pause or stop any sound that plays automatically for more than three seconds. Browsers also often block sound that starts by itself, so the player may not start at all.

How to fix it. Let people choose to press play.

  • A background video where the sound doesn't matter: add muted, plus playsinline so iPhones play it in place. Browsers generally allow muted video to start by itself.
  • A video or music people should hear: remove autoplay and add controls.
  • Moving video that starts by itself and runs over five seconds also needs a way to pause it, under WCAG 2.2.2 Pause, Stop, Hide. Page builders' video blocks usually have switches for this.

How the check spots it: It looks in the HTML for <audio> tags with autoplay, and <video> tags with autoplay but no muted. It can't hear whether a video has a soundtrack, so a silent video without muted is flagged too; adding muted clears it. Players started by a script, and YouTube or Vimeo embeds, aren't seen.

Alt text that says nothing useful

What it means. These images have alt text, the description read aloud in place of the picture, but it describes nothing: a file name like "IMG_4021.jpg", a single word like "image" or "banner", a number, a phrase starting "picture of", or more than 150 characters.

Why it matters. A blind visitor hears "DSC 0042 dot jpg" and learns nothing about your work. "Image of" wastes words, because screen readers already say it's an image. Very long alt text is hard to take in by ear. WCAG 1.1.1 Non-text Content (level A) asks for text that does the same job as the image, which a file name doesn't.

How to fix it. Rewrite each one to say what matters about the image on this page, in a few words: "Our van outside a house in Brunswick", not "van.jpg". Use alt="" for decoration. File names often end up as alt text when an upload tool fills it in automatically, so check new images' settings after uploading. Images with no alt text at all are covered in images have no alt text.

How the check spots it: It flags alt text that is only a generic word (image, photo, picture, graphic, icon, banner, header, hero, slider and the like), only a number or punctuation, looks like a file name (ending in .jpg or .png, say, or starting like IMG_1234 or DSC 0042), begins "image of", "photo of" or similar, or runs over 150 characters. It can't tell whether a normal-looking description is accurate.

Linked pages have images without alt text

What it means. On one or more pages linked from yours, some images have no alt attribute at all. Alt text is a short description of an image, read aloud by screen readers and shown if the image doesn't load.

Why it matters. Without it, a screen reader may read out the file name, like "IMG_4021.jpg", and a blind visitor misses what the picture shows. WCAG, the web's accessibility standard, asks for a text alternative for every meaningful image (success criterion 1.1.1, Level A). Google also uses alt text to understand images.

How to fix it. Describe what matters in each picture: "Our van outside a house in Brunswick". Give purely decorative images, like dividers and background patterns, an empty alt (alt="") so screen readers skip them.

  • WordPress: the media library has an alternative text field for each image. Wix, Squarespace and Shopify have one in each image's settings.
  • An image that's part of a template, like a footer logo, only needs fixing once, in the template.
  • W3C explains the rule in Understanding non-text content.

How the check spots it: it counts <img> tags with no alt attribute in the HTML of up to four pages linked from the checked page (see broken pages). An empty alt="" counts as present, since that's right for decoration. It doesn't judge whether the text is any good.

Headings skip levels or are empty

What it means. Headings come in six levels, <h1> to <h6>, and work like an outline: one main heading, sections under <h2>, sub-sections under <h3>. On this page a heading jumps down more than one level (an <h2> followed by an <h4>, say), or a heading has nothing in it.

Why it matters. Screen readers list headings so people can jump to the section they want, and the levels show how sections fit together. A skipped level makes people wonder what they missed; an empty heading is announced as "heading" and nothing else. WCAG doesn't strictly forbid skipping a level, but 1.3.1 Info and Relationships (level A) asks that the structure people see is in the code, and 2.4.6 Headings and Labels (level AA) asks headings to describe their topic, which an empty one can't.

How to fix it. Choose each heading's level by its place in the outline, not its size, and set the size with the theme's styles. Remove empty headings, which page builders sometimes leave as spacers. The W3C's headings tutorial has examples.

How the check spots it: It goes through every <h1> to <h6> in the HTML in order and flags any step down of more than one level; stepping back up is fine. It also counts headings with no text (alt text on an image inside counts as text). Google's Lighthouse test has its own heading order check, and its result is listed here too. More than one <h1> is covered in more than one main heading.

Embedded frames have no title

What it means. An iframe is a window in your page showing something from elsewhere: a Google Map, a YouTube video, a booking calendar or a reviews feed. These have no title attribute saying what they are.

Why it matters. A screen reader announces an untitled frame as just "frame", sometimes with its address, so people can't tell your map from your booking form without going into each one. WCAG 4.1.2 Name, Role, Value (level A) asks that each frame has a name, and a title is the standard way to give it one.

How to fix it. Add a short title saying what's in the frame: <iframe src="…" title="Map of our Brunswick workshop">. When you paste embed code from YouTube, Google Maps or a booking service, add or edit the title before saving. A generic one like "YouTube video player" is better than none; naming the video is better still. If a plugin creates the frame, look for a title setting.

How the check spots it: It flags each <iframe> in the HTML that has an address but no title, or an empty one. It can't see frames a script adds later, but Google's Lighthouse test, which runs in a real browser, has its own frame title check, and its result is listed here too.

The page has no main landmark

What it means. <main> is an HTML tag that wraps the page's own content, apart from the header, menu, sidebar and footer. Tags like this are called landmarks: signposts screen readers can jump between. This page has no <main>.

Why it matters. On every page, screen reader and keyboard users meet the same logo, menu and links before reaching what they came for. With <main>, screen reader users can skip straight to the content in one keystroke. WCAG 2.4.1 Bypass Blocks (level A) asks for a way to skip blocks repeated on every page; landmarks are one recognised way, and a "Skip to content" link is another.

How to fix it. Wrap the content between the header and footer in one <main> tag. On WordPress this lives in the theme's templates; many current themes include it, so an update or a newer theme may fix it. On hosted builders the platform writes the page structure, so raise it with their support. A "Skip to content" link that jumps to <main> helps keyboard users too. The W3C's page regions tutorial shows the pattern.

How the check spots it: It looks for a <main> tag in the HTML, and only on pages with at least 150 words. An element with role="main" isn't counted, though screen readers treat it the same; if your theme uses that, switching to <main> clears the finding.

More than one main heading (H1)

What it means. <h1> is meant for the page's main heading, the one that says what the page is about. This page has several. Often a theme makes the logo or site name an <h1> as well as the page title, or a page builder sets several big headings as <h1>.

Why it matters. It's a convention, not a rule: WCAG doesn't require a single <h1>, and Google doesn't either. But one clear main heading makes the page easier to scan and its outline easier to follow. Screen reader users can jump to the <h1> to find where the content starts, and if the logo is one too, they land in the wrong place first.

How to fix it. Keep <h1> for the page's title and make the others <h2>, or lower to fit the outline (see headings skip levels). Change sizes with styles, not levels. If the logo is an <h1> on every page, look for a theme setting; otherwise it's a small template change.

How the check spots it: It counts the <h1> tags in the HTML, including empty ones, and lists up to three. Because it reads the HTML, not the screen, a heading hidden by the theme or shown only on phones still counts. A page with no <h1> gets a separate finding under Search.

The page's language code isn't valid

What it means. The <html> tag has a lang attribute, but its value isn't a standard language code, such as en for English or en-AU for Australian English. Common mistakes are a language name (lang="English") or an underscore (en_AU, the way some software writes a locale).

Why it matters. Screen readers and translation tools that can't read the code may ignore it, which has the same effect as no language at all: the screen reader falls back to its default voice and pronunciation. WCAG 3.1.1 Language of Page (level A) needs a code software can understand, not just the attribute.

How to fix it. Use lang="en-AU" or lang="en". Codes follow a standard called BCP 47, explained in the W3C's choosing a language tag. An underscore often comes from a theme or plugin printing the site's locale setting as it is; an update or a small theme fix sorts it out.

How the check spots it: It checks the format only: two or three letters, optionally followed by hyphenated parts of one to eight letters or digits. A well-formed code that's wrong for the page, like lang="fr" on an English page, isn't caught. A missing code is covered in the page's language isn't set. Google's Lighthouse test checks for valid codes too, and its result is listed here.

Elements jump the keyboard order

What it means. Keyboard users move through links, buttons and form fields with the Tab key, in the order they come in the page. The tabindex attribute changes that, and a value above 0, such as tabindex="1", pulls an element to the front of the queue.

Why it matters. Everything with a positive tabindex is visited first, ahead of the menu and content around it, and then the keyboard jumps back to the top. People tabbing through land in places that make no sense and lose track of where they are. WCAG 2.4.3 Focus Order (level A) asks that the order keeps the page's meaning. The numbers are fragile too: later changes to the page leave them out of step.

How to fix it. Remove tabindex from links, buttons and fields, which are reachable already, or change positive values to tabindex="0", which keeps something in its natural place. To make something come earlier, move it earlier in the code. Some form plugins and older widgets add numbered values; look for a setting or an update. MDN's tabindex reference has the details.

How the check spots it: It counts the tags in the HTML with a tabindex above 0. tabindex="0" and tabindex="-1" are normal and aren't counted.

Keep exploring