问题
I have a react SPA in which I have some links which navigate to other pages or other locations on the same page, These navigations are either decided programmatically or are dependent on javascript to go to another location on the same page.
- I might not know the link
href
when the link is displayed, so I render it withhref="#"
andevent.preventDefault()
in the click handler, after which I run the logic to decide where the link should navigate to. - In case of anchor links, I need javascript to scroll to the element, because with SPA routers hash based anchor links might not work as the anchored element might not be available yet, and also i need smooth scroll. (In this case, I can probably still specify the href, which keeps the link accessible, but use javascript to handle the scrolling)
To me, semantically it still should be a link and not a button as it navigates the user to another page or another location on the same page. But, thinking about accessibility, the screen reader doesn't have enough information to understand the link destination and can't announce it to the user. I suppose that is not alright ?
How do I make sure that the usage is semantic as well as accessible? Should I be using a button instead? Or should I be adding some other information to the link with aria-label ? Or is it actually ok for accessibility to have links with href="#" ?
回答1:
Short Answer
Links should be used if the URL changes (navigation) for everything else a button should be used. <a href="#"
is not a good practice but for a SPA it should be OK if your link text is accurate and detailed. Avoid smooth scroll or give people a way to switch it off as it can be disorientating.
Longer Answer
I gave quite an extensive answer on <a> vs <button> in SPAs here, so I hope that is sufficient to answer which one to use in what scenario for general use cases.
With regards to the #
in the URL due to you not knowing the URL before hand. It would be much better if you start it as #
if the URL is unknown but then update the href
once you know where you are going to route people.
This is for the reasons discussed in the answer I linked regarding reassurance, i.e. knowing where a link will take me.
Obviously if you are not able to do this then make sure the link text is very descriptive so that I can be confident I am going to the right place.
Scrolling within a SPA
With regards to the scrolling to different parts of the page that would still be a link as you say, assuming that you update the url with #section-name
. You should do this, but if your application router cannot handle URL fragments then I would not update the URL at all and change this to a button.
At this stage I would use some visually hidden text within the button to explain that this scrolls to a section on the current page.
The example below illustrates this. Please use the CSS class below to visually hide text as it has better compatibility than bootstrap sr-only class as explained in this answer I gave.
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<button><span class="visually-hidden">Go To </span>Section name<span class="visually-hidden"> on this page</span></button>
A quick word on smooth scrolling
Finally I would caution you on the use of smooth scrolling. If you use this make sure there is a way to switch it off as it may be distracting or disorientating for people with either motion disorders or anxiety disorders.
One way you can do this is to use the CSS media query prefers-reduced-motion.
Final Thoughts
Without seeing each scenario it is hard to give a 100% definitive answer, if you can try and follow standard navigation patterns of buttons for same page actions, links with url fragments for navigating to sections of the same page and links to other pages, even if these are handled via AJAX and only partial reloads.
Obviously that is the aim, I am aware that with some routing solutions this is not always possible in which case use your best judgement and test it with a screen reader as screen reader users are most likely to suffer from a poorly formed navigation system in a SPA.
One last tip - if you do change page in a SPA, make the <h1>
on the next page programatically focusable with tabindex="-1"
and focus that once the page loads. It is a great way to let users with little to no vision know that navigation is complete in a SPA using AJAX.
来源:https://stackoverflow.com/questions/63251705/accessibility-using-javascript-only-links-with-href