Remove focus from next/link element after page change
Run next info (available from version 12.0.8 and up)
No response
What version of Next.js are you using?
12
What version of Node.js are you using?
14
What browser are you using?
Chrome, Firefox
What operating system are you using?
macOS
How are you deploying your application?
other
Describe the Bug
In Chrome & Firefox, when changing pages using a next/link the clicked anchor remains focused after page change. This causes anchor styles to remain in their focused state.
I found this issue - https://github.com/vercel/next.js/issues/2768 from a few years ago that solved this problem.
This is the PR created by @connor-baer for that issue - https://github.com/vercel/next.js/pull/3545. The solution was to do document.body.focus() on every route change.
However, the issue appears to be back.

Expected Behavior
When changing pages with a next/link the clicked link should no longer have focus after page change.
To Reproduce
Visit this in chrome or firefox and click the header links: https://stackblitz.com/edit/nextjs-js-focus-issue
Short term solution in _app.tsx:
const router = useRouter()
useEffect(() => {
document.activeElement instanceof HTMLElement && document.activeElement.blur()
}, [router])
To my knowledge this should't have any accessibility implications.
Hi, so I believe this behavior is the result of research that ended up being implemented in the following PR: #20428
Please have a read at the (quite lengthy) thread there and consider closing this issue if you got your answer. If you are still unsure, let me know and I'll get further assistance on this.
In short, I think the conclusion was that resetting focus to body is not the most desirable.
I have read different posts on this and am still unsure of the desired behavior here.
I have an SPA where things like header and footer are persistent across all routes, but if the user e.g. has used the keyboard to select a different page in the footer on a lengthy page, I do not feel it is very user-friendly to be starting with keyboard navigation on the next page from the footer.
Right now I have an effect running after route changes (excluding any changes in query-parameters of course) that will focus the first page element if no modals are open. But I am unsure if this is good practice in terms of accessebility.
+1 I currently have this focus and blur:
export function focusSkipNav(blur = false) {
const el = document.getElementById("skip-nav")
if (el) {
el?.focus()
if (blur) {
el?.blur()
}
}
}
export function yieldSkipNav() {
focusSkipNav(true)
}
which I run on page change as well
useEffect(() => {
router.events.on("routeChangeComplete", yieldSkipNav)
return () => {
router.events.off("routeChangeComplete", yieldSkipNav)
}
}, [router.events])
it seems to resolve the sticky issue and sets the focus to where I expect it to be, but I'm not clear about accessibility around this either.
I think it's in line with Marcy's comment but it was a little confusing to read
The research of mine that you mentioned recommended that focus should be sent to a small, keyboard-interactive element like a skip link. Sending focus to an h1 or wrapper element works for some aspects, but wasn't really the recommended solution. I also want to make sure visible focus outlines are considered, even if it takes using :focus-visible or something like what-input to keep mouse users happy. There is a lot of value in showing the user's focus point after it moves, and focus outlines are often turned off for wrapper elements (and in general).
and I'm not sure if leaving focus on those elements is good ux since it'll make most skip nav implementations visible on page change.