So you have a non-page-based navigation: tabs, carousels, accordions, multi-level menus, route changes... we deal with these a lot in modern frontends. Is your "trigger" (the thing you press to make the navigation happen) a link or a button? I tend to side with link (it's taking you to a part of the document, just a hidden one right now). Jeremy has a slightly more considered approach that thinks less about semantics (without ignoring them) and more about actual user experience:
- Is the target of the trigger close by, or directly adjacent to, the trigger in the DOM? Use a button, because you don't need to worry about a focus change.
- Otherwise, use a link with a fragment identifier (y'know,
As he points out, that means you may end up using a link even where a button is sort of semantically cleaner, such as a login modal. In my head, a modal is always a button: it doesn't take me to a part of the document or another page, it opens a new form entirely (Jeremy sees this differently anyway, and I can understand his reasoning). But using a link means your focus state gets switched to the modal immediately, no extra code required, plus if JS fails the link may still work.
This mental model only gets you so far, but Jeremy also highlights some useful ARIA roles that can be sprinkled on top to further increase the accessibility. I'll try to keep it all in mind 😄