Links and buttons Rule

Links must have text a screen reader can announce link-name

Every link needs text that a screen reader can announce and a voice control user can say. Visible text is best. An icon-only link, or an image link with no alt text, has no name at all, so it is announced as just 'link', and the page's list of links gives no clue where each one goes.

Websight reports this as Links must have discernible text

Who it affects

Someone who is blind, tabbing through an online florist's footer hears link, link, link for the Instagram, Facebook and Pinterest icons and cannot tell them apart.

Someone using voice control (Dragon, or Voice Control on a Mac) has no word to say to open an icon link, so has to fall back to a numbered grid over every clickable thing on the page.

Someone who reads the page through a screen reader's links list sees a list full of empty entries and 'Read more' and has no sense of where any of them lead.

Broken versus fixed

Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.

Broken

A screen reader announces: link, link, link. Nothing says which one is Instagram and which is Facebook.

Fixed

Announced: link, Bloom and Stem on Instagram. Then: link, Bloom and Stem on Facebook.

Show the markup behind both examples
Broken
<style>body{font-family:system-ui;margin:0;padding:16px;background:#f6f3ee}.social{display:flex;gap:12px;align-items:center}.ico{display:inline-block;width:36px;height:36px;border-radius:50%;background:#8a5a7a}.ico.fb{background:#4a6fa5}.ico.pin{background:#b23a3a}</style>
<p style="margin:0 0 8px"><strong>Bloom and Stem</strong>, florist, Norwich</p>
<div class="social">
  <a href="#instagram" class="ico"></a>
  <a href="#facebook" class="ico fb"></a>
  <a href="#pinterest" class="ico pin"></a>
</div>
Fixed
<style>body{font-family:system-ui;margin:0;padding:16px;background:#f6f3ee}.social{display:flex;gap:12px;align-items:center}.ico{display:inline-block;width:36px;height:36px;border-radius:50%;background:#8a5a7a}.ico.fb{background:#4a6fa5}.ico.pin{background:#b23a3a}</style>
<p style="margin:0 0 8px"><strong>Bloom and Stem</strong>, florist, Norwich</p>
<div class="social">
  <a href="#instagram" class="ico" aria-label="Bloom and Stem on Instagram"></a>
  <a href="#facebook" class="ico fb" aria-label="Bloom and Stem on Facebook"></a>
  <a href="#pinterest" class="ico pin" aria-label="Bloom and Stem on Pinterest"></a>
</div>

Test it by hand in two minutes

  1. Press Tab repeatedly through the page. Each time a link gets focus, ask: if I could only hear this link, would I know where it goes?
  2. Turn on VoiceOver (Cmd+F5 on a Mac), open the rotor with Ctrl+Option+U and choose Links. On Windows, start NVDA and press Insert+F7. Any entry that is blank, or says only 'link', fails.
  3. Right click an icon link, choose Inspect, and look for text between the a tags, an aria-label, or an img with an alt attribute.
  4. Read each link's text on its own, away from its sentence. 'Click here' and 'Read more' pass this rule but still fail the person; say where the link goes.

The fix

Before
<a href="https://instagram.com/bloomandstem" class="icon-instagram"></a>
After
<a href="https://instagram.com/bloomandstem" class="icon-instagram" aria-label="Bloom and Stem on Instagram"></a>

Say where the link goes, in the words a person would use. If it opens a new tab or a PDF, say that too.

Image link

Before
<a href="/bouquets/peony"><img src="peony.jpg" alt=""></a>
After
<a href="/bouquets/peony"><img src="peony.jpg" alt="Peony bouquet"></a>

When the image is all the link holds, its alt text is the link text. An empty alt leaves the link with no name.

Visually hidden text instead of aria-label

Before
<a href="/basket" class="basket-icon"></a>
After
<a href="/basket" class="basket-icon"><span class="visually-hidden">Basket, 2 items</span></a>

Hidden text gets translated by browser translation tools and shows up if the CSS fails. Use a clip-based visually-hidden class, never display:none, which hides it from everyone.

Inline SVG inside a link

Before
<a href="/search"><svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/></svg></a>
After
<a href="/search"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="7"/></svg><span class="visually-hidden">Search</span></a>

Hide the drawing and add the words. An SVG title element also works, but hidden text is read more consistently.

Common mistakes

  • Relying on the title attribute, which most screen readers skip and touch screen users never see.
  • Putting the name in a CSS ::before content string; some screen readers read it, many do not.
  • Hiding the text with display:none, which removes it from screen readers as well as the screen.
  • Writing the same name, like 'Read more', on ten links that go to ten different places.
  • Giving a logo link the alt text 'logo' instead of the company name and where it goes, which is usually home.

WCAG criteria this rule maps to

axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:

The scanner can see that a link has no accessible name from its text, image alt, aria-label or aria-labelledby. It cannot tell whether the name is useful, so a link called 'Click here' passes the rule and still fails the person. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.

Scan your own page for this and 63 other checks

Open any page in Chrome, click Websight, and get a score out of 100 with every issue explained and a draft fix snippet per element.

Add Websight to Chrome

Free scans, no account, nothing leaves your computer. Automated tools find only part of the problems; the extension says so on every report.