Closed QuincyLarson closed 8 years ago
This could be a good resource: https://www.youtube.com/watch?v=HtTyRajRuyY
@zersiax We hope to cover tips for coding for screen readers in detail. If you have any advice for specific HTML and CSS properties we should teach, please add as much detail as possible on a comment here. Thanks!
Hi folks,
I was wondering if I could help out on these challenges - I'm new to the process and don't want to step on any toes or duplicate work if someone is already working on this topic. I've been reading through the W3C's web content accessibility guidelines here that group 12 guidelines into 4 major principles, and I think it could be a useful resource in the wiki. Also, it could provide another layer of organizational structure around the challenges listed above. I'm not sure there's an appropriate coding challenge for every one of these items, but a lot of the challenges already fall neatly into the buckets, listed below for reference:
1) Perceivable Information and User Interface
2) Operable User Interface & Navigation
3) Understandable Information and User Interface
4) Robust Content and Reliable Interpretation
Let me know how I can be helpful - I don't want to create work and can reorder items, or start working on the list as you see fit.
Cheers, Heather / @hkuz
@HKuz yes - we could certainly use your help. I created the list based on my pre-existing knowledge, but if you have time to do further research, you can resequence and expand upon my above list - and even help design some of them.
Here's a topic that's well underway, which has good examples of instructions, code, and tests: https://github.com/FreeCodeCamp/CurriculumExpansion/issues/27
About how much time do you think you would have over the next week or so to contribute to this?
Sounds good! The current list is great, let me dive into the guidelines more and make sure I understand all the challenges and how they'd fit. I'll put any re-order thoughts on paper and post them here by the end of the weekend. I also want to look more into the ARIA attribute suite and how it applies to hidden/collapsible/dynamic content (there may be a challenge or two there), and using tabindex
for keyboard navigation.
Thanks for including a link to the other topic, having examples to work off of is a huge help.
In terms of time, I can commit to 20 hours over the next week to start, and can likely up that as needed.
Good to see this is being picked up. Let me take your list and add my thoughts:
Add Alt Text to Images for Visually Impaired Accessibility // If I remember correctly, this one's already in the HTML curriculum. We do need to make sure we practice what we preach and use alts consistently ourselves in the website as well as the challenges
Know when you should not add alt text (when a picture is already explained, do alt='') // I'd like to nuance that alt= is mandatory according to HTML5 spec. So any image should have this attribute, even if you leave it blank. Image alts may be left blank when no additional info can be gleaned from them; think decorative imagery and, as stated, images that already have a textual caption
Jump Straight to the Content Using the Main Element // This is an interesting one, a point of a lot of discussion. Overall though you are right, a page should only have one main element that encompasses the main content of the website Highlight Content Using the Article Element // this title looks a little strange, in what way are you intending to highlight content just by using this semantic marker?
Improve the Accessibility of your Header with the Header Element // this one, as well as nav and footer, add so-called landmarks to a page that can be jumped between. Not sure if you want to make it three separate tests, maybe take header and footer in one Improve the Accessibility of your Navigation with the Nav Element //This title seems a bit general, adding a nav element doesn't actually increase the accessibility of your navigation bar, it just makes it easier to reach Improve Accessibility by Adding Notes with the Footer element // ehm ...no, not quite ...the footer element is literally meant for a website's footer. The bit that holds things like the copyright info, social media links, maybe terms and conditions. Not so much for adding notes to an existing page Improve Chart Accessibility with the Figure Element // I'd like to see how you fill this one in Improve Video Accessibility with the Video Element // In what way do you intend to improve access by using this element? Do you mean improving access by using html5 video instead of flash, or?
Improve Chart Accessibility with the Audio Element // You ...want to make an auditory representation of a chart? Ambitious :) Improve Form Field Accessibility with the Label Element (use the "for" property) // This one is prett important, but you might want to add it within the material on general form fields. There's not really any valid reason not to use the for-attribute Wrap Radio Buttons in a Label Element for Better Accessibility (use the "for" property) // Consult webaim for this one, radiobuttons have their own little trickery Add Subtitles to a Video to Improve Accessibility // yup, although that is usually not the responsibility of a web developer Specifiy Time in Screen Reader Friendly Way // what do you mean? Add a Date Picker // which is accessible? I'd love to hear more Add Screen Reader Only Attributes (with aria-hidden?) // No ...aria-hidden actually hides things from screenreaders. If you want to get elements to show only for screenreaders, you visually hide them by giving the element a width and height of 1 in css and/or moving it out of the viewport by using negative css properties. Again, consult webaim for this. Standardize Times with the DateTime HTML5 Property // no experience with this element Improve readability with high contrast text // Might want to talk about the contrast ratio of 4.5 to 1 specified by WCAG Make Links Navigatable with HTML Access Keys // interesting tidbit, wouldn't have thought of that one myself Avoid Colorblindness Colors (using close colors to convey important information) // Doesn't this one link up with the contrast one earlier?
There's two important ones missing here, on first glance. Not sure how you will want to test for them though:
Phew, long comment. If there are questions, definitely send them my way.
@zersiax thanks for your input and detailed response, your commentary is really helpful. It sounds like a few of the challenges may warrant further discussion or need some clarification. Looking over the list again after reading your points, it seems that there are three main messages or goals we're trying to impress on the campers with these challenges:
1) Make visual content accessible to users. The challenges about having text alternatives for non-text content, improving readability with appropriate contrast, not using color alone to convey important information, and avoiding color-blindness colors are examples of this theme. Your points about the alt attribute being mandatory and the 4.5 to 1 contrast ratio would be covered in the challenge text where they are applicable. 2) Use appropriate markup to add semantic meaning to content. This is done with HTML elements and/or attributes and is the bulk of the list - why and when to use the HTML5 elements, the form attributes, the nav/header/footer elements having landmarks that make them easier to navigate, and the date and time ones. The two new points about link text and headings fit here, too. 3) Make sure a site's navigation is keyboard-friendly. The challenge for the access keys and any new ones for tabindex reinforce this.
Potential new challenges (thoughts and comments welcome):
I do have a question about whether we should incorporate any challenges introducing the ARIA suite. I fell down a rabbit hole today reading the ARIA authoring practices page and see that it's a deep topic with lots of different options and applications. Given its use to make dynamic or collapsible content accessible with screen readers in particular, there may be value in introducing the topic to campers. Is it worth having a couple simple examples to explain a few key concepts and properties? For example, using role
when an element is used in a different way than expected (a div
is a button) or aria-labelledby
to tie collapsible content to its heading. With the current timeline for the curriculum changes, another option is to add this topic in later if we want it.
Oddly enough, that authoring practices page had a date picker example in it :) although at a couple hundred lines of code, it didn't lend itself to a challenge very well...
@zersiax Thank you for your detailed feedback on these challenge titles. I've carefully incorporated all of your feedback into my original comment
Also, if anyone's curious, here's the accessibility wiki article @zersiax is referring.
@HKuz I've added your new proposed challenges (including those two based off of @zersiax's feedback) to the list of challenges.
@HKuz there's a built in HTML5 datepicker that requires almost no code.
Also, my understanding is that most of the really important aspects of the ARIA suite have already been incorporated into HTML5 and are usable in modern browsers. If this is the case, perhaps we could skip discussion of the ARIA features altogether for the sake of simplicity.
It's worth pointing out that Free Code Camp's curriculum aims doesn't need to cover expert topics beyond those necessary for a solid foundation in a give topic. So many accessibility concepts may be a bit advanced for our campers. We should focus on the "low hanging fruit" concepts.
@hkuz What you are running into when it comes to the rabbit hole is the fact that when we are referring to ARIA, we really aren't talking about HTML anymore. ARIA as you probably know stands for Accessible Rich Internet Applications and the concept of a RIA in computer science lingo tends to be a web application, single-page application, that kind of thing. So ARIA is so vast because there's a huge amount of things you can do in the front-end these days, and it really is meant as a last resort. So ...as for including or excluding it from the FCC curriculum, here's a few considerations that may help you guys:
I hope this is clear so far. If you guys would rather sit down and have a meeting over something like Skype about this I'd be willing to do that, just let me know.
@zersiax and @QuincyLarson thanks for the clarification, especially on ARIA. I didn't realize a lot of its key aims were already incorporated into HTML5, so it makes sense to keep the emphasis where it is in the challenges. Sounds like next steps are to start crafting the challenges based on the list, which I can get started on. The first one will probably take the longest, as I'll need to look at other examples under the other topics and figure out the testing. I think I saw August 23rd mentioned in the chat room as the next deadline to start getting challenges into the seed code - honestly, I doubt I can get all of these done by then myself, but I'll start plugging away we can see where things stand later this week. Let me know if there's anything I'm missing. Thanks!
@zersiax @HKuz My understanding is HTML5 continually incorporates new aspects of ARIA as is practically possible, and ARIA is kind of the pioneering front of accessibility features. Does this mesh with your understanding of the technology?
@zersiax great observation about the changing text on Free Code Camp. I agree - it sounds like we should use live areas on our tests and on our code output element. Would you be interested in creating an issue for this and describing how you think it should ideally work?
@HKuz August 23rd is an ideal date, but we have some flex because I will be inputing these into the seed code myself, and I can only tackle one section at a time. I would say you have up until August 30 or so. At some point, we will cut off unfinished challenges and have to ship them at a later date (whenever we add new challenges, it causes mass confusion, so we only do this a few times a year).
Thanks @QuincyLarson - that timeline is doable. I just finished a handful of challenges on another topic, so I'll get cranking on these.
@zersiax I'll be working on these in batches and posting a set when I'm decently happy with it. Your comments so far have been really helpful, if you don't mind reviewing what I work on and making sure an explanation isn't a total whiff, or the coding example doesn't inadvertently show dated/bad practices, that would be awesome. None of that role=button stuff sneaking through! Haha, alright, I'll be in touch gentlemen.
First batch in the queue. The introduction blurb I wrote for the section ended up being too long to include in one of the challenges. so I split it out. There isn't a code challenge to it (I know that's a goal of keeping them interactive), so feel free to include or not.
"Accessibility" generally means having web content and a user interface that can be understood, navigated, and interacted with by a broad audience. This includes people with visual, auditory, mobility, or cognitive disabilities.
Websites should be open and accessible to everyone, regardless of a user's abilities or resources. Some users rely on assistive technology such as a screen reader or voice recognition software. Other users may only be able to navigate through a site using a keyboard. Keeping the needs of various users in mind when developing your project can go a long way towards creating an open web.
Here are three general concepts we'll explore more throughout the following challenges:
Having accessible web content is an ongoing challenge. A great resource for your projects going forward is the W3 Consortium's Web Content Accessibility Guidelines (WCAG). They set the international standard for accessibility and provide a number of criteria you can use to check your work.
assert(true, 'message: Carry on')
It's likely you've seen an alt
attribute on an img
tag in other challenges. Alt
text describes the content of the image and provides a text-alternative in case the image fails to load or can't be seen by a user. It's also used by search engines to understand what an image contains to include it in search results. Here's an example:
<img src="importantLogo.jpeg" alt="Company logo">
People with visual impairments rely on screen readers to convert web content to an audio interface, and won't get information if it's only presented visually. For images, screen readers can access the alt
attribute and read its contents to deliver key information.
Good alt
text is concise but descriptive, and meant to briefly convey the relevant meaning of the image. When should you include an alt
attribute on your image? Always! Per HTML5 specification, this is now considered mandatory.
CamperCat happens to be both a coding ninja and an actual ninja, and is building a website to share his knowledge. The profile picture he wants to use showcases his skills, and should be appreciated by all site visitors. Add an alt
attribute in the img
tag, that explains CamperCat is doing karate.
<img src="doingKarateWow.jpeg">
assert($('img').attr('alt'), 'message: Give the <code>img</code> tag an <code>alt</code> attribute, and make sure it is not empty.');
<img src="doingKarateWow.jpeg" alt="CamperCat doing karate">
In the last challenge, you learned that including an alt
attribute on img
tags is mandatory. However, sometimes images are grouped with a caption already describing them, or are used for decoration only, and alt
text may seem redundant or unnecessary. In situations when an image is already explained with text content, or does not add meaning to a page, the img
still needs an alt
attribute, but it can be set to an empty string. Here's an example:
<img src="visualDecoration.jpeg" alt="">
Background images usually fall under the 'decorative' label as well, but they are typically applied with CSS rules, and are therefore not part of the markup that screen readers process.
CamperCat has coded a skeleton page for the blog part of his website below. He's planning to add a visual break between his two articles with a decorative image of a samurai sword. Add an alt
attribute to the img
tag in the code below and set it to an empty string.
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>To Come...</p>
</article>
<img src="samuraiSwords.jpeg">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>To Come...</p>
</article>
<footer></footer>
assert(!($('img').attr('alt') == undefined), 'message: Make sure to add an <code>alt</code> attribute to the <code>img</code> tag.');
assert($('img').attr('alt') == "", 'message: The <code>alt</code> attribute should be set to an empty string.');
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>To Come...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>To Come...</p>
</article>
<footer></footer>
Headings (h1
through h6
elements) are workhorse tags that help provide structure and labeling to your content. Given these characteristics, screen readers can be set to read only the headings on a page so the user gets a summary. This means it is important for the heading tags in your markup to have semantic meaning and relate to each other, not be picked merely for their size values. If you were writing a paper with an introduction, a body, and a conclusion, you wouldn't put the conclusion as a subsection of the body in your outline, right? Similarly, the heading tags in a webpage need to go in order and indicate the hierarchical relationships of your content - ones with equal (or higher) rank start new implied sections, headings with lower rank start subsections of the previous one.
As an example, a page with an h2
element followed by several subsections labeled with h4
tags would confuse a screen reader user. With six choices, it's tempting to use a tag because it looks better in a browser, but you can use CSS to edit the relative sizing.
One final point, your page should always have one h1
element, which is the main subject of your content.
CamperCat wants a page dedicated to becoming a ninja and has some ideas in place. Help him fix the headings so his markup gives semantic meaning to the content, and shows the proper parent-child relationships of his sections. Change all the h5
tags to the proper heading level to indicate they are subsections of the h2
ones.
<header>
<h1>How to Become a Ninja</h1>
</header>
<main>
<h2>Learn the Art of Moving Stealthily</h2>
<h5>How to Hide in Plain Sight</h5>
<h5>How to Climb a Wall</h5>
<h2>Learn the Art of Battle</h2>
<h5>How to Strengthen your Body</h5>
<h5>How to Fight like a Ninja</h5>
<h2>Learn the Art of Living with Honor</h2>
<h5>How to Breathe Properly</h5>
<h5>How to Simplify your Life</h5>
</main>
<footer></footer>
assert($('h3').length === 6, 'message: Make sure to replace the <code>h5</code> tags with <code>h3</code> tags');
assert($('h5').length === 0, 'message: Make sure to replace all the <code>h5</code> tags on the page.')
<header>
<h1>How to Become a Ninja</h1>
</header>
<main>
<h2>Learn the Art of Moving Stealthily</h2>
<h3>How to Hide in Plain Sight</h3>
<h3>How to Climb a Wall</h3>
<h2>Learn the Art of Battle</h2>
<h3>How to Strengthen your Body</h3>
<h3>How to Fight like a Ninja</h3>
<h2>Learn the Art of Living with Honor</h2>
<h3>How to Breathe Properly</h3>
<h3>How to Simplify your Life</h3>
</main>
<footer></footer>
@HKuz you're off to a great start! We are creating a special "section intro" type of challenge and can use your intro text for it :)
@HKuz looking good so far :) I did notice a number of small spelling errors particularly in the introduction but not sure if you're going to spell-check them all together in the end? :)
@QuincyLarson no ...not quite. ARIA is as I said more of a way to map non-semantic elements like divs, spans or similar to correct semantic roles like headings or buttons. It's also used to convey for example that a part of a webpage should be treated as an application rather than a web page which has a significant effect on how a screen reader renders it. Especially in those kinds of cases, it becomes very important to have your ARIA properties set correctly because a screen reader user will almost entirely rely on tab and shift+tab and the arrow keys to navigate that portion of the web app. If your form field doesn't have an aria-labeledby this would force a screen reader user to use advanced navigation commands to check what they are supposed to fill in on every single field, and a lot of screen reader users don't even know these commands. A typical example of somewhat non-standard HTML5 ARIA that doesn't directly map to HTML5 is making a treeview accessible, illustrated here: http://oaa-accessibility.org/example/42/
Whoops, thanks @zersiax! I had the spell check turned off in my text editor, giving me the false impression that my typing accuracy was amazing. I'll go back and edit the posts, and check as I go from here out.
HTML5 introduced a number of new elements that give developers more options while also incorporating accessibility features. These tags include main
, header
, footer
, nav
, article
, and section
, among others. By default, a browser renders these elements similarly to the humble div
, but using them where appropriate layers additional meaning in your markup. The tag name alone can indicate the type of information it contains, which adds what is called semantic meaning to that content. Assistive technologies can access this information to provide better page summary or navigation options to their users.
The main
element is used to wrap (you guessed it) the main content, and there should be only one per page. It's meant to surround only the information that's related to the central topic of your page, and not include items that repeat across pages, like navigation links or banners. This tag also has an embedded landmark feature that can be used by assistive technology to quickly navigate to the good stuff. If you've ever seen a "Jump to Main Content" link at the top of a page, using a main
tag automatically gives assistive devices that functionality now.
CamperCat has some big ideas for his ninja weapons page. Help him set up his markup by adding opening and closing main
tags between the header
and footer
in the code below. Keep the main
tags empty for now.
<header>
<h1>Weapons of the Ninja</h1>
</header>
<footer></footer>
assert($('main').length == 1, 'message: Add one <code>main</code> element to the page.');
assert(code.match(/<\/header>\s*?<main>\s*?<\/main>/gi), 'message: Place the <code>main</code> element between the <code>header</code> and <code>footer</code>.');
<header>
<h1>Weapons of the Ninja</h1>
</header>
<main></main>
<footer></footer>
We mentioned article
as one of the new HTML5 elements that adds semantic meaning to your markup in the last challenge. Articles
are sectioning elements, and are used to wrap independent, self-contained content. The tag works well with blog entries, forum posts, or news articles. Determining whether content can stand alone is usually a judgement call, but there are a couple simple tests you can use. Ask yourself if you removed all surrounding context, would that content still make sense, or similarly for text, would the content hold up if it were in an RSS feed?
Remember that folks using assistive technologies rely on organized, semantically meaningful markup to better appreciate your work.
A note about section
and div
:
The section
element was also added with HTML5, and has a slightly different semantic meaning than article
. Where article
is for standalone content, section
is for grouping thematically related content. They can be used within each other, as needed. For example, if a book is the article
, then the chapters are the sections
. When there's no relationship between groups of content, then use a div
.
div
- blocks content
section
- blocks related content
article
- blocks independent, self-contained content
Astute campers may have noticed that CamperCat used article
tags to wrap the posts on his blog page, but he forgot to use them around the top one. Change the div
tag to use an article
tag instead.
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<div>
<h2>The Garfield Files: Lasagna as Training Fuel?</h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-NOM trifecta that is lasagna...</p>
</div>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer></footer>
assert($('article').length == 3, 'message: There should be three separate <code>article</code> elements in the markup.');
assert($('div').length == 0, 'message: Change the <code>div</code> tag to an <code>article</code> tag.');
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>The Garfield Files: Lasagna as Training Fuel?</h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-NOM trifecta that is lasagna...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer></footer>
The next HTML5 element that adds semantic meaning and improves accessibility is the header
tag. It's used to wrap introductory information or navigation links for its parent tag, and works well around content that's repeated at the top on multiple pages. Header
shares the embedded landmark feature we saw with main
, allowing assistive technologies to quickly navigate to that content.
Note:
Header
is meant for use in the body
tag of your HTML document. This is different than the head
element, which contains the page's title
, meta
information, etc.
CamperCat is writing some great articles about ninja training, and wants to add a page for them to his site. Help him fix the top div
that currently contains the h1
to a header
tag instead.
<body>
<div>
<h1>Training with CamperCat</h1>
</div>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
</body>
assert($('header').length == 1, 'message: Make sure to use a <code>header</code> tag instead of the <code>div</code> tag around the <code>h1</code>.');
assert($('div').length == 0, 'message: Change the <code>div</code> tag to a <code>header</code> tag.');
<body>
<header>
<h1>Training with CamperCat</h1>
</header>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
</body>
The nav
element is another item in the HTML5 suite with the embedded landmark feature for easy screen reader navigation. This tag is meant to wrap around the main navigation links in your page. If there are repeated site links at the bottom of the page, it isn't necessary to markup those with a nav
tag as well, using a footer
(covered in the next challenge) is sufficient.
CamperCat included navigation links at the top of his training page, but wrapped them in a div
. Change the div
to a nav
tag to improve the accessibility on his page.
<body>
<header>
<h1>Training with CamperCat</h1>
<div>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</div>
</header>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
</body>
assert($('nav').length == 1, 'message: Make sure to use a <code>nav</code> tag instead of the <code>div</code> tag around the navigation links.');
assert($('div').length == 0, 'message: Change the <code>div</code> tag to a <code>nav</code> tag.');
<body>
<header>
<h1>Training with CamperCat</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
</body>
Similar to header
and nav
, the footer
element has a built-in landmark feature that allows assistive devices to quickly navigate to it. It's primarily used to contain copyright information or links to related documents that usually sit at the bottom of a page.
CamperCat's training page is making good progress. Change the div
he used to wrap his copyright information at the bottom of the page to a footer
element.
<body>
<header>
<h1>Training</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
<div>© 2016 CamperCat</div>
</body>
assert($('footer').length == 1, 'message: Make sure to use a <code>footer</code> tag instead of the <code>div</code> tag around the copyright information.');
assert($('div').length == 0, 'message: Change the <code>div</code> tag to a <code>footer</code> tag.');
<body>
<header>
<h1>Training</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
<footer>© 2016 CamperCat</footer>
</body>
HTML5 introduced the figure
element, along with its buddy figcaption
. Used together, these items wrap a visual representation (like an image, diagram, chart, etc.) along with its caption. This gives a two-fold accessibility boost by both semantically grouping related content, and providing a text alternative that explains the figure. For data visualizations like charts, the caption can be used to briefly note the trends or conclusions for users with visual impairments, but we'll cover how to move a table version of the chart's data off-screen (using CSS) for screen reader users in another challenge.
Here's an example - note that the figcaption
goes inside the figure
tags and can be combined with other elements:
<figure>
<img src="roundhouseDestruction.jpeg" alt="Photo of CamperCat executing a roundhouse kick">
<br />
<figcaption>
Master CamperCat demonstrates proper form of a roundhouse kick.
</figcaption>
</figure>
CamperCat is hard at work creating a stacked bar chart showing the amount of time per week to spend training in stealth, combat, and weapons. Help him structure his page better by changing the div
tag he used to a figure
tag, and the p
tag that surrounds the caption to a figcaption
tag.
<body>
<header>
<h1>Training</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section>
<!-- Only change code below this line -->
<div>
<!-- Stacked bar chart will go here -->
<br />
<p>Breakdown per week of time to spend training in stealth, combat, and weapons.</p>
</div>
<!-- Only change code above this line -->
</section>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
<div>© 2016 CamperCat</div>
</body>
assert($('figure').length == 1, 'message: Make sure to use a <code>figure</code> tag instead of the <code>div</code> tag around the chart and caption.');
assert($('figcaption').length == 1, 'message: Make sure to use a <code>figcaption</code> tag instead of the <code>p</code> tag around the caption.');
assert($('div').length == 0, 'message: Change the <code>div</code> tag to a <code>figure</code> tag.');
assert($('p').length == 0, 'message: Change the <code>p</code> tag to a <code>figcaption</code> tag.');
assert($('figure').children('figcaption').length == 1, 'message: Make sure the <code>figcaption</code> is a child of the <code>figure</code> tag.')
<body>
<header>
<h1>Training</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section>
<!-- Only change code below this line -->
<figure>
<!-- Stacked bar chart will go here -->
<br />
<figcaption>Breakdown per week of time to spend training in stealth, combat, and weapons.</figcaption>
</figure>
<!-- Only change code above this line -->
</section>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
<div>© 2016 CamperCat</div>
</body>
Improving accessibility using semantic HTML markup applies to using both appropriate tag names and attributes. We'll cover several important scenarios using attributes in forms in the next few challenges. You may have seen a label
tag wrapping the text for a specific form control item, which ties meaning to it and makes it more readable. The for
attribute on a label
tag explicitly associates that label with the form control and is used by screen readers. The value of the for
attribute must be the same as the value of the id
attribute of the form control.
Here's an example:
<form>
<label for="name">Name:</label>
<input type="text" id="name" name="name">
</form>
CamperCat expects a lot of interest in his thought-provoking blog posts, and wants to include an email sign up form. Add a for
attribute on the email label
that matches the id
on its input
field.
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<section>
<form>
<p>Sign up to receive CamperCat's blog posts by email here!</p>
<label>Email:</label>
<input type="text" id="email" name="email">
<input type="submit" name="submit" value="Submit">
</form>
</section>
<article>
<h2>The Garfield Files: Lasagna as Training Fuel?</h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-yummy trifecta that is lasagna...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer>© 2016 CamperCat</footer>
</body>
assert($('label').attr('for'), 'message: Give the <code>label</code> tag a <code>for</code> attribute, and make sure it is not empty.');
assert($('label').attr('for') == 'email', 'message: Make sure the <code>for</code> attribute matches the value of the email <code>input id</code>attribute, which is case sensitive.');
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<section>
<form>
<p>Sign up to receive CamperCat's blog posts by email here!</p>
<label for="email">Email:</label>
<input type="text" id="email" name="email">
<input type="submit" name="submit" value="Submit">
</form>
</section>
<article>
<h2>The Garfield Files: Lasagna as Training Fuel?</h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-yummy trifecta that is lasagna...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer>© 2016 CamperCat</footer>
</body>
Our next form topic will cover accessibility of radio buttons. Each choice is given a label
with a for
attribute tying to the id
of the corresponding item as we covered in the last challenge. Since radio buttons often come in a group where the user must choose one, there's a way to semantically show the choices are part of a set. The fieldset
tag surrounds the entire grouping of radio buttons to achieve this. It often uses a legend
tag to provide a description for the grouping, which is read by screen readers for each choice in the fieldset
element.
The fieldset
wrapper and legend
tag are not necessary when the choices are self-explanatory, like a gender selection. Using a label
with the for
attribute for each radio button is sufficient.
Here's an example:
<form>
<fieldset>
<legend>Choose one of these three items:</legend>
<input id="one" type="radio" name="items" value="one">
<label for="one">Choice One</label><br>
<input id="two" type="radio" name="items" value="two">
<label for="two">Choice Two</label><br>
<input id="three" type="radio" name="items" value="three">
<label for="ground">Choice Three</label>
</fieldset>
</form>
CamperCat wants information about the ninja level of his users when they sign up for his email list. He's added a set of radio buttons, and learned from our last lesson to use label
tags with for
attributes for each choice. Go CamperCat! However, his code still needs some help. Change the div
tag surrounding the radio buttons to a fieldset
tag, and change the p
tag inside it to a legend
.
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<section>
<form>
<p>Sign up to receive CamperCat's blog posts by email here!</p>
<label for="email">Email:</label>
<input type="text" id="email" name="email">
<!-- Only make changes below this line -->
<div>
<p>What level ninja are you?</p>
<input id="newbie" type="radio" name="levels" value="newbie">
<label for="newbie">Newbie Kitten</label><br>
<input id="intermediate" type="radio" name="levels" value="intermediate">
<label for="intermediate">Developing Student</label><br>
<input id="master" type="radio" name="levels" value="master">
<label for="master">Master</label>
</div>
<!-- Only make changes above this line -->
<input type="submit" name="submit" value="Submit">
</form>
</section>
<article>
<h2>The Garfield Files: Lasagna as Training Fuel?</h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-yummy trifecta that is lasagna...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer>© 2016 CamperCat</footer>
</body>
assert($('fieldset').length == 1, 'message: Make sure to use a <code>fieldset</code> tag instead of a <code>div</code> around the radio button set.');
assert($('legend').length == 1, 'message: Make sure to use a <code>legend</code> tag instead of the <code>p</code> tag around the text asking what level ninja a user is.');
assert($('div').length == 0, 'message: Change the <code>div</code> tag to a <code>fieldset</code> tag.');
assert($('p').length == 4, 'message: Change the <code>p</code> tag to a <code>legend</code> tag.');
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<section>
<form>
<p>Sign up to receive CamperCat's blog posts by email here!</p>
<label for="email">Email:</label>
<input type="text" id="email" name="email">
<!-- Only make changes below this line -->
<fieldset>
<legend>What level ninja are you?</legend>
<input id="newbie" type="radio" name="levels" value="newbie">
<label for="newbie">Newbie Kitten</label><br>
<input id="intermediate" type="radio" name="levels" value="intermediate">
<label for="intermediate">Developing Student</label><br>
<input id="master" type="radio" name="levels" value="master">
<label for="master">Master</label>
</fieldset>
<!-- Only make changes above this line -->
<input type="submit" name="submit" value="Submit">
</form>
</section>
<article>
<h2>The Garfield Files: Lasagna as Training Fuel?</h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-yummy trifecta that is lasagna...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near...</p>
</article>
<img src="samuraiSwords.jpeg" alt="">
<article>
<h2>Is Chuck Norris a Cat Person?</h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer>© 2016 CamperCat</footer>
</body>
FYI @QuincyLarson and @zersiax - I changed the title of one of the challenges slightly.
Old: Wrap Radio Buttons in a Label Element for Better Accessibility (use the "for" property)
New: Wrap Radio Buttons in a Fieldset Element for Better Accessibility
The original comment checklist text is updated. The challenge text still covers the importance of using a label
with the for
attribute, but I wanted to better reflect the WebAIM article guidance about using fieldset
.
@HKuz looking good so far :) I saw you mention that the header tag can be shown multiple times on a page within articles etc. , I must say that is not really something I see in the wild a lot. I'm not sure if it's wrong, but I don't think it really adds much to do that and sticking to a header as the actual header of a web page is I think the recommended approach :) Keep up the good work :)
Got it, @zersiax, I've updated that challenge. It's good to know what's actually implemented in the wild, as you say :) and focus on that for the campers. I've also tweaked the footer challenge since it referenced those same characteristics. And thanks for reviewing these, it's much appreciated!
Forms often include the input
field, which can be used to create several different form controls. The type
attribute on this element indicates what kind of input will be created. You may have noticed the text
and submit
input
types in prior challenges, and HTML5 introduced an option to specify a date
field. Depending on browser support, a date picker shows up in the input field when it's in focus, which makes filling in a form easier for all users. For older browsers, the type
will default to text
, so it helps to show users the expected date format just in case.
Here's an example:
<label for="input1">Enter a date (MM-DD-YYYY):</label>
<input type="date" id="input1" name="input1">
CamperCat is setting up a mortal combat tournament and wants to survey his likely competitors to see what date works best. Add an input
tag under the label
, which has a type
attribute of 'date', an id
attribute of 'pickdate', and a name
attribute of 'date'.
<body>
<header>
<h1>Tournaments</h1>
</header>
<section>
<h2>Mortal Combat Tournament Survey</h2>
<form>
<p>Tell us the best date for the competition</p>
<label for="pickdate">Preferred Date (MM-DD-YYYY):</label>
<!-- Add your code below this line -->
<!-- Add your code above this line -->
<input type="submit" name="submit" value="Submit">
</form>
</section>
<br>
<footer>© 2016 CamperCat</footer>
</body>
assert($('input').length == 2, 'message: Make sure to add one <code>input</code> tag for the date selector field above the <code>input</code> tag for submit.');
assert($('input').attr('type') == 'date', 'message: Make sure to have a <code>type</code> attribute of \'date\' on your <code>input</code> tag.');
assert($('input').attr('id') == 'pickdate', 'message: Make sure to have an <code>id</code> attribute of \'pickdate\' on your <code>input</code> tag.');
assert($('input').attr('name') == 'date', 'message: Make sure to have a <code>name</code> attribute of \'date\' on your <code>input</code> tag.');
<body>
<header>
<h1>Tournaments</h1>
</header>
<section>
<h2>Mortal Combat Tournament Survey</h2>
<form>
<p>Tell us the best date for the competition</p>
<label for="pickdate">Preferred Date:</label>
<!-- Add your code below this line -->
<input type="date" id="pickdate" name="date">
<!-- Add your code above this line -->
<input type="submit" name="submit" value="Submit">
</form>
</section>
<br>
<footer>© 2016 CamperCat</footer>
</body>
Have you noticed that all of the applied accessibility challenges so far haven't used any CSS? This is to illustrate the importance of creating a logical document outline, and using semantically meaningful tags around your content before introducing the visual design aspect. However, CSS's magic can also improve accessibility on your page when you want to visually hide content meant only for screen readers. This happens when information is clearly conveyed in a visual format (like a chart), but screen reader users need an alternative presentation (like a table) to access the data. CSS is used to position the screen reader-only elements off the visual area of the browser window.
Here's an example of the CSS rules that accomplish this:
.sr-only {
position: absolute;
left: -10000px;
width: 1px;
height: 1px;
top: auto;
overflow: hidden;
}
Note - the following CSS approaches will NOT do the same thing:
1) display: none;
or visibility: hidden;
hides content for everyone, including screen reader users
2) Zero values for pixel sizes, such as width: 0px; height: 0px;
removes that element from the flow of your document, meaning screen readers will ignore it
CamperCat created a really cool stacked bar chart for his training page, and put the data into a table for his visually impaired users. The table
already has an sr-only
class, but the CSS rules aren't filled in yet. Give the position
an absolute
value, the left
a -10000px
value, and the width
and height
both 1px
values.
<head>
<style>
.sr-only {
position: ;
left: ;
width: ;
height: ;
top: auto;
overflow: hidden;
}
</style>
</head>
<body>
<header>
<h1>Training</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section>
<h2>Master CamperCat's Beginner Three Week Training Program</h2>
<figure>
<!-- Stacked bar chart of weekly training-->
<p>[Stacked bar chart]</p>
<br />
<figcaption>Breakdown per week of time to spend training in stealth, combat, and weapons.</figcaption>
</figure>
<table class="sr-only">
<caption>Hours of Weekly Training in Stealth, Combat, and Weapons</caption>
<thead>
<tr>
<th></th>
<th scope="col">Stealth & Agility</th>
<th scope="col">Combat</th>
<th scope="col">Weapons</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Week One</th>
<td>3</td>
<td>5</td>
<td>2</td>
<td>10</td>
</tr>
<tr>
<th scope="row">Week Two</th>
<td>4</td>
<td>5</td>
<td>3</td>
<td>12</td>
</tr>
<tr>
<th scope="row">Week Three</th>
<td>4</td>
<td>6</td>
<td>3</td>
<td>13</td>
</tr>
</tbody>
</table>
</section>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye, world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
<footer>© 2016 CamperCat</footer>
</body>
assert($('.sr-only').css('position') === 'absolute', 'message: Change the <code>position</code> of the <code>sr-only</code> class to <code>absolute</code>.');
assert($('.sr-only').css('left') === '-10000px', 'message: Change <code>left</code> of the <code>sr-only</code> class to <code>-10000px</code>.');
assert(code.match(/width:\s*?1px/gi), 'message: Change the <code>width</code> of the <code>sr-only</code> class to <code>1px</code>.');
assert(code.match(/height:\s*?1px/gi), 'message: Change the <code>height</code> of the <code>sr-only</code> class to <code>1px</code>.');
<head>
<style>
.sr-only {
position: absolute;
left: -10000px;
width: 1px;
height: 1px;
top: auto;
overflow: hidden;
}
</style>
</head>
<body>
<header>
<h1>Training</h1>
<nav>
<ul>
<li><a href="#stealth">Stealth & Agility</a></li>
<li><a href="#combat">Combat</a></li>
<li><a href="#weapons">Weapons</a></li>
</ul>
</nav>
</header>
<section>
<h2>Master CamperCat's Beginner Three Week Training Program</h2>
<figure>
<!-- Stacked bar chart of weekly training-->
<p>[Stacked bar chart]</p>
<br />
<figcaption>Breakdown per week of time to spend training in stealth, combat, and weapons.</figcaption>
</figure>
<table class="sr-only">
<caption>Hours of Weekly Training in Stealth, Combat, and Weapons</caption>
<thead>
<tr>
<th></th>
<th scope="col">Stealth & Agility</th>
<th scope="col">Combat</th>
<th scope="col">Weapons</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Week One</th>
<td>3</td>
<td>5</td>
<td>2</td>
<td>10</td>
</tr>
<tr>
<th scope="row">Week Two</th>
<td>4</td>
<td>5</td>
<td>3</td>
<td>12</td>
</tr>
<tr>
<th scope="row">Week Three</th>
<td>4</td>
<td>6</td>
<td>3</td>
<td>13</td>
</tr>
</tbody>
</table>
</section>
<section id="stealth">
<h2>Stealth & Agility Training</h2>
<article><h3>Quickly climb foliage using a minimum spanning tree approach</h3></article>
<article><h3>No training is NP-complete without parkour</h3></article>
</section>
<section id="combat">
<h2>Combat Training</h2>
<article><h3>Dispatch multiple enemies with multithreaded tactics</h3></article>
<article><h3>Goodbye, world: 5 proven ways to knock out an opponent</h3></article>
</section>
<section id="weapons">
<h2>Weapons Training</h2>
<article><h3>Swords: the best tool to literally divide and conquer</h3></article>
<article><h3>Breadth-first or depth-first in multi-weapon training?</h3></article>
</section>
<footer>© 2016 CamperCat</footer>
</body>
@HKuz this looks great. I like how you tee up the CSS to discourage people from simply copying and pasting the CSS in your example :)
@QuincyLarson thanks! I actually hadn't thought of it that way, but I'll take it! By the way, my goal is to get these challenges done by Thursday (8/25). You may have noticed I made some slight re-order edits to the original comment, too - I found some of the challenges seem to flow nicely into others. Hope that's not an issue.
Continuing with the date theme, HTML5 also introduced the time
element along with a datetime
attribute to standardize times. This is an inline element that can wrap a date or time on a page, then a valid format of that date is held by the datetime
attribute, which is the value accessed by assistive devices. It helps avoid confusion by stating a standardized version of a time, even if it's written in an informal or colloquial manner.
Here's an example:
<p>Master CamperCat officiated the cage match between Goro and Scorpion <time datetime="2013-02-13">last Wednesday</time>,
which ended in a draw.</p>
CamperCat's mortal combat survey results are in! Wrap a time
tag around the text "Thursday, September 15th" and add a datetime
attribute to it set to "2016-09-15".
<body>
<header>
<h1>Tournaments</h1>
</header>
<article>
<h2>Mortal Combat Tournament Survey Results</h2>
<p>Thank you to everyone for responding to Master CamperCat's survey. The best day to host the vaunted Mortal Combat tournament is Thursday, September 15<sup>th</sup>. May the best ninja win!</p>
<section>
<h3>Comments:</h3>
<article>
<p>Posted by: Sub-Zero on <time datetime="2016-08-13T20:01Z">August 13<sup>th</sup></time></p>
<p>Johnny Cage better be there, I'll finish him!</p>
</article>
<article>
<p>Posted by: Doge on <time datetime="2016-08-15T08:12Z">August 15<sup>th</sup></time></p>
<p>Wow, much combat, so mortal.</p>
</article>
<article>
<p>Posted by: The Grim Reaper on <time datetime="2016-08-16T00:00Z">August 16<sup>th</sup></time></p>
<p>Looks like I'll be busy that day.</p>
</article>
</section>
</article>
<br>
<footer>© 2016 CamperCat</footer>
</body>
assert(code.match(/<time \s*?datetime=("|')2016-09-15("|')\s*?>\s*?Thursday, September 15<sup>th<\/sup>\s*?\.?\s*?<\/time>/gi), 'message: Make sure to place an opening and closing <code>time</code> tag around "Thursday, September 15<sup>th</sup>" and include a <code>datetime</code> attribute set to "2016-09-15".');
assert($('time').attr('datetime'), 'message: Make sure to add a <code>datetime</code> attribute on your <code>time</code> element.');
assert($('time').attr('datetime') === "2016-09-15", 'message: Make sure the <code>datetime</code> attribute is set to "2016-09-15".');
<body>
<header>
<h1>Tournaments</h1>
</header>
<article>
<h2>Mortal Combat Tournament Survey Results</h2>
<p>Thank you to everyone for responding to Master CamperCat's survey. The best day to host the vaunted Mortal Combat tournament is <time datetime="2016-09-15">Thursday, September 15<sup>th</sup></time>. May the best ninja win!</p>
<section>
<h3>Comments:</h3>
<article>
<p>Posted by: Sub-Zero on <time datetime="2016-08-13T20:01Z">August 13<sup>th</sup></time></p>
<p>Johnny Cage better be there, I'll finish him!</p>
</article>
<article>
<p>Posted by: Doge on <time datetime="2016-08-15T08:12Z">August 15<sup>th</sup></time></p>
<p>Wow, much combat, so mortal.</p>
</article>
<article>
<p>Posted by: The Grim Reaper on <time datetime="2016-08-16T00:00Z">August 16<sup>th</sup></time></p>
<p>Looks like I'll be busy that day.</p>
</article>
</section>
</article>
<br>
<footer>© 2016 CamperCat</footer>
</body>
@HKuz no worries - you are spear-heading these challenges so I'll defer to your judgement :)
@HKuz since you've been working so hard on this, I've promoted you to topic owner. Note that you have write permission on this repo, and can update the sequence of challenges in my original post up top.
@QuincyLarson very cool, thank you!
Low contrast between the foreground and background colors can make text difficult to read. Sufficient contrast improves the readability of your content, but what exactly does "sufficient" mean? The Web Content Accessibility Guidelines (WCAG) recommend at least a 4.5 to 1 contrast ratio for normal text. The ratio is calculated by comparing the relative luminance values of two colors, and ranges from 1:1 for the same color, or no contrast, to 21:1 for white against black, the strongest contrast. There are many contrast checking tools available online that calculate this ratio for you.
CamperCat's choice of light gray text on a white background for his recent blog post has a 1.5:1 contrast ratio, making it hard to read. Change the current gray (#D3D3D3) color
of the text to a darker gray (#636363) to improve the contrast ratio to 6:1.
<head>
<style>
body {
color: #D3D3D3;
background-color: #FFF;
}
</style>
</head>
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>A Word on the Recent Catnip Doping Scandal</h2>
<p>The influence that catnip has on feline behavior is well-documented, and its use as an herbal supplement in competitive ninja circles remains controversial. Once again, the debate to ban the substance is brought to the public's attention after the high-profile win of Kittytron, a long-time proponent and user of the green stuff, at the Claw of Fury tournament.</p>
<p>As I've stated in the past, I firmly believe a true ninja's skills must come from within, with no external influences. My own catnip use shall continue as purely recreational.</p>
</article>
</body>
assert($('body').css('color') === "rgb(99, 99, 99)", 'message: Change the text <code>color</code> for the <code>body</code> to the darker gray, using its <code>hex code</code>.');
assert($('body').css('background-color') === "rgb(255, 255, 255)", 'message: Keep the <code>background-color</code> for the <code>body</code> white.');
<head>
<style>
body {
color: #636363;
background-color: #FFF;
}
</style>
</head>
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>A Word on the Recent Catnip Doping Scandal</h2>
<p>The influence that catnip has on feline behavior is well-documented, and its use as an herbal supplement in competitive ninja circles remains controversial. Once again, the debate to ban the substance is brought to the public's attention after the high-profile win of Kittytron, a long-time proponent and user of the green stuff, at the Claw of Fury tournament.</p>
<p>As I've stated in the past, I firmly believe a true ninja's skills must come from within, with no external influences. My own catnip use shall continue as purely recreational.</p>
</article>
</body>
Color is an integral part of visual design, but its use introduces two accessibility issues. First, color alone should not be used as the only way to convey important information because screen reader users won't see it. Second, foreground and background colors need sufficient contrast so colorblind users can distinguish them. We've covered having text alternatives to address the first issue, and the last challenge introduced contrast checking tools to help with the second. The WCAG recommended contrast ratio of 4.5:1 applies for color use as well as gray-scale combinations.
Colorblind users have trouble distinguishing some colors from others - usually in hue but sometimes lightness as well. You may recall the contrast ratio is calculated using the relative luminance (or lightness) values of the foreground and background colors. In practice, the 4.5:1 ratio can be targeted by darkening the darker color and lightening the lighter one with the aid of a color contrast checker. Darker colors on the color wheel are considered to be blues, violets, magentas, and reds, whereas lighter colors are oranges, yellows, greens, and blue-greens.
CamperCat is experimenting with using color for his blog text and background, but his current combination of a greenish background-color
with maroon text color
has a 2.5:1 contrast ratio. We can easily adjust the lightness of the colors since he declared them using the CSS hsl()
property (which stands for hue, saturation, lightness) by changing the third argument. Increase the background-color
lightness value from 35% to 55%, and decrease the color
lightness value from 20% to 15%. This improves the contrast to 5.9:1.
<head>
<style>
body {
color: hsl(0, 55%, 20%);
background-color: hsl(120, 25%, 35%);
}
</style>
</head>
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>A Word on the Recent Catnip Doping Scandal</h2>
<p>The influence that catnip has on feline behavior is well-documented, and its use as an herbal supplement in competitive ninja circles remains controversial. Once again, the debate to ban the substance is brought to the public's attention after the high-profile win of Kittytron, a long-time proponent and user of the green stuff, at the Claw of Fury tournament.</p>
<p>As I've stated in the past, I firmly believe a true ninja's skills must come from within, with no external influences. My own catnip use shall continue as purely recreational.</p>
</article>
</body>
assert($('body').css('color') === "rgb(59, 17, 17)", 'message: Change only the lightness value for the text <code>color</code> to 15%.');
assert($('body').css('background-color') === "rgb(111, 168, 111)", 'message: Change only the lightness value for the <code>background-color</code> to 55%.');
<head>
<style>
body {
color: hsl(0, 55%, 15%);
background-color: hsl(120, 25%, 55%);
}
</style>
</head>
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>A Word on the Recent Catnip Doping Scandal</h2>
<p>The influence that catnip has on feline behavior is well-documented, and its use as an herbal supplement in competitive ninja circles remains controversial. Once again, the debate to ban the substance is brought to the public's attention after the high-profile win of Kittytron, a long-time proponent and user of the green stuff, at the Claw of Fury tournament.</p>
<p>As I've stated in the past, I firmly believe a true ninja's skills must come from within, with no external influences. My own catnip use shall continue as purely recreational.</p>
</article>
</body>
There are various forms of colorblindness, ranging from a reduced sensitivity to a certain wavelength of light to the inability to perceive color at all. The most common form is a reduced sensitivity to detect greens. If two colors with similar hues (close to the wavelength in question) are the foreground and background color of your content, a colorblind user may not be able to distinguish them. Close colors can be thought of as neighbors on the color wheel, and those combinations should be avoided when conveying important information.
Note: Some online color picking tools include visual simulations of how colors appear for different types of colorblindness. These are great resources in addition to online contrast checking calculators.
CamperCat is testing different styles for an important button
, but the yellow (#FFFF33) background-color
and the green (#33FF33) text color
are neighboring hues on the color wheel and virtually indistinguishable for some colorblind users. (Their similar lightness also fails the contrast ratio check). Change the text color
to a dark blue (#003366) to solve both problems.
<head>
<style>
button {
color: #33FF33;
background-color: #FFFF33;
font-size: 14px;
padding: 10px;
}
</style>
</head>
<body>
<header>
<h1>Danger!</h1>
</header>
<button>Delete Internet</button>
</body>
assert($('button').css('color') === "rgb(0, 51, 102)", 'message: Change the text <code>color</code> for the <code>button</code> to dark blue.');
assert($('button').css('background-color') === "rgb(255, 255, 51)", 'message: Don't change the <code>background-color</code> of the <code>button</code>.');
<head>
<style>
button {
color: #003366;
background-color: #FFFF33;
font-size: 14px;
padding: 10px;
}
</style>
</head>
<body>
<header>
<h1>Danger!</h1>
</header>
<button>Delete Internet</button>
</body>
As we've seen in prior challenges, screen reader users have different options for what type of content their device reads, including skipping to (or over) landmark elements, jumping to the main content, or getting a page summary from the headings. Another option is to only hear the links available on a page. Screen readers do this by reading the link text, or what's between the anchor (a
) tags. Having a list of "click here" or "read more" links isn't helpful, instead, use brief but descriptive text within the a
tags to provide more meaning for these users.
The link text that CamperCat is using is not very descriptive without the surrounding context. Move the anchor (a
) tags so they wrap around the text "information about batteries" instead of "Click here".
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near. <a href="">Click here</a> for information about batteries</p>
</article>
</body>
assert(code.match(/<a href="">\s*?information about batteries\s*?<\/a>/gi), 'message: Move the anchor <code>a</code> tags from around the words "Click here" to wrap the words "information about batteries". Don\'t remove the <code>href=""</code> attribute');
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2>Defeating your Foe: the Red Dot is Ours!</h2>
<p>Felines the world over have been waging war on the most persistent of foes. This red nemesis combines both cunning stealth and lightening speed. But chin up, fellow fighters, our time for victory may soon be near. Click here for <a href="">information about batteries</a></p>
</article>
</body>
@HKuz The description text in these challenges is really well written and thought out. You do a great job of explaining why these concepts are important in a way that will hopefully convince campers that they are worth the extra effort.
HTML offers the accesskey
attribute to specify a shortcut key to activate or bring focus to an element. This can make navigation more efficient for keyboard-only users. HTML5 allows this attribute to be used on any element, but it's of particular use when paired with interactive ones, such as links, buttons, and form controls.
Here's an example:
<button accesskey="b">Important Button</button>
CamperCat wants the links around the two blog article titles to have keyboard shortcuts so his site's users can quickly navigate to the full story. Add an accesskey
attribute to both links and set the first one to "g" (for Garfield) and the second one to "c" (for Chuck Norris).
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2><a id="first" href="">The Garfield Files: Lasagna as Training Fuel?</a></h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-yummy trifecta that is lasagna...</p>
</article>
<article>
<h2><a id="second" href="">Is Chuck Norris a Cat Person?</a></h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer>© 2016 CamperCat</footer>
</body>
assert($('#first').attr('accesskey'), 'message: Make sure to add an <code>accesskey</code> attribute to the <code>a</code> tag with the <code>id</code> of "first".');
assert($('#second').attr('accesskey'), 'message: Make sure to add an <code>accesskey</code> attribute to the <code>a</code> tag with the <code>id</code> of "second".');
assert($('#first').attr('accesskey') === 'g', 'message: Make sure to set the <code>accesskey</code> attribute on the <code>a</code> tag with the <code>id</code> of "first" to "g". Note that case matters.');
assert($('#second').attr('accesskey') === 'c', 'message: Make sure to set the <code>accesskey</code> attribute on the <code>a</code> tag with the <code>id</code> of "second" to "c". Note that case matters.');
<body>
<header>
<h1>Deep Thoughts with Master CamperCat</h1>
</header>
<article>
<h2><a accesskey="g" id="first" href="">The Garfield Files: Lasagna as Training Fuel?</a></h2>
<p>The internet is littered with varying opinions on nutritional paradigms, from catnip paleo to hairball cleanses. But let's turn our attention to an often overlooked fitness fuel, and examine the protein-carb-yummy trifecta that is lasagna...</p>
</article>
<article>
<h2><a accesskey="c" id="second" href="">Is Chuck Norris a Cat Person?</a></h2>
<p>Chuck Norris is widely regarded as the premier martial artist on the planet, and it's a complete coincidence anyone who disagrees with this fact mysteriously disappears soon after. But the real question is, is he a cat person?...</p>
</article>
<footer>© 2016 CamperCat</footer>
</body>
The HTML tabindex
attribute has three distinct functions relating to an element's keyboard focus. Its presence on a tag indicates that element can be focused on, and the value (an integer that's positive, negative, or zero) determines the behavior. We'll start with the special values of zero and -1.
Certain elements, such as links and form controls, automatically receive keyboard focus when a user tabs through a page, in the same order as they come in the HTML source markup. This same functionality can be given to other elements, such as div
, span
, and p
, by placing a tabindex="0"
attribute on them.
Here's an example:
<div tabindex="0">I need keyboard focus!</div>
Note:
A negative tabindex
value (typically -1) indicates that an element is focusable, but is not reachable by the keyboard. This method is generally used to bring focus to content programmatically (like when a pop-up window is activated), and is beyond the scope of these challenges.
CamperCat created a new survey to collect information about his users. He knows input
fields automatically get keyboard focus, but he wants to make sure his keyboard users pause at the instructions while tabbing through the items. Add a tabindex
attribute to the p
tag and set its value to "0". Bonus - notice how using tabindex
also enables the CSS pseudo-class :focus
to work on the p
tag?
<head>
<style>
p:focus {
background-color: yellow;
}
</style>
</head>
<body>
<header>
<h1>Ninja Survey</h1>
</header>
<section>
<form>
<p>Instructions: Fill in ALL your information then click <b>Submit</b></p>
<label for="username">Username:</label>
<input type="text" id="username" name="username"><br>
<fieldset>
<legend>What level ninja are you?</legend>
<input id="newbie" type="radio" name="levels" value="newbie">
<label for="newbie">Newbie Kitten</label><br>
<input id="intermediate" type="radio" name="levels" value="intermediate">
<label for="intermediate">Developing Student</label><br>
<input id="master" type="radio" name="levels" value="master">
<label for="master">9th Life Master</label>
</fieldset>
<br>
<fieldset>
<legend>Select your favorite weapons:</legend>
<input id="stars" type="checkbox" name="weapons" value="stars">
<label for="stars">Throwing Stars</label><br>
<input id="nunchucks" type="checkbox" name="weapons" value="nunchucks">
<label for="nunchucks">Nunchucks</label><br>
<input id="sai" type="checkbox" name="weapons" value="sai">
<label for="sai">Sai Set</label><br>
<input id="sword" type="checkbox" name="weapons" value="sword">
<label for="sword">Sword</label>
</fieldset>
<br>
<input type="submit" name="submit" value="Submit">
</form><br>
</section>
<footer>© 2016 CamperCat</footer>
</body>
assert($('p').attr('tabindex'), 'message: Make sure to add a <code>tabindex</code> attribute to the <code>p</code> tag with the form instructions.');
assert($('p').attr('tabindex') === '0', 'message: Make sure to set the <code>tabindex</code> attribute on the <code>p</code> tag to "0".');
<head>
<style>
p:focus {
background-color: yellow;
}
</style>
</head>
<body>
<header>
<h1>Ninja Survey</h1>
</header>
<section>
<form>
<p tabindex="0">Instructions: Fill in ALL your information then click <b>Submit</b></p>
<label for="username">Username:</label>
<input type="text" id="username" name="username"><br>
<fieldset>
<legend>What level ninja are you?</legend>
<input id="newbie" type="radio" name="levels" value="newbie">
<label for="newbie">Newbie Kitten</label><br>
<input id="intermediate" type="radio" name="levels" value="intermediate">
<label for="intermediate">Developing Student</label><br>
<input id="master" type="radio" name="levels" value="master">
<label for="master">9th Life Master</label>
</fieldset>
<br>
<fieldset>
<legend>Select your favorite weapons:</legend>
<input id="stars" type="checkbox" name="weapons" value="stars">
<label for="stars">Throwing Stars</label><br>
<input id="nunchucks" type="checkbox" name="weapons" value="nunchucks">
<label for="nunchucks">Nunchucks</label><br>
<input id="sai" type="checkbox" name="weapons" value="sai">
<label for="sai">Sai Set</label><br>
<input id="sword" type="checkbox" name="weapons" value="sword">
<label for="sword">Sword</label>
</fieldset>
<br>
<input type="submit" name="submit" value="Submit">
</form><br>
</section>
<footer>© 2016 CamperCat</footer>
</body>
The next function that the tabindex
attribute offers is to specify the exact tab order of elements. This is achieved when the value of the attribute is set to a positive number of 1 or higher. Setting a tabindex="1"
will bring keyboard focus to that element first, then cycle through the sequence of specified tabindex
values (2, 3, etc.), before moving to default and tabindex="0"
items. It's important to note that when the tab order is set this way, it overrides the default order (which uses the HTML source), and may confuse users who are expecting to start navigation from the top of the page. This technique may be necessary in some circumstances, but in terms of accessibility, take care before applying it.
Here's an example:
<div tabindex="1">I get keyboard focus, and I get it first!</div>
<div tabindex="2">I get keyboard focus, and I get it second!</div>
CamperCat has a search field on his Inspirational Quotes page that he plans to position in the upper right corner with CSS. He wants the search input
and submit input
form controls to be the first two items in the tab order. Add a tabindex
attribute set to "1" to the search input
, and a tabindex
attribute set to "2" to the submit input
.
<body>
<header>
<h1>Even Deeper Thoughts with Master CamperCat</h1>
<nav>
<ul>
<li><a href="">Home</a></li>
<li><a href="">Blog</a></li>
<li><a href="">Training</a></li>
</ul>
</nav>
</header>
<form>
<label for="search">Search:</label>
<input type="search" name="search" id="search">
<input type="submit" name="submit" value="Submit" id="submit">
</form>
<h2>Inspirational Quotes</h2>
<blockquote>
<p>“There's no Theory of Evolution, just a list of creatures I've allowed to live.”<br>
- Chuck Norris</p>
</blockquote>
<blockquote>
<p>“Wise men say forgiveness is divine, but never pay full price for late pizza.”<br>
- TMNT</p>
</blockquote>
<footer>© 2016 CamperCat</footer>
</body>
assert($('#search').attr('tabindex'), 'message: Make sure to add a <code>tabindex</code> attribute to the search <code>input</code> tag.');
assert($('#submit').attr('tabindex'), 'message: Make sure to add a <code>tabindex</code> attribute to the submit <code>input</code> tag.');
assert($('#search').attr('tabindex') === '1', 'message: Make sure to set the <code>tabindex</code> attribute on the search <code>input</code> tag to "1".');
assert($('#submit').attr('tabindex') === '2', 'message: Make sure to set the <code>tabindex</code> attribute on the submit <code>input</code> tag to "2".');
<body>
<header>
<h1>Even Deeper Thoughts with Master CamperCat</h1>
<nav>
<ul>
<li><a href="">Home</a></li>
<li><a href="">Blog</a></li>
<li><a href="">Training</a></li>
</ul>
</nav>
</header>
<form>
<label for="search">Search:</label>
<input type="search" name="search" id="search" tabindex="1">
<input type="submit" name="submit" value="Submit" id="submit" tabindex="2">
</form>
<h2>Inspirational Quotes</h2>
<blockquote>
<p>“There's no Theory of Evolution, just a list of creatures I've allowed to live.”<br>
- Chuck Norris</p>
</blockquote>
<blockquote>
<p>“Wise men say forgiveness is divine, but never pay full price for late pizza.”<br>
- TMNT</p>
</blockquote>
<footer>© 2016 CamperCat</footer>
</body>
HTML5's audio
element gives semantic meaning when it wraps sound or audio stream content in your markup. Audio content also needs a text alternative to be accessible to the deaf or hard of hearing. This can be done with nearby text on the page or a link to a transcript.
The audio
tag supports the controls
attribute, which shows the browser default play, pause, etc. controls, and supports keyboard functionality. This is a boolean attribute, meaning it doesn't need a value, it's presence on the tag turns the setting on.
Here's an example:
<audio id="meowClip" controls>
<source src="audio/meow.mp3" type="audio/mpeg" />
<source src="audio/meow.ogg" type="audio/ogg" />
</audio>
Note: Multimedia content, which usually has both visual and auditory components, needs synchronized captions and a transcript so users with visual and/or auditory impairments can access it. Generally, a web developer is not responsible for creating the captions or transcript, but needs to know to include them.
Let's break from our normally scheduled programming and meet one of our fellow campers, Zersiax (@zersiax), a champion of accessibility and a screen reader user. To hear a clip of his screen reader in action, add an audio
element (after the p
) with the controls
attribute. Then place a source
tag inside the audio
tags with the src
attribute set to "https://s3.amazonaws.com/freecodecamp/screen-reader.mp3" and type
attribute set to "audio/mpeg".
<body>
<header>
<h1>Real Coding Ninjas</h1>
</header>
<p>A sound clip of Zersiax's screen reader in action.</p>
</body>
assert($('audio').length === 1, 'message: Make sure to add an <code>audio</code> element after the <code>p</code> tag.');
assert($('audio').attr('controls'), 'message: Make sure the <code>audio</code> tag includes the <code>controls</code> attribute.');
assert($('source').length === 1, 'message: Make sure to add a <code>source</code> element inside the <code>audio</code> tags. Use the example code as a model.');
assert($('audio').children('source').length === 1, 'message: Make sure the <code>source</code> element is a child of the <code>audio</code> element.');
assert($('source').attr('src') === "https://s3.amazonaws.com/freecodecamp/screen-reader.mp3", 'message: Make sure to include the <code>src</code> attribute on the <code>source</code> tag exactly as it is in the instructions.');
assert($('source').attr('type') === "audio/mpeg", 'message: Make sure to include the <code>type</code> attribute on the <code>source</code> tag exactly as it is in the instructions.');
<body>
<header>
<h1>Real Coding Ninjas</h1>
</header>
<p>A sound clip of Zersiax's screen reader in action.</p>
<audio controls>
<source src="https://s3.amazonaws.com/freecodecamp/screen-reader.mp3" type="audio/mpeg" />
</audio>
</body>
@QuincyLarson pending any comments, I think these challenges are in good shape. I ended up swapping the "Add subtitles to a video" challenge out for the "Improve accessibility of audio content with the audio element" one. I got most of the way through writing a video challenge, (videos need captions and transcripts, web developers don't generate these things, use the track
element to link to the captions), but saw that the track
element included 4 different attributes in the best practices example code. I thought trying to cover each one in one challenge would throw too much at them in one go, and it wasn't worth splitting over several challenges. We got the 'low-hanging fruit' on the audio
element challenge. Let me know if you disagree, or want to discuss more - either this point or any of the other challenges.
I'm going to post a series of links I collected that may make sense for the wiki. Basically they're what you guys already included in this thread or the resources I referenced in the challenges.
Let me know if there's anything else, and how I can help.
@HKuz is in charge of coordinating the expansion of these challenges, but needs your help.
For each challenge, please reply to this GitHub issue with:
Here are the challenges we have currently planned (these can be further expanded):
I found this website quite helpful in constructing this list: http://www.html5accessibility.com