I'm mainly interested in the a11y aspects
So as you might be aware, sometimes you might wish to have a button that acts as an anchor.
These are 4 ways (I can think of) of approaching this issue:
1. Button inside an anchor element
<button>Button</button>
2. Anchor inside button element
<button>Button</button>
<!-- Also should it be a href or button onclick (?) -->
3. Anchor styled as a button (without a button element)
<a class="buttonLike" href="//redirection">Button</a>
4. Button acting as a redirection (without an anchor element):
const button = document.getElementById('button')
button.addEventListener('click', () => {
window.location.href = "//redirection"
})
<button id="button">Button</button>
I've tried to find an answer to this myself. Closest I could find was this excerpt:
According to the MDN anchor spec, which states the following:
Anchor elements are often abused as fake buttons by setting their href to # or javascript:void(0) to prevent the page from refreshing, then listening for their click events .
These bogus href values cause unexpected behavior when copying/dragging links, opening links in a new tab/window, bookmarking, or when JavaScript is loading, errors, or is disabled. They also convey incorrect semantics to assistive technologies, like screen readers.
Use a <button> instead. In general, you should only use a hyperlink for navigation to a real URL.
Unfortunately this doesn't help me too much. Basically all it states is you should not use the third approach (anchor styled as a button) if you don't mean to provide a real link to it, which is not what this question is about.
Is there any official WCAG on this subject matter that I was unable to find or?
Option 1 is not valid HTML.
Option 2 is not valid HTML.
Option 3 is the correct choice here.
Option 4 is semantically incorrect.
Semantics are one of if not the most important aspects of accessibility.
There are two things at play which dictate option 3.
The first is that an anchor should be used only to jump to sections and to navigate between pages.
The second is that a button should perform actions on the same page.
Now if you want to style a call to action link to look like a button that is fine but make sure you use the correct semantics, but make sure that CTA leads to a new page or it isn't semantically correct.
And although it is swearing on StackOverflow to mention SEO, a hyperlink rather than a JavaScript redirection will be far better.
The first and second rules of ARIA say:
1st rule : If you can use a native HTML element [...] then do so
2nd rule : Do not change native semantics, unless you really have to.
Interactive elements like a and button can't contain other interactive elements:
The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links).
So, as what you want to do is linking to a page, your third solution is obviously the only one correct.
I think you might have confused the "bogus" stagement which refers to your 4th example.
From my little experience with Accessibility and semantics there is no "one size fits all". It really depends on your priorities and the user experience you are aiming for.
A <button> gets all the accessibility goodies from the browser automatically: Being selected or pressed using the tab or spacebar/enter keys.
A <a> element is a link, links are meant to be used as links or anchors within a page.
Anchors are not as important in comparison to a button within a page. From a user experience point of view; a button is used by people to interact with a UI, either to confirm or make the UI do something. Pressing a button provides a different feedback compared to a link. Anchor links on the other hand help a user with finding content within a page.
Again, it really depends on what you are trying to do:
Is this a terms page or an article? Then list your anchor links without any button-like styling
Does this a link that has to look as a button so users find it easier to spot or interact? Then style it as a button without it being actually a <button>.
Related
I am working on a web page where user has to scroll a lot.
For ease of use, I have added the back-to-top link at the bottom of the page, so user can navigate to the top of the page.
Now I have a html markup like this:
<a class="btn-primary" href="#top">
<span class="btn-content link-content">
<svg focusable="false"><use xlink:href="#arrow-upward"></use></svg>
</span>
</a>
How can I make my link more accessible? I have thought of adding aria-label, but other than that nothing crosses my mind
First of all, render your component usable, for example by following NNg’s Back-to-Top Button Design Guidelines. This is a solid basis. Thanks to #outis for the hint.
Here are some accessibility concerns that come to mind with regards to such a Back to top component.
Alternative text/accessible name
Every interactive element needs an accessible name. This text is not only what gets read by a screen reader when focussing the element, but also how voice control can identify the button, as in “Click on back to top”.
Accompanying text for sighted users
Adding a tooltip for sighted users via the title attribute is always a good idea as well, but you should never rely on that attribute to provide an accessible name, as implementation in screen readers is not good.
Even better would be having the text always visible for everyone. Not everyone gets icons correctly.
That way you also provide a very visible hint to voice command users.
The visible part needs to be included in the accessible name (alt text) for this reason. You should add role="presentation" to the SVG if you have accessible text next to it.
This is an example from the GOV.UK Design System Guidelines, who care a great deal about accessibility. They add it just before the footer on long pages.
Contrast
Since you didn’t share your CSS, we don’t know what it does with colours. You need to make sure that the icon and text’s contrast with the background are still 4.5:1 or above.
Avoid icon-fonts
You already got that right. (:
Since users with reading disorders often make their browser use a font they can read well, icon-fonts will break and remove icons that—ironically—would help them most.
Be careful with animated scroll
Often developers (or designers?) like to fly back to the top instead of the instant jump. This can help users orientate.
Nowadays we can simply specify this with scroll-behaviour: smooth and let the browser do the work.
However you implement this, you should be careful to not cause vertigo in people who are sensitive to these zoom animations. Only apply this if the user can and did not set prefers-reduced-motion
Focus
While it is important to include the button in the tab order, it should probably come right before the footer, even when it’s visible all the time.
Focus needs to be visible, of course, as for all interactive elements.
Keyboard users can easily jump back to top by using their Home key, so it’s less important to have the button in early in focus order or after each chapter or something.
When the button disappears when arriving on top, focus needs to be put somewhere else, it must not be “lost” (going to body or html).
Refer to the WCAG
I might have missed some criteria in this answer.
If you want to be sure, you can open up the WCAG-EM Report Tool and start creating a report for your component.
All criteria of the Web Content Accessibility Criteria will need to be audited by you. This is the industry standard for accessible web applications, and legally binding in a lot of states.
You can also add the Title attribute in your anchor tag
<a class="btn-primary" href="#top" title="go to top of page">
When working on the in-page navigation links, we should not forget the screen reader users, so we must ensure they know the purpose of the link. A common way is an aria-label attribute specifying a meaningful value, such as 'Go to top' or 'Back to top'. Once the aria-label is specified, the content of the link should be hidden from the screen reader (Exceptions exist) i.e.: via aria-hidden='true' .
Another detail that should not be forgotten is the focus handling. By default, most of the browsers just scroll the page when using an #Element's_ID for the href if the id does not exist, and SR/Keyboard users will be affected in such a way that after the page is scrolled to top and Tab key is pressed the focus will move to the next focusable element before the page was scrolled up, so, the result will be, an undesired page scroll down.
There is a working implementation in W3C patterns page https://www.w3.org/WAI/ARIA/apg/patterns/.
Hope this helps in your accessibility journey. The a11y world needs lot of people interested on it.
<body id="top">
...
<a class="btn-primary" aria-label="Back to top" href="#top">...
</a>
...
</body>
Say there is piece of text (regardless of whether it is styled as a "traditional" link or button) on a page that when clicked leads to a new page with a new page/URL. But the navigation happens programmatically (e.g. via react-router using the History web API) instead of a hard HTTP refresh.
In this case, should it be a traditional anchor link with href attribute such as # or a button?
Option 1:
<a href="#" onClick={navigateToNextPage}>Link</a>
The downside is that you have a junk href attribute. You could remove that but then it is not in the tab order and doesn't get default link styling (though these could be overcome with one-off styling). Also if you copy the link it will copy as # which is incorrect and be interpreted incorrectly by screen readers.
Option 2:
<button onClick={navigateToNextPage}>Link</a>
The downside here is that if you want it to look like a traditional link you need to apply custom styling. Also in some ways it is really acting like a traditional link in my view. But this would be better for screen readers.
I can't comment on React but here is the correct method for SPAs, implementing it should be trivial in React.
Short Answer
Use a hyperlink (<a>) to navigate between pages and when loading additional content if no other option is available.
More simply: if the URL changes or you add large amounts of information to the page, use a hyperlink.
Long Answer
In your question you mentioned the History API and react-router.
For this reason I assume that the function navigateToNextPage changes the URL.
I also assume that I could access that page directly if I desired by entering that URL into my browser.
With those assumptions in mind you should use:-
<a href="new-page-url" onClick={navigateToNextPage}>Link</a>
Obviously you would stop the default action (e.preventDefault() or React equivalent).
A couple of points on why to use the format described above:-
Accessibility - when I encounter a hyperlink with a screen reader I am able to ask my screen reader where that link will take me, this is reassuring, I can't do the same with a button. This is why I didn't use # for the hyperlink but instead added the actual destination. If you see href="#" it is nearly always a sign that the wrong element is being used or it is being used incorrectly. After reading your comments about performing an action before navigating this is still perfectly valid, perform your action and then redirect, it is still navigation at the end of the day.
Accessibility - when I am navigating a site via a screen reader I may decide to cycle through all the hyperlinks on the page to get a feeling for the page structure. (NVDA modifier + K to get next link for example). I am very unlikely to loop through all the buttons on a page to look for navigation.
Accessibility - If I encounter a link I expect the page to change (even via AJAX). If I encounter a button I expect it to perform an action on the current page. Expected behaviour is a key part of accessibility.
Accessibility - hyperlinks have some important states. 'visited' is a key one on pages with lots of links as I may want to review something I read earlier and being able to navigate via visited links (e.g. NVDA modifier + K for all unvisited links). Buttons do not expose this information. An important point here is that you also can't style a button with button:visited in your CSS so you miss out on the visual clue for everybody there.
Accessibility - Space key vs the Enter key. If I land on a link I am expecting to press space to navigate, a <button> only works with the Enter key and so I may be confused as to why the page isn't changing. (I am assuming at this point you have used a load of aria to convince me this button is a hyperlink).
Robustness - If your site has limited functionality when JavaScript fails a hyperlink is far better than a button. It will still work when JavaScript fails and this is especially useful when a JavaScript failure may only be a temporary load problem with one page, allowing a user to get to another functioning page.
SEO - I dare to speak of SEO on Stack Overflow? Shame! Shame! Shame! :-P - but seriously although Google is pretty darned smart in what it can do on JS powered sites it does still struggle to work out where a JavaScript only link will take it. If SEO matters for you then use a hyperlink with a valid destination so Google can map information correctly.
Probably other reasons I have forgotten to mention but I think I have made the point.
What do you have to consider when using AJAX to navigate between pages?
Although not part of your question I thought I would quickly add a couple of points for completeness.
You need to signal to a user that a page is loading if you are using a SPA pattern (and therefore interrupting normal navigation). e.g. I click your link you need to let me know that an action is being performed (loading.....) as you intercept the normal browser behaviour with e.preventDefault() or equivalent.
The simplest way is to use aria-live=assertive on a region that explains the page is loading. You can Google how to implement that correctly.
Additionally when the new page loads you need to manage focus.
The best way to do this is to add a level 1 heading (<h1>) to each page that has tabindex="-1".
Once the page loads the last action you perform in your JavaScript navigation function is to place the focus onto this heading.
This has two benefits:
it lets the user know where they are now
it also lets them know when the page load is complete (as AJAX navigation doesn't announce when the page is loaded in most screen readers).
By using tabindex="-1" it means that the heading won't be focusable by anything other than your JavaScript so won't interfere with the normal document flow.
You can just do e.preventDefault() when clicked on <NavLink> do your thing. Then navigate. NavLink generates <a> tag in HTML and provide active class by default when route is active. This allow you to style active state link.
import React from "react";
import { NavLink, withRouter } from "react-router-dom";
function Header(props) {
const handleClick = e => {
e.preventDefault();
console.log("DO SOMETHING");
props.history.push(e.target.pathname);
};
return (
<ul>
<li>
<NavLink exact to="/" onClick={handleClick}>
Home
</NavLink>
</li>
<li>
<NavLink to="/about" onClick={handleClick}>
About
</NavLink>
</li>
<li>
<NavLink to="/topics" onClick={handleClick}>
NavLink
</NavLink>
</li>
</ul>
);
}
export const HeaderNav = withRouter(Header);
Wokring example: https://codesandbox.io/s/react-router-5-rqzqq
I would recommend you to use semantic HTML. This means using the correct HTML elements for their intended purpose as much as possible.
Easier to develop with — you can get some functionality for free, plus it is arguably easier to understand.
Better on mobile — semantic HTML is arguably lighter in file size than non-semantic spaghetti code, and easier to make responsive.
Good for SEO — search engines give more importance to keywords inside headings, links, etc., than keywords included in non-semantic
s, etc., so your documents will be more findable by customers.
There's more details
I am trying to scan the body of an email for a confirmation link. I am not sure how to find the right link though.
All interesting e-mails have their link inside the href attribute of an a element, the link sometimes contains one or more of some keywords like "register", "validate", "click", "uid"... and some form of ID. Sadly all don't have those keywords and the IDs also have many different ways they can look.
Do you have any ideas how you can find the right link, maybe something I missed?
While there is no standard for how confirmation links in emails are formatted and it's almost impossible to detect all of them with 100% accuracy, but you can still cover a whole lot.
I think you're moving in the right direction. You can also look for words, if any, inside the anchor tags like; 'Confirm you email,' 'Click here to confirm.' Also the words before and after the anchor tags themselves. Don't just analyse the hrefs apart from their context.
You can go a bit further and open the links that don't fit these criteria then look for certain helping keywords. It's a bit risky, though, as some confirmation links expire after they're opened. So keep that in mind.
A bit advanced approach (and a bit out there TBH) you can apply, if none of the links in an email are identified as confirmation links, could be taking a screenshot from the email itself and someone selects where the confirmation link is then do some analysis on the position of the click then select the corresponding element and get your link. I'm not kidding! you can do it using Puppeteer in a relatively easy way!
Of course you can always use machine learning but you don't wanna go there.
And that's it, I think.
I am trying to implement "Anchor Jumping" functionality using JavaScript and Angular 2 in my application, Means user can jump across the section within a page.
As per the client requirement, User can jump(Navigate) the section using of pressing Ctrl+Shift+Left/Right Arrow key.
Here, I add one snap to clear out the question as below.
As an example, Suppose first time focus on Menu and user press the Ctrl+Shift+Right Arrow at that time focus should be go to next element item(i.e. Breadcrumb section or any section).
I am very confuse about, How to manage the dynamic loading content? (How can I count this dynamic content in my section?)
Please suggest any idea to achieve this functionality.
What you need is a focus manager. I wouldn't bother writing one from scratch, Angular Focus Manager is one example of how to solve this problem. It also incorporates Mousetrap.js, which adds shortcut directives.
Your dynamic content can always be wrapped in something (even a div) that has its focus managed.
I hope this helps!
I'm building something similar to this - http://www.impressivewebs.com/demo-files/content-switcher/content-switcher.html
I wondered if anyone had any ideas as to how I can show the current panel in the navigation WITHOUT using JavaScript - pure CSS.
I'm fairly confidant it's not possible but I thought I'd ask anyway.
Just to clarify...
You'll notice that when you click a link on this page - http://www.impressivewebs.com/demo-files/content-switcher/content-switcher-javascript.html the link you just clicked on highlights to inform the user which panel they're looking at. That's what I want to do in CSS.
It's possible, believe it or not, it's just really tricky. This should get you started: http://thinkvitamin.com/design/css/how-to-create-a-valid-non-javascript-lightbox/ The key bit is captured in this quote:
I'm sure you are all aware of linking to an an element on the same page with the use of the ID attribute and how it works. However, you may not have known that linking to an element that is hidden off the page causes the element to be "pulled" into view as opposed to the window jumping down to that element.
So basically, you'd put all of your slides off-page and then have the numbered links use anchors to pull those into view. Your use case should be a bit simpler than the one she's doing, since you don't have to dim out the rest of the page.
What you need to do is to put what you need to slide inside a container with fixed size and "overflow" property set to hidden.
Then, inside this container, you put your "slidable" contents inside a list of anchor elements with "display" set to block and size the same of the container.
If, from a link on the page, you call one of the anchors in the list, the element with the correspondent anchor name will automgically show up..
simple as that.