gaurav5430
gaurav5430

Reputation: 13917

Accessibility - Javascript only links with href="#" an antipattern?

I have a react SPA where I have some links which require javascript to change the page url. Semantically these should be links, but the link destination is computed at runtime on click, or it requires javascript to move to that location (history api)

I have seen it mentioned at a few places that href="#" is an antipattern or something that should be avoided. For example this article from webaim https://webaim.org/techniques/hypertext/ mentions that:

One of the most serious barriers is to create links that go nowhere. Developers sometimes use JavaScript to create dynamic menus that drop down when the user hovers over certain links with the mouse. In some cases, the link itself goes nowhere at all, and its only purpose is to expose the links in the drop-down menu, which do have real destinations. Links like this often have a pound sign as the link destination, which means that the link destination is the same page; clicking on the link accomplishes nothing. Both keyboard users and mouse users will experience nothing at all when attempting to activate the link.

and it gives an example of href="#"

Now i get that using href="#" for links which do nothing or do not take the user anywhere might semantically be incorrect. In my usage though, the link does have a destination, just that the destination can't be specified in href and may not be decided unless the link is clicked. So my usage is to have href="#" and e.preventDefault() onClick, so that it does not go to top of the page and create another history entry.

I have seen other working solutions/workarounds for this:

But i would like to understand, if using href="#" for links that do have a destination (which is figured out after clicking on the link, or applied using javascript) is an antipattern.

This is a follow up to this question related to javascript only links accessibility Accessibility: Using javascript only links with href="#"

Upvotes: 2

Views: 1021

Answers (2)

Junji Zhi
Junji Zhi

Reputation: 1480

If you are using a screen reader software, e.g., NVDA on Windows (Browser mode, specifically), it could intercept certain keys (e.g., Space or Enter key) to a <a> tag and bind certain behavior to that, meaning that it bypasses the Javascript code that generates dynamic URLs). So your app could be broken for NVDA users.

You can actually try testing your app on NVDA / JAWS on Windows, and see if <a href="#" /> + Javascript works.

If you are building a dropdown menus, generally, it's hard to implement make it 100% accessible for hover-and-expand menus. We should avoid using this pattern if possible. You are better off using other designs, e.g., table of content.

Upvotes: 1

Lionel Rowe
Lionel Rowe

Reputation: 5946

If it navigates to a new URL, the href property should be set to that new URL. You can then use event.preventDefault() to prevent the page from reloading at the new location.

// mock out history for demo purposes
const history = {
  pushState: (_data, _title, newUrl) => {
    alert(`navigated to ${newUrl}!`)
  }
}

document.querySelector('#spa-link').addEventListener('click', e => {
  e.preventDefault()
  
  history.pushState({}, '', '/new/path')
})
<a id="spa-link" href="/new/path">Go to new path</a>

Upvotes: 1

Related Questions