# Links do not have a discernible name: what it means and how to fix it

**Audit ID:** `link-name` · **Category:** Accessibility

<!--QA-->
> **Quick answer:** This audit fails when a link has no text a screen reader can announce, usually an icon-only link such as a cart or social icon. Fix it by adding an aria-label to the anchor, adding visually hidden text inside it, or giving an image inside the link real alt text.
<!--/QA-->

This Lighthouse audit fails when a link on the page has no text a screen reader can announce. The most common cause is an icon-only link: a magnifying glass, a cart, a social icon, a logo wrapped in an anchor. Sighted users see the icon. A screen reader reaches the link and says "link", or reads out the URL, which tells the user nothing about where it goes.

## TL;DR

- **What:** One or more `<a>` elements have no accessible name.
- **Why it matters:** Screen readers announce these links as "link" or read the raw URL, so the user cannot tell what they do.
- **Fix:** Give every link real text, or an `aria-label`, or visually hidden text. Never leave an anchor with only an icon inside it.

## What does the link-name audit check?

Lighthouse runs the axe-core rule [`link-name`](https://dequeuniversity.com/rules/axe/4.12/link-name) against the rendered DOM. It computes the accessible name of each `<a>` element that has an `href`, and fails the audit if that name is empty.

The accessible name comes from the first of these that produces text:

1. `aria-labelledby` pointing at another element
2. `aria-label` on the anchor
3. The text content of the anchor, including `alt` text of any image inside it
4. `title` on the anchor

If all four are empty, the link has no discernible name and the audit fails. The passing title reads "Links have a discernible name"; the failing one is "Links do not have a discernible name".

## Why do links without a discernible name matter?

Screen reader users navigate by pulling up a list of every link on the page, out of context. That list is built entirely from accessible names. A nameless link shows up as "link", or as `https://example.com/cart?ref=header`, alongside a dozen others that look the same.

It also affects:

- **Voice control.** Users say "click Search" to activate a link. With no name there is nothing to say.
- **WCAG conformance.** This is a failure of [SC 2.4.4 Link Purpose (In Context)](https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-in-context.html) at Level A, and it is one of the most common failures on the web.
- **SEO, indirectly.** Search engines use anchor text as a relevance signal. An empty link passes none.

## How do I fix "links do not have a discernible name"?

Pick whichever of these fits the markup. All four produce a valid accessible name.

```html
<!-- FAILS: icon-only link, nothing to announce -->
<a href="/cart"><svg>...</svg></a>

<!-- FIX 1: aria-label on the anchor. Best for icon-only links. -->
<a href="/cart" aria-label="Shopping cart"><svg aria-hidden="true">...</svg></a>

<!-- FIX 2: visually hidden text. Works without ARIA and survives translation. -->
<a href="/cart">
  <svg aria-hidden="true">...</svg>
  <span class="sr-only">Shopping cart</span>
</a>

<!-- FIX 3: alt text, when the link wraps an <img> -->
<a href="/"><img src="/logo.svg" alt="Acme home"></a>

<!-- FIX 4: real visible text, always the best option when you have room -->
<a href="/cart">Cart</a>
```

The `sr-only` class, if your CSS framework does not already ship one:

```css
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
```

Note the `aria-hidden="true"` on the icon in fixes 1 and 2. Without it, some screen readers announce the SVG's own title alongside your label, producing "Shopping cart, cart icon". Hide the decorative graphic and let the label speak.

## What are the most common causes on a real site?

In a scan of 269 production storefronts, `link-name` failed on **67.3% of them**. The offenders were almost always the same handful of patterns:

- **Social icons in the footer.** A row of anchors containing only an SVG each.
- **The logo link.** `<a href="/"><img src="logo.svg" alt=""></a>` with an empty `alt`, which is correct for a decorative image but leaves the link nameless.
- **Icon buttons that are really links.** Search, cart, account, hamburger menu.
- **Pagination.** Arrows rendered as `‹` and `›` characters, or as icons, with no label.
- **"Read more" cards** where the whole card is an anchor wrapping an image with empty `alt` and the heading sits outside the link.
- **Empty tracking anchors.** `<a href="#" onclick="track()"></a>` with no content at all.

## How do I fix this in React, Next.js, WordPress, or Shopify?

### React / Next.js

Icon components usually spread props, so the label goes on the `Link`, not the icon:

```jsx
// FAILS
<Link href="/cart"><CartIcon /></Link>

// FIXED
<Link href="/cart" aria-label="Shopping cart">
  <CartIcon aria-hidden="true" />
</Link>
```

If you use `next/image` inside a link, an empty `alt` leaves the link nameless. Either give the image real `alt` text describing the destination, or add `aria-label` to the `Link`.

Catch these in CI with `eslint-plugin-jsx-a11y`, which ships an `anchor-has-content` rule for exactly this.

### WordPress

Most themes generate the social and logo markup for you. Check:

- **Site logo block.** Set the site title so the logo link inherits a name, or add alt text to the logo in the Customizer.
- **Social Icons block.** WordPress core adds labels automatically, but many page builders do not. Inspect the rendered anchor.
- **Menu items with icon fonts.** If the menu label is hidden via CSS, replace `display: none` with the `.sr-only` pattern above. `display: none` removes the text from the accessibility tree; clipping keeps it.

### Shopify

The usual culprits are in `header.liquid` and `footer.liquid`:

```liquid
<!-- FAILS -->
<a href="{{ routes.cart_url }}">{% render 'icon-cart' %}</a>

<!-- FIXED -->
<a href="{{ routes.cart_url }}" aria-label="{{ 'layout.cart.title' | t }}">
  {% render 'icon-cart' %}
</a>
```

Use a translation key rather than a hardcoded string so the label follows the storefront locale. Dawn-based themes already do this; older and heavily customised themes frequently do not.

## What link-name pitfalls should I avoid?

- **Do not use `title` as your fix.** It technically satisfies the audit, but `title` is not shown on touch devices, is inconsistently announced, and is invisible to voice control users. It passes the test without helping anyone.
- **Do not use `display: none` or `visibility: hidden` to hide link text.** Both remove the text from the accessibility tree, so the link goes back to having no name. Use the clipping `.sr-only` pattern.
- **Do not label every link "click here" or "read more".** That passes `link-name` and fails [SC 2.4.9](https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-link-only.html), and it is what the separate `link-text` audit checks. Name the destination.
- **Do not put `aria-hidden="true"` on the anchor itself.** It hides the link from assistive tech entirely while leaving it keyboard focusable, which is worse than the original problem.
- **Do not rely on an empty `alt` inside the link.** `alt=""` is correct for decoration, but if that image is the only content of the anchor, the link is nameless.
- **Watch for duplicate names.** Ten links all labelled "Read more" pass this audit but produce a useless link list. Include the destination: "Read more about shipping".

## How do I verify the fix?

1. Re-run Lighthouse. The `link-name` audit should pass and move into "Passed audits".
2. In Chrome DevTools, select the anchor and check the **Accessibility** pane. The **Computed Properties → Name** field shows exactly what a screen reader will announce. Empty means it still fails.
3. Test with a real screen reader's link list: VoiceOver on Mac (VO+U, then arrow to Links), or NVDA on Windows (Insert+F7). Read the list without looking at the page. If you cannot tell where a link goes, the name is not good enough.
4. Add [axe DevTools](https://www.deque.com/axe/devtools/) or `eslint-plugin-jsx-a11y` to catch regressions before they ship.

## Related audits

- [Image alt attributes](/audits/image-alt), the images inside those links
- [Document main landmark](/audits/document-main-landmark), landmark navigation
- [Heading order](/audits/heading-order), semantic structure
- [Color contrast](/audits/color-contrast), visual accessibility

---

Audit your URL at https://lighthouse-md.com.
