The following was written due to a question Vikas Parashar asked on Twitter, that Heydon Pickering had already answered by the time I got around to checking Twitter. This post dives deeper into Heydon’s answer and calls out some more specifics about how an anchor may be exposed to assistive technologies, such as screen readers.

The anchor element (<a>) without an href attribute is meant to represent a placeholder link, as noted in the HTML Living Standard:

If the a element has no href attribute, then the element represents a placeholder for where a link might otherwise have been placed...

A potential use case for a placeholder link is in a situation where one might need to “disable” a link in a navigation. Since the disabled attribute, and aria-disabled are not meant to be used on <a> elements, removing the href would be a way to make people aware that a link would be there, pending some sort of requirement be met (see Steve Faulkner’s short note on disabled and aria-disabled).

For instance:

    <!-- ... -->
    <li><a href="...">Our products</a></li>
    <li><a>Members only</a></li> <!-- gotta sign up! -->
    <!-- ... -->

When using a placeholder link, one should be aware of how browsers may expose, or how assistive technologies such as screen readers may interpret the element.

For instance, without an href attribute browsers will not allow keyboard focus to navigate to a placeholder link. This is OK, since the anchor should have no function without an href.

That said, sometimes developers will leave an href off from an <a> and add an onclick event to it. However, if one is doing something this a larger question of “what is this element really meant to represent?” should be asked.

If the element is trying to behave like a button, use a <button> element! Or add a tabindex="0", role="button" and make sure Enter and Space keys can be used to activate it. If the onclick causes a URL/route change, then it’s acting like a link and you should really look into how to do that using the href in your framework of choice.

Putting all of that aside for now, the following is a quick rundown of how screen readers will interpret placeholder links, with particular attention paid to if attributes that would provide accessible names or descriptions are set to the <a> element.

VoiceOver on macOS 10.14.5

VoiceOver and Safari (12.1.1) will not announce a placeholder link as a “link”, but will announce it as “clickable” even if there is no onclick, or tabindex attributes on the element.

If given an accessible name via:

<a title="example">my anchor</a>
<!-- or -->
<a aria-label="example">my anchor</a>
<!-- or -->
<a aria-labelledby="id_ref">my anchor</a>

The placeholder link will be announced as if it were a role="group" with an accessible name. VoiceOver could then navigate into the “group” to hear the announcement of the anchor’s visible text, again also announced as “clickable”.

If paired with Chrome (75), no “clickable” announcement will accompany the announcement of the anchor’s text. Similar “group” announcements will be made if the anchor is given an accessible name. But where Chrome and Safari behavior differ is that if the <a> is given an onClick attribute, it will be re-exposed as a “link”.

JAWS 2019 (June release) with different browser pairings

Testing with IE11, Edge (77 Chromium), Chrome (75) and Firefox (68); navigating with the virtual cursor (up and down arrows) JAWS will often only announce the placeholder links as static text. When given an onclick attribute JAWS announce these anchors as links.

JAWS paired with Chrome or Edge, if an attribute that would otherwise provide an accessible name or description (e.g. aria-label, title, or aria-describedby) were set to a placeholder link, then the element would be announced as “clickable” even though there’s no functionality provided.

NVDA 2019.1 with different browser pairings

Testing with Edge (Chromium), Chrome and Firefox; NVDA will announce a placeholder link as a “link” if given an onclick attribute.

When paired with IE11, NVDA will announce “clickable” if a placeholder link has an onclick attribute.

Similar to JAWS, NVDA paired with Chrome or Chromium Edge will announce placeholder links as “clickable” if the <a> element has attributes that would provide an accessible name or description.

VoiceOver on iOS 12.3.1

Beyond announcing its visible text, there are no additional announcements made by VoiceOver when navigating to placeholder links.

TalkBack 7.3 with different browser pairings on Android 8.1

TalkBack and Firefox (68) will continue to announce any <a> without an href as a “link”. Firefox Android bug filed.

TalkBack and Chrome (75) will only announce placeholder links with an onclick attribute as “links”.

Wrapping up

If one is using a basic placeholder link per its intended use of representing where a link might have been placed, e.g. <a>not a link right now</a>, then it will largely announce as intended, as static text.

It’s when the element has been provided additional attributes to provide modified accessible names, or to provide accessible descriptions, that using a placeholder link may not convey the information or (lack of) functionality expected. So, in the event where a link should have an aria-label were it to be fully functional, that attribute should be removed, along with the href if currently representing a placeholder link.

Finally, if adding an onclick event to a placeholder link one should stop and think about why. If it’s meant to be a link, it should have an href. If it’s meant to act like a button, then use a button element.

FYI: you can check out a test page of placeholder links, here.