If I'm building a single page web app, what should happen to
focus
when the user clicks some navigation?
This is a video I shot a while back, but the question comes up so often I wanted to re-share here on dev.to—plus it's a good excuse to write my first post 😁
Typically in a single page app you'll have a structure that looks roughly something like this:
<nav>
<a href="/">Home</a>
<a href="/cart">Shopping Cart</a>
<a href="/settings">Settings</a>
</nav>
<main>
<!-- some content -->
</main>
Because it's a single page app, clicking on a link won't do a hard refresh. Instead, it will trigger a route change which usually uses a bit of AJAX to fetch some more data and populate the <main>
content area.
For a sighted user this is all good—but what if I'm a non-sighted user navigating with a screen reader? I may not know that the new content has been added to the page (maybe I was expecting a hard refresh) and there's no indication that I should navigate back to the <main>
area.
One easy way to improve this experience is to find a good heading in the newly loaded content and direct focus
to it. The easiest way to pull this off is to give the heading a tabindex
of -1 and call its focus()
method.
<main>
<h2 tabindex="-1">Welcome to your shopping cart</h2>
</main>
<script>
// Assuming this gets called every time new content loads...
function onNewPage() {
var heading = document.querySelector('h2');
heading.focus();
// You can also update the page title :)
document.title = heading.textContent;
}
</script>
A screen reader will then announce the new heading, as well as the main
landmark area that it's contained within. Note that you probably don't want to do this focus management when a user first arrives at your site—you would only want to do it for subsequent navigation, like when they click a link.
Hope you enjoyed this post! It's an easy trick that could make a big difference for some of your users. And if you're interested in more a11y screencasts check out my playlist over on the YouTubes 📺
✌️
Top comments (12)
Begin dev confessions...
I must admit, I am weak when it comes to ally skills aside from some knowledge of
aria-*
attributes. I must also admit that most places I've worked at to the best of my knowledge never even had ally on the radar and I feel like I am probably not the only dev that has had this experience.End dev confessions...
Hey that's ok! Folks have to start somewhere :)
I know it can be tough to get an organization motivated to work on it, and the topic area itself can feel pretty arcane at times. If it's any help, I put together a doc and a video for last year's Google I/O which covers what various folks on the team can do to improve the accessibility of their site.
developers.google.com/web/fundamen...
Thanks for sharing Rob. Looking forward to reading/viewing more content from you.
Hey Rob thanks for the tip!
MDN has me telling anyone who will listen that non-interactive elements shouldn't have a
tabindex
. Are we just going to have to say that SPAs are an exception to the rule?Usually that's correct--you should only give an element tabindex if a user can interact with it or provide it some input.
But for the specific case of managing focus I've often seen folks use this technique because there is no alternative way to move the users focus start point. Browsers actually have an internal API that they use to move the focus start point (developers.google.com/web/updates/...) but it's not exposed to developers as a JavaScript API. The tabindex + focus() trick I showed is a sort of near term hack to achieve a similar effect.
One of the things I really want to work on next is exposing the focus start point API so this trick becomes unnecessary.
I love these tips. I spent years trying to get employers to take it seriously, but it mostly ended up cycling in a pattern of brief starts and fade outs. One nice thing about starting a business was I got to make it a top priority. Thanks for keeping a11y in the forefront.
It works most of the time , but in iOS sometimes it just ignores .focus() no matter what you do. Any suggestions?
I think I've seen bugs related to this before. If you have an example that you can put into a jsbin I can try to send it over to my friends on the Safari team.
Great post. I think if I'm going to start learning a11y, it's going to come in bite-sized chunks like this. Thanks for your work!
This article on managing focus for accessibility is a valuable resource for web developers and designers. cricketbuzz.com id login
What is important to consider when designing focus? negative energy cleansing spell
I like your post and all you share with us is up to date and quite informative . Sky exchange login ID provider