Links unreachable with tab key despite having href made me learn about Spatial Navigation
Tags: webdev, a11y, testing
Published: 2023-10-30 17:10:09

Another issue where I was not able to google a simple solution: I discovered that links on a website were not "tabbable", i.e. not reachable using the tab key – despite having an `href` attribute, which should make them reachable even without explicitly adding a `tabindex` attribute.

**TL;DR** In the end, I learned that my code was correct, but that some user agents use [spatial navigation](https://wicg.github.io/spatial-navigation/), a 4-directional alternative to the usual [tab key navigation](https://webaim.org/techniques/keyboard/) considered essential for accessibility testing.

Trying to find a solution for similar problems, I first came across some obvious posts that are helpful in general:
- [HTML: Unable to reach a link using Tab key](https://stackoverflow.com/questions/57426425/html-unable-to-reach-a-link-using-tab-key)
- [Why would an `a` tag need `tabindex=0`?](https://stackoverflow.com/questions/30740226/why-would-an-a-tag-need-tabindex-0)
- [The Most Common Web Accessibility Mistakes & How To Solve Them](https://medium.com/charlottes-digital-web/the-most-common-web-accessibility-mistakes-how-to-solve-them-5b7d25a337e0)

## The most common web accessibility mistakes

I verified that I had not many any of the common accessibility mistakes including
- using a `button` instead of `a` link or using `a` link instead of a `button`
- using icons as buttons
- using an empty `href` attribute 
- omitting the `href` attribute
- not making elements tabbable

## Not making elements tabbable

This sounds misleading, as we already discovered that having a valid `href` attribute in an `a` element should be enough to "make it tabbable". But still it isn't!

I must have done something that caused the links to become untabbable. They might be
- disabled by JavaScript (`event.preventDefault()`)
- disabled by CSS (`pointer-events: none`)
- obscured by another element

That might or might not be related to tab indexing, but it might prevent default behavior and cause problems, so let's inspect!

## Links disabled by JavaScript 

Check if I have some event handler that prevents a link's default click action ([`event.preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)) either directly or by observing a parent element using [event delegation](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation). 

## Links disabled by CSS

In a similar way, we can disable default click handling using the [CSS pointer-events property](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events) (`pointer-events: none`).

## Links obscured by another element

Sometimes, we can't use elements in the intended way anymore when other elements overlay them. This could be caused by negative margins or absolute positioning.

### Still no conclusion

I did not find any links that were completely disabled, as all of them reacted to hover (mouse over) and mouse clicks, but I did find all of the above techniques in my codebase.

I removed the suspicious pointer-events property on my target offset areas, but nothing changed. All links are clickable, hoverable, touchable, but not tabbable.

## Isolating the problem

In a modular design system, it's relatively easy to isolate a bug or an undesired behavior. But what if it can only be reproduced on a complex website?

We can use dev tools to remove unrelated parts of the page. In my case, the second most suspicious element on the page, preceding the main section with its untabbable web links, is a hero header set to 100% of the page height.

What happens after deleting the hero element from the document? It does not make any difference!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aj4g0yfih8klidnfyoa2.png)

So here we are: "more than 20 years of professional experience", but I fail to "make my links tabbable". I'm sure that used to work 20 years ago, and it works when adding links to a codepen. So what's happening here? Would it even work if we added `tabindex="0"` as we shouldn't have to?

Is there anything wrong with any other attribute or style? Let's give one of my unsuspicious links a closer look and compare different variations.

The only markup variation that worked so far was adding a tabindex.

So what about our CSS? We could prevent loading any styles and try again. Now it looks like 30 years ago and it still doesn't work!

![screenshot of unstyled page section](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/if6xeu4btufel9cx9f2u.png)

Maybe we should disable JS instead. And it still doesn't work? Let's copy my markup into a new codepen and verify, possibly copying over more elements of the defunct page until we catch the problematic part...

## Links not tabbable without explicit tabindex?

I don't even need to add any styles or scripts: links without explicit tabindex are not tabbable in this example!

{% codepen https://codepen.io/openmindculture/pen/KKJzXJB %}

Nothing but simple HTML markup that should work everywhere:

```html
A <a href="https://example.com/">Link</a>,
<a href="https://example.com/" target="_blank">href and target</a>, [...]

<h3>Same as above, but with explicit tabindex=0</h3>

A <a tabindex="0" href="https://example.com/">Link with nothing but href</a>, another
<a tabindex="0" href="https://example.com/" target="_blank">one with href and target</a>
```

What's that? A browser bug? A browser misconfiguration? Should I stop using an alternative [Chromium](https://www.chromium.org/) build like [Vivaldi](https://vivaldi.com/)?

Let's retest everything in the latest stable Firefox browser!

## Retesting in Firefox

- production page: all links are tabbable ✅
- current dev branch on localhost: all links are tabbable ✅
- codepen example: all links are tabbable ✅

## Retesting in Google Chrome

- production page: all links are tabbable ✅
- current dev branch on localhost: all links are tabbable ✅
- codepen example: all links are tabbable ✅

## Rephrasing my search query

I had already researched:
- "links not tabbable"
- "make all href links tabbable without explicit tabindex"
- "unable to reach a link using tab key"

Let's proceed with a different focus:
- "**Vivaldi** tab navigation"

![Vivaldi tab navigation screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/od9b4x4dwl9asuisfjd0.png)

Maybe that's still not a good search query, as parallel browsing sessions are also known as "open tabs", so "browser tab navigation" means switching between those tabs, not using the tab key to navigate on a web page.

What about these?
- "**Vivaldi** link using **tab key**"
- "**links not tabbable in Vivaldi**"

Someone had a similar problem back in 2021: [Using tab-key to navigate websites is impossible](https://forum.vivaldi.net/topic/63724/using-tab-key-to-navigate-websites-is-impossible), probably not exactly my problem, or I would have noticed before.

###  Using tab-key to navigate websites is impossible ↔️

Still curious to read, I find an answer hinting it's a misconfiguration:

>> Using tab-key many parts of websites are skipped. Other browser (like Chrome, Edge, Firefox) don't show this problem. So it's definitely a bug in Vivaldi.
>> This is a problem on Windows AND Mac.
>
> Not a bug.
> Want to jump to every element on a site?
> Settings → Webpages → Webpage Focus → Focus all Controls and Links

If that's not the default browser behavior, it feels like a bug and another reason to make Firefox my default browser again. Even if the answer is technically correct, the phrase "not a bug" might sound like "you are too stupid to understand our software" unless it is part of a helpful explanation.

[![Issue screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1q00p8sulmcpn9wbwtcf.png)](https://forum.vivaldi.net/topic/63724/using-tab-key-to-navigate-websites-is-impossible)

Vivaldi doesn't even seem to support full tab navigation in search results by default. How come I only find out now? Maybe they changed the default settings in a recent update?

Side note: I also remember ranting about ["A fine Firefox feature"](https://dev.to/ingosteinke/a-fine-firefox-feature-4056) in 2022, so maybe I better make Chromium my new default.

The actual problem isn't wasting my time on fixing bugs. I used to embrace bug fixing as a learning process where I can discover patterns and improve how I work. But as we keep telling coworkers that using keyboard navigation is one important little step to improve accessibility in our daily work ...

### Confusion

It feels wrong to add `tabindex="0"` to every link on my website, and it wouldn't even be possible when I include user generated content beyond my control, like in a content management system.

I don't even understand: what would be the benefit of not enabling tab key navigation by default?

Ongoing issue discussion:

>>> The problem is that a tab key navigation jumps to all focusable elements on a website, that could take much time until you reach the place you want to.
>>
>> This is the reason to change default browser behavior against every other current user agent? People who don't find tab index helpful and who are willing and able to use a mouse or a touch screen can still do so, but I still don't get why the alternative should be disabled. There are a lot of websites where tab index is a helpful shortcut even for "abled" users.
>>
>>That's what accessible web design should consider and prevent having too many irrelevant elements on a page, and that's what tabindex was made for.
>
> I hope for future there will be a Vivaldi which can easily switch fast between Tab Key Navigation, Caret Navigation and Spatial Navigation.

Today I learned that there are at least theree types of (keyboard) navigation:

- [Tab Key Navigation](https://webaim.org/techniques/keyboard/)
- [Caret Navigation](https://en.wikipedia.org/wiki/Caret_navigation)
- [Spatial Navigation](https://wicg.github.io/spatial-navigation/)

Tab key navigation is the traditional way of jumping forward and backward using tab and shift-tab keys. Caret navigation is what we can do when using the command line.

## Spatial Navigation ✥

> Spatial navigation is the ability to navigate between focusable elements based on their position within a structured document. Spatial navigation is often called ‘directional navigation’ which enables four(top/left/bottom/right) directional navigation. Users are usually familiar with the 2-way navigation using both ‘tab key’ for the forward direction and ‘shift+tab key’ for the backward direction, but not familiar with the 4-way navigation using arrow keys.

## Conclusions

There is no need to add `tabindex="0"` to every link on every website. We should test our websites in many different browsers, and as Vivaldi keeps adding unexpected features, this might inspire us to discover new aspects that we might have overlooked otherwise, like considering **spatial navigation**.

![screenshot of different web browser icons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4sy8yxga5tksp6czr63t.png)

Hopefully someone will add a more helpful answer in the post comments!

Did you ever experience a similar situation?

What do you recommend as a follow-up?