I'm in the process of marking up a site and I've been really trying to hone my accessibility skills. I'm wondering what the most semantic mark-up is for tabbed content. This is what I have now:
<section>
<nav>
Stuff
Stuff
Stuff
</nav>
<section id="content" aria-live="polite" role="region">
<article>...</article>
<article>...</article>
<article>...</article>
</section>
</section>
I have a few specific questions about this.
Am I on the right track? If not can someone recommend some changes?
Will I need to make changes if I were to load in the articles via AJAX?
Do I need the nav tag?
Are WAI-ARIA roles enough here?
Are these the correct WAI-ARIA roles to use?
1.Am I on the right track? If not can someone recommend some changes?
Yes, you've absolutely started in a good way. Some of the tab stuff could be given some tab-related roles if you want to improve it, but it's functional as is.
2.Will I need to make changes if I were to load in the articles via AJAX?
No. It should be fine. The fact that it is a live region should (tested with NVDA only) mean that new content is announced. Is this the behaviour you're after?
3.Do I need the nav tag?
No, but I think it helps make it crystal clear what that bit of the document is for. A note though, that if you do what I've done below and mark it as a tablist, the fact that it's a navigation element doesn't get announced anymore.
4.Are WAI-ARIA roles enough here?
If by ARIA roles you're also including states and properties, yes essentially you should be covered for loading dynamic content (if that's what you're after). There's no case for moving the user's keyboard focus or anything with things as they are. IMO, you'd only really want to do that if there's a lot of navigational stuff between what the user clicked and what content you're giving them.
5.Are these the correct WAI-ARIA roles to use?
You're not far off. If you really want a tab-style experience, then you need the tablist, tab and tabpanel roles. I'll give an example.
I've taken your code and made a contrived but working example to test it. It's not loading anything in AJAX, just showing and hiding stuff. I wanted to be sure before I gave this answer, but I'll put the code here too in case it helps.
<html>
<head>
<title>Aria test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('nav a').on('click', function () {
hideArticles();
deslectAllTabs();
$(this).attr('aria-selected', true);
var tab = '#' + $(this).attr('aria-controls');
$(tab).show();
});
});
function hideArticles() {
$('article').hide();
}
function deslectAllTabs() {
$('nav a').attr('aria-selected', false);
}
</script>
<style type="text/css">
article { display: none; }
</style>
</head>
<body>
<section>
<nav role="tablist">
Stuff1
Stuff2
Stuff3
</nav>
<section id="content" aria-live="polite" role="region">
<article id="content1" role="tabpanel">The lazy dog jumped over the quick fox</article>
<article id="content2" role="tabpanel">If you click this tab then your life will be better</article>
<article id="content3" role="tabpanel">Know your roles</article>
</section>
</section>
</body>
</html>
I hope this helps.
Semantics tend to get vague at this level, but yeah I think you're on the right track as long as each of the tabs would really count as a separate article.
The article element represents a component of a page that consists of a self-contained composition in a document, page, application, or site and that is intended to be independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content.
Source
I don't think the <nav> is misplaced here, although it depends on how important the different tabs are in regards to the whole of your website:
The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links. Not all groups of links on a page need to be in a nav element only sections that consist of major navigation blocks are appropriate for the nav element. In particular, it is common for footers to have a list of links to various key parts of a site, but the footer element is more appropriate in such cases, and no nav element is necessary for those links.
Source
I wouldn't use sections to wrap the stuff in it though.
The section element is not a generic container element. When an element is needed only for styling purposes or as a convenience for scripting, authors are encouraged to use the div element instead. A general rule is that the section element is appropriate only if the element's contents would be listed explicitly in the document's outline.
Source
An additional rule of fist for the <section> element is that they should have a title. If not, it's probably not really a "section" but just a group of elements that you needed to wrap in something, so just use a <div>.
Related
The HTML <main> element represents the dominant content of the <body> of a document, portion of a document or application. The main content area consists of content that is directly related to or expands upon the central topic of a document, or the central functionality of an application. Quote Mozilla Dev.
Questions in my mind
#1
Do we support the same feature if we add a "role" to the "div" tag later? And the same special cases apply?
<div role="main"> == <main> ?
#2
The content of a <main> element should be unique to the document. Content that is repeated across a set of documents or document sections such as sidebars, navigation links, copyright information, site logos, and search forms should not be included unless the search form is the main function of the page.. Quote Mozilla Dev.
It really is a special situation or too much of a relative exceptional situation. A relative explanation.
The only concrete thing I understand (Tree Structure)
eg. wrong usage
<header>..</header>
<article>
<main></main>
</article>
<aside>..</aside>
<footer></footer>
eg. correct use
<header>..</header>
<main>
<article>..</article>
</main>
<aside>..</aside>
<footer></footer>
So actually the question in my mind is starting right here.
<header>..</header>
<main>
<article>
<form>
<input type="text" name="user_name" />
....
....
</form>
</article>
</main>
<aside>..</aside>
<footer></footer>
Now that I use the form element after the main tag, is this an incorrect use?
Screenshot of my project page tree
This a landing page, and the form a register action "Special for this document". So now googlebot read it for collective website form "Like a search form", finally created a negative scenario?
I mean is that the content of the main tag should only be composed of pure text? Sources are a complete mystery!
If we give a much more specific example
Youtube
Youtube using role="main"
My review: Tag including, the search form and navigation menu. Because search form main characteristic for youtube...
As a result of this:
For example, If I have a search engine page and I am including the search form after the main tag;
Scenario 1:
I made a violation of the rules in a strict manner and the undesired motion was negatively affected by the seo, the tree making is wrong.
Scenario 2:
It is not an obvious violation of the rules, but an undesirable aspect of the advice. Googlebot etc. it will not be a negative situation for seo because it can not detect whether the violation is valid (because it is affecting the main content, perhaps using it).
Is there any good idea or technical support?
Like most HTML semantics, a good dose of pragmatism is helpful. Fragmentation of the main role in WAI-ARIA is possible, but strongly disliked and therefore not valid for the <main> element. What that means is that the main element should be the minimal container to hold everything that is the principal content of the page. If that incidentally contains things that would be placed outside the main element if the tree structure permitted it, that should just be accepted as a necessary deviation from the ideal.
I am trying to figure out a way to display an archive of email newsletters on my client's site. The issue is that the newsletters are full of a zillion inline styles, which is great for seeing them in Outlook or wherever, but they're not looking too hot in an otherwise-nicely styled site.
My goal is for my client to be able to copy the entire source code of a generated newsletter (which her list management company* gives her access to) and paste it into the CMS (drupal, if it makes a difference).
*Constant Contact? Mail Chimp? I forget. One of those.
Then I'd like to display it on her site, inside the basic structure (header, nav, etc) of the rest of the site. If this was 1997, I'd say "iframes!" and be done with it, but A) that seems like a lame solution, and B) the code doesn't actually exist on a page by itself, which I think is required for iframes.
Is there some kind of tag I can put around this block of HTML to isolate it from the rest of the site's styles? Or is there another way to go about this entirely?
Thanks!
IFrames are the only way to go that I've ever been able to find. The only alternative to this would be to override every style in the parent page's CSS for the newsletter display area.
As you noted, using an iframe will probably require you to host the newsletters in an independent file. The only alternative to this that I'm aware of is that you can use JavaScript to dynamically create and/or populate the iframe.
If you go with this method, you could have the newsletter present in a div with a specific class, and then use JavaScript to move the div into an iframe. The big downside being that this wouldn't happen for users without JavaScript enabled.
9 years later and there still isn't a better solution.
If you don't have an external source (you can't add html into a frame manually) you need to use js to insert the messy html/css (in my case I use it to view emails)
<iframe class="my-frame" width="100%" height="100%" src="about:blank"></iframe>
and js:
const frame = document.querySelector('.my-frame');
frame.contentWindow.document.open('text/html', 'replace');
frame.contentWindow.document.write(hereGoesYourMessyHtmlCss);
frame.contentWindow.document.close();
Is there a reason why you can't use a modal? That would allow you to force a new request and make the page render how you'd want it to by not applying your general stylesheet while at the same time keeping your user on the desired page. Of course, it doesn't display the element inline so-to-speak, but it's nearly functionally equivelent.
Cutting and pasting raw HTML presents too many security problems, in my opinion. Never trust user's input. Even when the content is entirely benign, next week the designer of newsletter might decide to change their formatting or incorporate some javascript and you'll be responsible for anything that might go wrong.
Therefore I would implement a parser that would drop anything but the content part and leave only b, a, h*, blockquote and similar simple elements, like the ones allowed in forum posts, as well as their styles. After that, you can display it as a normal post in a CMS. I don't see any reason why that should look differently.
As for how to isolate that from your other CSS, you don't really need to if you are careful that all of CSS rules of your CMS apply to elements with specific classes. Alternatively, do a CSS reset for your posts:
.post p {
margin: 0;
...
.post /* all the standard CSS reset rules preceded with .post */
and then
<div class="post"> content parsed from your CMS </div>
Another option that I haven't used myself but am looking to possibly leverage in a similar situation is to use the Shadow DOM which is part of the Web Components spec. My main concern is that we still have some user's using IE 11 and while there seems to be support for polyfills it doesn't look like covering all browser's is real straight forward based on what I've read elsewhere.
Some details on how to use Shadow DOM to this effect can be found here and here. I've also created a small gist that I've created to demonstrate basic idea that I've been formulating as I learn about how the Shadow DOM works which I'll be updating as I learn more. Below you can see a snapshot of the content of that gist.
<!doctype html>
<html>
<head>
<style>
.row {
display: flex;
}
.column {
flex: 50%;
padding: 10px;
height: 300px;
}
* {
color: Red;
}
</style>
</head>
<body>
<div class="row">
<div class="column" style="background-color:#aaa;">
<h2>Column 1</h2>
<div id="content1">
SOME CONTENT FROM CMS
</div>
</div>
<div class="column" style="background-color:#bbb;">
<h2>Column 2</h2>
<div id="content2">
SOME MORE CONTENT FROM CMS
</div>
</div>
</div>
<script>
document
.getElementById("content1")
.attachShadow({ mode: 'open' })
.innerHTML = `
<style>
*{all:initial}
style{display: none}
div{display: block}
</style>
<h3>This text is not red</h3>
<div>slot content: <slot></slot></div>`;
document
.getElementById("content2")
.attachShadow({ mode: 'open' })
.innerHTML = `
<style>
*{all:initial}
style{display: none}
div{display: block}
</style>
<h3>This text is not red</h3>
<div>slot content: <slot></slot></div>`;
</script>
</body>
</html>
The "h1 tag with an image" debate seems as old as time itself, but with HTML5 explicitly allowing multiple H1 tags as part of its spec, all the previous questions on this subject seem out of date.
As I understand it, the following works perfectly with the HTML OA:
<body>
<header>
<h1>
<a href="http://www.example.com">
<img src="logo.png" alt="Ernie's Restaurant - Great Italian food">
</a>
</h1>
</header>
<nav><!-- the site-wide navigation --></nav>
<article>
<h1>About us</h1>
<p>…</p>
</article>
</body>
But I'm working with an SEO company on a website and they've told me:
"The logo link CAN’T be H1. It doesn’t make sense."
Are they right? Is there something bad about the above document outline? If you can't put the logo in a H1 tag, why do the W3C do it themselves on their website?
These people are supposedly SEO experts, but I just don't understand their complaint. What am I missing?
Most of the time, you'd want to wrap the image in an anchor, which also has a title... See This answer and This answer.
Maybe they were just nervous about the lack of a proper anchor? The img tag is entirely legitimate.
Yes, you can have an img element as content of an h1 element.
Yes, it makes sense to have the img-logo as h1 (in case it belongs to the body sectioning root, like it does in your example).
If your site doesn’t show a separate textual name, you definitely should do this. Otherwise, the document outline could be wrong (if you don’t use sectioning elements wherever needed) or at least the outline would have an unlabeled top-level entry, which is not very user friendly/accessible.
If you have a site logo and a textual site name, it’s discussible: either include the img together with the text in the same h1, or have only one of these elements in h1 (either one is possible) and have the other one as "alternative title", e.g., together in a header element.
For examples, see some of my related answers on SO (1, 2, 3) and Code Review (1, 2, 3).
(Your "SEO expert" is not the only one having a problem with this, as you can see in some of the comments to my linked answers. I have yet to see an argument against it ….)
Well, in HTML 4.01 with for example <div id="example"> I could make <a href="#example"> to scroll to that div.
How can I make the same effect with <section class="asd xyz">?
They work the same. Add an ID to the section and the link should work.
<section id="example"></section>
This code jumps to the section #example.
Jump to example
EDIT:
Pure HTML does not allow you to jump to class names and for a good reason. IDs are unique while classes can be reused as often as you want. Therefore you just can't jump to a class name since it probably doesn't have a single target.
I am trying to figure out a way to display an archive of email newsletters on my client's site. The issue is that the newsletters are full of a zillion inline styles, which is great for seeing them in Outlook or wherever, but they're not looking too hot in an otherwise-nicely styled site.
My goal is for my client to be able to copy the entire source code of a generated newsletter (which her list management company* gives her access to) and paste it into the CMS (drupal, if it makes a difference).
*Constant Contact? Mail Chimp? I forget. One of those.
Then I'd like to display it on her site, inside the basic structure (header, nav, etc) of the rest of the site. If this was 1997, I'd say "iframes!" and be done with it, but A) that seems like a lame solution, and B) the code doesn't actually exist on a page by itself, which I think is required for iframes.
Is there some kind of tag I can put around this block of HTML to isolate it from the rest of the site's styles? Or is there another way to go about this entirely?
Thanks!
IFrames are the only way to go that I've ever been able to find. The only alternative to this would be to override every style in the parent page's CSS for the newsletter display area.
As you noted, using an iframe will probably require you to host the newsletters in an independent file. The only alternative to this that I'm aware of is that you can use JavaScript to dynamically create and/or populate the iframe.
If you go with this method, you could have the newsletter present in a div with a specific class, and then use JavaScript to move the div into an iframe. The big downside being that this wouldn't happen for users without JavaScript enabled.
9 years later and there still isn't a better solution.
If you don't have an external source (you can't add html into a frame manually) you need to use js to insert the messy html/css (in my case I use it to view emails)
<iframe class="my-frame" width="100%" height="100%" src="about:blank"></iframe>
and js:
const frame = document.querySelector('.my-frame');
frame.contentWindow.document.open('text/html', 'replace');
frame.contentWindow.document.write(hereGoesYourMessyHtmlCss);
frame.contentWindow.document.close();
Is there a reason why you can't use a modal? That would allow you to force a new request and make the page render how you'd want it to by not applying your general stylesheet while at the same time keeping your user on the desired page. Of course, it doesn't display the element inline so-to-speak, but it's nearly functionally equivelent.
Cutting and pasting raw HTML presents too many security problems, in my opinion. Never trust user's input. Even when the content is entirely benign, next week the designer of newsletter might decide to change their formatting or incorporate some javascript and you'll be responsible for anything that might go wrong.
Therefore I would implement a parser that would drop anything but the content part and leave only b, a, h*, blockquote and similar simple elements, like the ones allowed in forum posts, as well as their styles. After that, you can display it as a normal post in a CMS. I don't see any reason why that should look differently.
As for how to isolate that from your other CSS, you don't really need to if you are careful that all of CSS rules of your CMS apply to elements with specific classes. Alternatively, do a CSS reset for your posts:
.post p {
margin: 0;
...
.post /* all the standard CSS reset rules preceded with .post */
and then
<div class="post"> content parsed from your CMS </div>
Another option that I haven't used myself but am looking to possibly leverage in a similar situation is to use the Shadow DOM which is part of the Web Components spec. My main concern is that we still have some user's using IE 11 and while there seems to be support for polyfills it doesn't look like covering all browser's is real straight forward based on what I've read elsewhere.
Some details on how to use Shadow DOM to this effect can be found here and here. I've also created a small gist that I've created to demonstrate basic idea that I've been formulating as I learn about how the Shadow DOM works which I'll be updating as I learn more. Below you can see a snapshot of the content of that gist.
<!doctype html>
<html>
<head>
<style>
.row {
display: flex;
}
.column {
flex: 50%;
padding: 10px;
height: 300px;
}
* {
color: Red;
}
</style>
</head>
<body>
<div class="row">
<div class="column" style="background-color:#aaa;">
<h2>Column 1</h2>
<div id="content1">
SOME CONTENT FROM CMS
</div>
</div>
<div class="column" style="background-color:#bbb;">
<h2>Column 2</h2>
<div id="content2">
SOME MORE CONTENT FROM CMS
</div>
</div>
</div>
<script>
document
.getElementById("content1")
.attachShadow({ mode: 'open' })
.innerHTML = `
<style>
*{all:initial}
style{display: none}
div{display: block}
</style>
<h3>This text is not red</h3>
<div>slot content: <slot></slot></div>`;
document
.getElementById("content2")
.attachShadow({ mode: 'open' })
.innerHTML = `
<style>
*{all:initial}
style{display: none}
div{display: block}
</style>
<h3>This text is not red</h3>
<div>slot content: <slot></slot></div>`;
</script>
</body>
</html>