Empty image links and vague “Read more” links
A banner is made clickable with an empty link laid over it, and the cards below all end in the same “Read more”.
The problem
Screen reader users can't tell where a link goes before they follow it.
A tea shop's home page opens with a banner: a photo of autumn leaves, the headline "Autumn blends are here" and a line about the new teas. The whole banner is clickable. Pressing Tab puts focus on it, and a screen reader announces "link", or reads out the address, "collections/autumn". Below it are three journal cards, each with a heading, a sentence and a link that says "Read more". Someone who opens the screen reader's list of links hears an unnamed link and then "Read more, Read more, Read more".
To make the whole banner clickable, the theme lays an empty <a> over it with absolute positioning. The headline and text sit in a sibling element, outside the link, so the link has no text and therefore no accessible name. The cards have the opposite problem: their links do have text, but the same two words for three different posts.
Screen reader users often move through a page by its links, or open a list of every link on it. An unnamed link gives them nothing to go on, and three identical "Read more" entries make them follow each one to find out where it leads. Voice control users say a link's text to activate it; they can't say the name of a link that has none, and "click Read more" matches three links at once. People who find reading hard also benefit when a link says plainly where it goes.
An automated check such as axe's link-name reliably flags the empty banner link. It does not judge whether a name is useful, so it passes three "Read more" links, a link named "IMG_2041.jpg", or an icon whose alt is "logo". A quick AI fix often adds aria-label="Link", which silences the scanner and helps nobody. It may also add an aria-label that drops the visible words, so voice control can no longer find the link. A name only helps when a person reads it in a list and still knows where it goes.
Try it
Press Tab to move through the links.
The panel shows what a screen reader announces for each link, and its list of links. Can you tell where each one goes?
The fix
Give every link words that say where it goes: add them to the links you have, or make the heading the link.
- 1Every link needs words: its text, an image's alt, or a name that starts with the visible label.
- 2Name the link laid over a banner, or replace it with a heading link stretched by a pseudo-element.
- 3Extend “Read more” with visually hidden text, or replace it with the destination.
<div class="banner"> <img src="/images/autumn.jpg" alt=""> <a href="/collections/autumn" class="banner-link"></a> <div class="banner-text"> <h2>Autumn blends are here</h2> <p>Roasted hojicha, chai and chestnut.</p> </div></div> <article class="card"> <h3>How to brew hojicha</h3> <p>Lower heat and a shorter steep bring out the roast.</p> <a href="/journal/brew-hojicha">Read more</a></article>html
<div class="banner"> <img src="/images/autumn.jpg" alt=""> <a href="/collections/autumn" class="banner-link"> <span class="visually-hidden">Autumn blends are here</span> </a> <div class="banner-text"> <h2>Autumn blends are here</h2> <p>Roasted hojicha, chai and chestnut.</p> </div></div> <article class="card"> <h3>How to brew hojicha</h3> <p>Lower heat and a shorter steep bring out the roast.</p> <a href="/journal/brew-hojicha"> Read more<span class="visually-hidden"> about how to brew hojicha</span> </a></article>css
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;}The banner link contains nothing, so assistive technology has no words to announce. The card's "Read more" only makes sense when the heading above it is read too. In a list of links, that heading is not read.
Adding the words leaves the layout as it is. The banner link is now announced as "Autumn blends are here, link", and each card link as "Read more about how to brew hojicha, link". The card names start with the visible words, so voice control can still find them. Instead of hidden text, the banner link can take its name from the headline with aria-labelledby, pointing at an id on the h2, so the two can't drift apart. Either way, someone reading the banner from top to bottom hears the headline twice: once as the link and once as the heading.
Both options give every link a name and meet 2.4.4. Adding the words is the smaller change: no layout or CSS changes, so it suits a theme or third-party slideshow you can't restructure, or a design that must keep "Read more". Making the heading the link is cleaner: one link per banner or card, read once, named by the heading people already see. Choose it when you can change the template. You can mix them, for example heading links on cards you own and a named overlay link on a slideshow you don't.
The stretched link covers other controls. Any other button or link inside the card, such as a "Save" button or a tag link, needs position: relative and a z-index above the pseudo-element, or it can't be clicked. The overlay also stops people selecting the card's text. If the card has several controls, consider making only the heading and image clickable.
Wrapping the whole card in one <a>. This is valid HTML and makes the card clickable, but the link's name becomes everything inside the card, so the screen reader reads a long paragraph. The card also can't contain another link or button. A link on the heading avoids both problems.
Hidden text versus aria-label. Use a clip-based .visually-hidden class, not display: none, which removes the text from the accessible name too. Prefer hidden text to aria-label: aria-label replaces the link's content, some browser translation tools skip it, and it can drift from the visible text. If you do use it, start it with the visible words.
Image and icon links. When the image is the only content of a link, its alt names the destination ("Leaf & Kettle home", "Instagram"), not the picture. When the image sits next to text in the same link, give it alt="" so the name is not read twice. For an SVG icon, hide the SVG with aria-hidden="true" and put visually hidden text in the link.
Editable content. In a theme or CMS, the banner's headline is often an optional field. If it is left empty, the stretched link has no name again. Require a link label when a link is set, or don't render the link when the label is empty. Several banners that each say "Shop now" have the same problem as "Read more".
Strictly, context can be enough. WCAG 2.4.4 accepts link text read together with its programmatically determined context, such as the sentence, list item or table cell it sits in. A "Read more" inside a well-structured card may therefore conform, but the list of links is still unclear, and level AAA 2.4.9 asks for links that make sense on their own. An empty link fails in every case.
Verify the fix
5 checks.
Test with: Keyboard, Screen reader, Mouse
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the shared card, banner or slideshow component changes.
Limits
This is a starting pattern, not a guarantee for every application. Paths and class names in the snippets are placeholders. Content editors can still write a vague link later, so keep link text in your publishing review. Test the complete journey with your target assistive technology.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.