Reset focus on Vue SPA page

Viewed 841

I'm developping Vue SPA with Vue router app and I'm trying to simulate oage reload, by resetting focus state after changing the route. Here is my code:

router.beforeEach((to, from, next) => {
  document.activeElement.blur();
  next();
});

My problem is that focus indeed returns to body element right after change, but on next focus it goes back to where it was, in this case footer, instead of "skip to content" button. I tried setting focus to window explicitly, but it doesn't work either. Does anyone have an idea how to reset focus flow for real, so it truly starts over? Any help will be appreciated!

2 Answers

Basing on this article I added tabindex -1 right before and removed it right after. It did the trick

router.beforeEach((to, from, next) => {
  document.body.setAttribute("tabindex", "-1");
  document.body.focus();
  document.body.removeAttribute("tabindex");
  next();
});

The Vue website now has some official documentation for re-focusing on a "Skip Link" after each navigation:

https://vuejs.org/guide/best-practices/accessibility.html#skip-link

Notes:

  1. Since this focuses on the Skip Link each time a navigation happens, this means if it's an auto-hiding link, like the one in the Vue docs, it will "pop open" each time you navigate to a different page.
  2. I also tried approaches that focus on the body of the page (like the answer from p-sara) however I encountered a problem with this and the VoiceOver feature of MacOS. Steps to reproduce this problem: 1. Navigate to a link with the VoiceOver controls (e.g. ctrl+option+left/right) 2. Open the link with the VoiceOver controls (ctrl+option+space) 3. On the new page, if you continue to navigate with the VoiceOver controls, it won't start from the top, it will continue from where you left off on the page.
  3. In my testing, it appears for VoiceOver controls to change focus, the .focus() method needs to applied to an element that can receive focus by default (like a link).
Related