I often need to use a step indication to display the step the user is on, or the progress of a package in transit, etc.
Like this:
This is made up of an unordered HTML list.
<ul class="progress-tracker progress-tracker--text progress-tracker--center">
<li class="progress-step is-complete">
<span class="progress-marker"></span>
<span class="progress-text">
<h4 class="progress-title">Step 1</h4>
Summary text explaining this step to the user
</span>
</li>
<li class="progress-step is-complete">
<span class="progress-marker"></span>
<span class="progress-text">
<h4 class="progress-title">Step 2</h4>
Summary text explaining this step to the user
</span>
</li>
<li class="progress-step is-active">
<span class="progress-marker"></span>
<span class="progress-text">
<h4 class="progress-title">Step 3</h4>
Summary text explaining this step to the user
</span>
</li>
<li class="progress-step">
<span class="progress-marker"></span>
<span class="progress-text">
<h4 class="progress-title">Step 4</h4>
Shorter summary text
</span>
</li>
<li class="progress-step">
<span class="progress-marker"></span>
<span class="progress-text">
<h4 class="progress-title">Step 5</h4>
Shorter summary text
</span>
</li>
</ul>
Assuming a new list is loaded on each page (i.e. "step"), is there a way to adapt this for screen readers/assistive technology?
It would be nice to have the reader read the current step to the user, at least.
Are the steps static or can the user click on a previous step to go back?
If the progress indicator is interactive, then enclose the whole thing in a <nav> element. Your progress indicator would be similar to a breadcrumb trail. The <nav> should also have an aria-label and the current step in the process should have aria-current. So it might look something like:
<nav aria-label="progress">
<ul class="progress-tracker progress-tracker--text progress-tracker--center">
<li class="progress-step is-complete">
...
</li>
<li class="progress-step is-complete">
...
</li>
<li class="progress-step is-active" aria-current="true">
...
</li>
...
</ul>
</nav>
However, your code snippet didn't include any links so I'm guessing your progress indicator is static and not interactive. In that case, don't use a <nav>, because you can't navigate with your indicator, but you could still group the elements together. Having an unordered list is a type of grouping, but sometimes a screen reader will not read the aria-label on a list.
<ul aria-label="progress">
You could work around the issue by having:
<div role="group" aria-label="progress">
<ul>
<li>
...
</li>
</ul>
</div>
(essentially replacing the <nav> in the first example with <div role="group">.
Since your progress indicator is a series of steps, using an ordered list <ol> would have better semantic information. You can style the list so the default numbers of a <ol> are not displayed (similar to how you're not showing bullet points with the <ul>).
And finally, I would add some "hidden" text for the screen reader to say if the step is completed or not. Visually, you have blue circles for completed steps, an open circle for the active step, and gray circles for not completed. That's all done with CSS (your "is-complete" and "is-active" classes). That same context should be conveyed to screen readers. The open circle ("is-active") is conveyed with the aria-current attribute. Use a "sr-only" type class to add text for a screen reader. (See What is sr-only in Bootstrap 3?)
<div role="group" aria-label="progress">
<ol class="progress-tracker progress-tracker--text progress-tracker--center">
<li class="progress-step is-complete">
<span class="sr-only">completed</span>
...
</li>
<li class="progress-step is-complete">
<span class="sr-only">completed</span>
...
</li>
<li class="progress-step is-active" aria-current="true">
...
</li>
<li class="progress-step">
<span class="sr-only">not completed</span>
...
</li>
...
</ol>
</div>
In summary, the minimal changes you need are to:
maybe switch from <ul> to <ol>
add "sr-only" text to the "completed" and "not completed" items
add aria-current to the current step
I disagree with the answers that were previously added to this question.
The correct way of identifying the current step is with aria-current="step".
While aria-current="page" is valid, is meant to be used in a set of links (for exemple, a breadcrumbs widget or a pagination widget).I highly recommend reading more about the aria-current attribute, including its possible values and when to use it. Your example would then look like follows:
<ol>
<li>Step 1 ... </li>
<li>Step 2 ... </li>
<li aria-current="step">Step 3...</li>
<li>Step 4 ... </li>
<li>Step 5 ... </li>
</ol>
Note: I also recommend you use an <ol> instead of an <ul> as this list of steps has an order.
It doesn't look like any of your content is focusable. I had a similar situation that I've shipped in our angular app that works great with JAWS, NVDA, and VoiceOver. What you can do is wrap your markup in a 'div' container and screen reader specific content like this.
<div>
<span class="sr-only">Step 3 of 5: Summary text explaining this step to the user</span>
...
</div>
The 'sr-only' class hides the copy from the visual UI but allows for screen readers to "see" it in the accessible tree.
.sr-only {
border: none;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
It's important to only make the content available for the step that is currently active.
Hope this helps.
Related
I have a lengthy list of buttons that I want to make WCAG compliant. Many of the items have endnotes (marked with an asterisk) as below. What is the proper way to provide the accessible description for these endnotes?
As far as I know, some browsers are not reading aria-describedby on not focusable elements.
<ul aria-describedby="list_description">
<li><button>Element **</button></li>
<li><button>Element</button></li>
<li><button>Element *</button></li>
<li><button>Element</button></li>
<li><button>Element *</button></li>
<li><button>Element *</button></li>
<li><button>Element **</button></li>
<li><button>Element</button></li>
<li><button>Element</button></li>
<li><button>Element *</button></li>
<li><button>Element **</button></li>
</ul>
<p id="list_description">
* - Important element <br>
** - Very important element
</p>
I was thinking about the solution described here: Accessibility and asterisks end notes, but placing <a> inside <button> doesn't seem right.
Another way is to provide duplicated descriptions for every list item.
What would you suggest to approach it?
placing <a> inside <button> doesn't seem right
Not only does it not feel right, it's not valid html :-) If you look at the <button> spec, under "content model", it says "there must be no interactive content descendant". An <a> is interactive so is not allowed inside a button.
Since you already have the text on the page that documents what * and ** mean, I would put IDs on those elements and then refer to them in the aria-labelledby attribute on each button.
I would also "hide" the * and ** in the button text from the screen reader since the user doesn't need to hear "star" or "star star". You do this with aria-hidden.
The final solution would be:
<ul>
<li>
<button id='b1' aria-labelledby='b1 vimportant'>Element
<span aria-hidden="true">**</span>
</button>
</li>
<li>
<button id='b2' aria-labelledby='b2'>Element</button>
</li>
<li>
<button id='b3' aria-labelledby='b3 important'>Element
<span aria-hidden="true">*</span>
</button>
</li>
<li>
<button id='b4' aria-labelledby='b4'>Element</button>
</li>
<li>
<button id='b5' aria-labelledby='b5 important'>Element
<span aria-hidden="true">*</span>
</button>
</li>
</ul>
<p id='important'><span aria-hidden="true">* - </span>Important element</p>
<p id='vimportant'><span aria-hidden="true">** - </span>Very important element</p>
Note, for consistencies sake, I put IDs on all the buttons and used aria-labelledby on all the buttons even though the buttons without a footnote don't really need them. It kind of makes for some silly code to have a button labeled by itself but it makes it easy to add other footnotes or have some simple text that is applied to the "not important" elements. If that's not likely, then you can remove the IDs and aria-labelledby on the simple buttons:
<ul>
<li>
<button id='b1' aria-labelledby='b1 vimportant'>Element
<span aria-hidden="true">**</span>
</button>
</li>
<li>
<button>Element</button>
</li>
<li>
<button id='b3' aria-labelledby='b3 important'>Element
<span aria-hidden="true">*</span>
</button>
</li>
<li>
<button>Element</button>
</li>
<li>
<button id='b5' aria-labelledby='b5 important'>Element
<span aria-hidden="true">*</span>
</button>
</li>
</ul>
<p id='important'><span aria-hidden="true">* - </span>Important element</p>
<p id='vimportant'><span aria-hidden="true">** - </span>Very important element</p>
I'm just learning html to build a team site at work. I'm getting the hang of it pretty easily, but I'm having an issue with subfolders not showing in a dropdown. The html is linked to css for a design, but I know the problem isn't with the css.
I'm not exactly sure what to try as I mentioned I am just learning how to code the html.
<li class="top"><span class="down">Folders</span>
<ul class="hsolinks">
<li><span class="down">HIPAA Security Office</span></li>
<ul class="hsolinks">
<li>Access</li>
<li>Audit</li>
<li>LAN File Access</li>
<li>Training</li>
</ul>
The expected result is that the folders "ACCESS", "AUDIT", "LAN FILE ACCESS", and "TRAINING" would show under the HIPAA Security Office in a css dropdown. However, when I place the code into SharePoint it only shows an arrow, but no folders in the dropdown under HIPAA Security Office.
Also, there is additional code under this which is why I have only closed one ul tag. I hope I'm clear with what I'm trying to do!
The <li> element always needs to be surrounded by a <ul> element. But you can have a <ul> inside an <li> if needed. Something like so will work
<ul>
<li class="top">
<a href="#nogo4" id="hsolinks" class="top_link">
<span class="down">Folders</span>
</a>
<ul class="hsolinks">
<li>
<a href="#" target="_parent" class="hsolinksfly">
<span class="down">HIPAA Security Office</span>
</a>
<ul class="hsolinks">
<li>
Access
</li>
<li>
Audit
</li>
<li>
LAN File Access
</li>
<li>
Training
</li>
</ul>
</li>
</ul>
</li>
</ul>
For more information and examples about the <ul> <li> elements read: ul: The Unordered List element
This question already has answers here:
Is there a CSS parent selector?
(33 answers)
Closed 4 years ago.
I want to find every Child-node of an element thats in the n-th position, eg. in:
<span class="passive match" id="1"></span>
<ul>
<li>
<span class="active match"></span>
<ul>
<li>
<span class="active match"></span>
</li>
</ul>
</li>
</ul>
<span class="passive match" id="2"></span>
<ul>
<li>
<span class="passive match"></span>
<ul>
<li>
<span class="active"></span>
</li>
</ul>
</li>
</ul>
I want to find both "active match" li Child of the ul next to the span "passive match"
Something like:
span.passive.match + ul:'has-Child'(span.active.match) {CSS here}
But the corresponding span.active.match can be a 3rd/6th/9th/12th etc. child-element from "passive match". Is there a CSS-Selector that can handle this or do I need to write a jQuery-Script that does it (which would be inefficient I'd say as I would need a recursive function that may run across 10k+ elements)?
Basically i have a tree filled with folders (.passive) and data (.active) and i want to display every data thats matched with a given filter (.match) and its path but want to hide every folder that has no child thats matching the filter. So the span with id="2" should be hidden, while the id="1" should show up in my dom structure. As the tree is generated by a plugin with private function and is used in multiple situation i cant just edit/ overwrite it but have to either use the CSS-Selectors to hide the unnecessary objects or use a javascript-script to do so. Maybe you'll have a better idea.
For this you need the :has() pseudo-class…
span.passive.match + ul:has(span.active.match)
… but it is not a standard (it is in draft status) and no browser currently supports it.
In the meantime, alter your HTML so there is a class on the ul.
Ideally, do this when you generate the HTML, but you could modify it after the fact with JavaScript.
$(".active.match").parents("ul").addClass("contains-active-match");
span.passive.match + ul.contains-active-match {
background: pink
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="passive match" id="1">a</span>
<ul>
<li>
<span class="active match">b</span>
<ul>
<li>
<span class="active match">c</span>
</li>
</ul>
</li>
</ul>
<span class="passive match" id="2">d</span>
<ul>
<li>
<span class="passive match">e</span>
<ul>
<li>
<span class="active">f</span>
</li>
</ul>
</li>
</ul>
So I'm learning web development on my own since I'm a CS major and it appears that my school doesn't have an option for that in cs (IT only). Right now I've been using youtube, Microsoft virtual academy, codecademy(not pro), and khan academy. Kind of besides the point but my question is I have pills in bootstrap, I want to have a list under each pill that's only accessable by clicking on that pill. The way I have it setup is that the pill is a shortcut to the list that is further down the page, is there a way for me to hide the lists so that they're only specific to the active pill without me having add each lists down the page, using html,css, or bootstrap? This is what I've been working with, I haven't moved on to js or php or any scripting, I do know python but I don't know how to implement scripts in html yet.
code below
<ul class = "nav nav-pills">
<li class ="active"> Engineering </li>
<li> Medical </li>
<li> Education </li>
<li> Jobs for students </li>
</div>
</div>
<div class ="eng-company-list">
<div class = "container">
<ul id="engineering-positions">
<li> Google </li>
<li> Amazon </li>
<li> Facebook </li>
<li> Twitter </li>
<li> Pandora </li>
<li> Dropbox </li>
<li> Pinterest </li>
<li> Khan Academy </li>
<li> Zynga </li>
<li> EA </li>
<li> Sony </li>
<li> Intel </li>
</ul>
</div>
</div>
<div class ="edu-list">
<div class ="container">
<ul id = "edu-positions">
<li> newitem </li>
<li> newitem </li>
<li> newitem </li>
<li> newitem </li>
<li> newitem </li>
<li> newitem </li>
</div>
</div>
like right now I click on the Engineering pill and it displays the eng-position list AND the edu-positions list, what I want to do is hide the edu-positions list from engineering and subsequently Jobs for students, Medical, etc.
You can use the display: none; css property: value pair on a default element and psuedo classes.
For example, name each container uniquely. (e.g. engineering-container, edu-container) and set css property "display" to "none" on both. Use relative positioning in your css and define the positions in which the container will reside. You can also use x-index values to place the container behind your main container.
Then use the :hover pseudo class on your primary navbar and the hidden containers to make it show. Set the :hover display values to block. So when you hover over the navbar tag "engineering", the list will also expand and show for the list you've associated with the engineering navbar link.
Sorry for not giving you a step-by-step details, but it can be done with just css. It would be easier with jQuery. But as the remark made in an earlier comment, you should learn css layout first. It will make you a better developer and you will need to know it pretty well if you're going to become a developer.
So, since you don't know js, I highly recommend you look into CSS psuedo classes. With it, you can get a navigation list to expand and retract. You will have to just make sure that the :hover includes your links else it will retract once you move off the div because it no longer the active element.
Try this:
<header id="navigation" class="nav nav-pills">
<ul class="menu-content" style="display: none;">
<li class="menu-link active">Engineering</li>
<li class="menu-link">Medical</li>
</ul>
</header>
And at end of body tag paste this:
<script type="text/javascript">
function showhide() {
var nav = document.getElementbyId('navigation');
if(nav.style.display == 'none') {
nav.style.display = 'block';
} else {
nav.style.display = 'none';
}
}
</script>
Or I found 100% open-source example of navigation which you want by Bootstrap on github https://github.com/BlackrockDigital/startbootstrap-logo-nav.
I am trying to develop/design a main menu/site map for our website.
The brief is that the menu should look like a directory tree and each item on the menu should either expand to reveal more menu items or link to another page on the site.
On top of this, every item should have the functionality to be added to the sites "Favourites" application, so that every user can more quickly find items that are buried deep within the menu structure.
Because of my insane OCD to make sure that everything is done correctly and to the best possible standards, I am having issues getting my markup to be semantically correct and accessible.
Here's what I've got so far:
<ul>
<li>
<ul>
<li>
Collapse "Menu Item 1"
</li>
<li>
Add "Menu Item 1" to Favourites
</li>
<li>
Menu Item 1
<ul>
<li>
<ul>
<li>
<a href="example3.html">Open "Menu Item 1's
First Child"</a>
</li>
<li>
<a href="example4.html">Add "Menu Item 1's
First Child" to Favourites</a>
</li>
<li>
<a href="example3.html">Menu Item 1's First
Child</a>
</li>
</ul>
</li>
<li>
<ul>
<li>
<a href="example5.html">Open "Menu Item 1's
Second Child"</a>
</li>
<li>
<a href="example6.html">Add "Menu Item 1's
Second Child" to Favourites</a>
</li>
<li>
<a href="example5.html">Menu Item 1's Second
Child</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
Expand "Menu Item 2"
</li>
<li>
Add "Menu Item 2" to Favourites
</li>
<li>
Menu Item 2
</li>
</ul>
</li>
<li>
<ul>
<li>
Open "Menu Item 3"
</li>
<li>
Add "Menu Item 3" to Favourites
</li>
<li>
Menu Item 3
</li>
</ul>
</li>
</ul>
As you can see, things start to get very complicated very quickly.
Is this the best way to convey this information or am I over complicating the matter?
Can you think of a better way for me to do this?
IMO you're using this list wrong. Collapse/Open/Add to favs... these elements don't belong to the tree, but you treat them as if they were part of it.
Your tree should has following structure:
<ul>
<li>
<span>menu item 1<span>
<ul>
<li>
<span>child node 1</span>
</li>
<li>
<span>child node 2</span>
</li>
</ul>
</li>
...
</ul>
That's the base of the tree. Now you should add actions (open/add... etc.). They might by placed as another, independent list after span element. Then just use class to separate childNodes list from actions list:
...
<li>
<div>
<span>menu item 1</span>
<ul class="actions"> ... </ul>
</div>
<ul class="childNodes"> ... </ul>
</li>
...
Well... in theory classes aren't required but it's much easier to handle with classes rather ... ul > li > div > ul selectors etc.
According to first comment
Base functionality of the website shouldn't rely on JavaScript. That's why I thing addition of whole tree using JS is bad idea. Actions like add to favs should be available without JS, but you may feel free to take control over that action, and overwrite it's functionality. So in HTML you have:
Add to favs
But using JS you do something like this (pseudo-code):
actionLink.addEventListener("click", function...
var id = take id: 123
do ajax request here
return false;
});
It's the best way to provide good availability and functionality at the same time.
About open/collapse actions. These requires JS by their nature so they can be added to actions list by JS. But once again... remember about "non-JS users". HTML/CSS should display a whole tree - JS should collapse its branches.
Sometimes I do as per Crozin's answer above but on a large site it can be impossible to load such a large tree (I have built systems for sites with over 100k pages).
A hybrid solution is to load in the tree so that the path down to the parent page only contains the current path and then display all the children of the parent. Then add JavaScript behaviour to add additinal parts of the tree.
Doing things this way means that non JS browsing can completely navigate the site but JS browsing gets the enhance functionality, all without the performance hit of building the entire tree.