Tag: HTML

Weekly Platform News: HTML Inspection in Search Console, Global Scope of Scripts, Babel env Adds defaults Query

In this week’s look around the world of web platform news, Google Search Console makes it easier to view crawled markup, we learn that custom properties aren’t computing hogs, variables defined at the top-level in JavaScript are global to other page scripts, and Babel env now supports the defaults query — plus all of last month’s news compiled into a single package for you.

Easier HTML inspection in Google Search Console

The URL Inspection tool in Google Search Console now includes useful controls for searching within and copying the HTML code of the crawled page.

Note: The URL Inspection tool provides information about Google’s indexed version of a specific page. You can access Google Search Console at https://search.google.com/search-console.

(via Barry Schwartz)

CSS properties are computed once per element

The value of a CSS custom property is computed once per element. If you define a custom property --func on the <html> element that uses the value of another custom property --val, then re-defining the value of --val on a nested DOM element that uses --func won’t have any effect because the inherited value of --func is already computed.

html {   --angle: 90deg;   --gradient: linear-gradient(var(--angle), blue, red); }  header {   --angle: 270deg; /* ignored */   background-image: var(--gradient); /* inherited value */ }

(via Miriam Suzanne)

The global scope of scripts

JavaScript variables created via let, const, or class declarations at the top level of a script (<script> element) continue to be defined in subsequent scripts included in the page.

Note:Axel Rauschmayer calls this the global scope of scripts.”)

(via Surma)

Babel env now supports the defaults query

Babel’s env preset (@babel/preset-env) now allows you to target browserslist’s default browsers (which are listed at browsersl.ist). Note that if you don’t specify your target browsers, Babel env will run every syntax transform on your code.

{   "presets": [     [       "@babel/preset-env",       {         "targets": { "browsers": "defaults" }       }     ]   ] }

(via Nicolò Ribaudo)

All the June 2019 news that’s fit to… print

For your convenience, I have compiled all 59 news items that I’ve published throughout June into one 10-page PDF document.

Download PDF

The post Weekly Platform News: HTML Inspection in Search Console, Global Scope of Scripts, Babel env Adds defaults Query appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , , , , , , ,

How to Section Your HTML

The sectioning elements in HTML5 are <nav>, <aside>, <article>, and <section>. <body> is also kind of a sectioning element since all content lying inside of it is part of the default document section.

Here is a brief explanation of each sectioning element and how they are used:

  • <nav> – Equivalent to role="navigation". Major site navigation that consistently appears frequently across the site. Examples include the primary navigation, secondary navigation, and in-page navigation.
  • <aside> – Equivalent to role="complimentary". Content that is only tangentially related (or not related) to the main content. Think of something like a sidebar with supplementary information, a note within an article, or the outer container for a list of related articles at the bottom of a blog post.
  • <article> – Equivalent to role="article". Content that is self-contained in that it makes sense on its own when taken out of context. That could mean a widget, a blog post or even a comment within a blog post.
  • <section> – Equivalent to role="region". Content that needs extra context from its parent sectioning element to make sense. This is a generic sectioning element that is used whenever it doesn’t make sense to use the other more semantic ones.

Contents

This is a very long article that I suspect you will want to come back to and reference multiple times. To make that easier, here is a list of all the article headings:

Jump to article heading
  1. When to use <nav>
    1. A <nav> is unnecessary around a search form
    2. Don’t use the word “nav” or “navigation” in the label
    3. Questions to ask yourself
    4. A <nav> doesn’t have to be a list of links
  2. Avoid nesting an <aside> inside an <aside>
  3. Article is like “Block”; Section is like “Element”
    1. Comments sections
  4. Don’t swap <div> for <section>
  5. Headers and footers
    1. What goes inside headers?
    2. What goes inside footers?
  6. Sectioning elements and the document outline algorithm
    1. No browser supports the document outline algorithm
  7. Sectioning content
  8. The <main> element
  9. You need to label your sections. Here are three methods.
    1. Method 1: Add an aria-label attribute
      1. The aria-label translation issue
      2. Positives
      3. Negatives
    2. Method 2: Add a <h#> element to it
      1. Heading placement
      2. Only one heading of the highest level per sectioning element
      3. The heading always comes first
      4. Making visually hidden section labels out of headings
      5. Headings are well-supported by structure analysis tools
      6. Positives
      7. Negatives
    3. Method 3: Use an aria-labelledby attribute
      1. Labels can be hidden without CSS
      2. Major portability issue
      3. No need to place the label near the sectioning element
      4. Turn non-heading elements into section labels
      5. Positives
      6. Negatives
  10. Only use one method at a time
  11. Adding section labels to our example layout
  12. Making Heading 1 be the first heading
  13. Concerns with the simplified outline algorithm spec
  14. Using aria on the example layout sectioning elements
    1. Using aria-label
    2. Using aria-labelledby
    3. Results of using aria
  15. What happens when you need h7?
  16. Does your site have a good structure?
  17. Download and use a screen reader

When to use <nav>

The <nav> element only ever needs to be used once per navigation block. Sub-navigation that is already contained inside a <nav> element does not need to be wrapped in a second <nav> element.

<nav aria-label="Primary">   <ul>     <li><a href="#">Primary link</a></li>     <li><a href="#">Primary link</a></li>     <li>       <a href="#">Primary link</a>       <!-- <nav> element is *not* needed again here -->       <ul>         <li><a href="#">Secondary link</a></li>         <li><a href="#">Secondary link</a></li>       </ul>     </li>   </ul> </nav>

The <nav> element is intended for only major navigation blocks. “Major” is a very subjective term though. html5doctor.com has a pretty good explanation of when it is and isn’t appropriate to use <nav>, keep in mind that the following are opinions and not official W3C rulings:

The key phrase is ‘major’ navigation. We could debate all day about the definition of ‘major’, but to me it means:

  • Primary navigation
  • Site search
  • Secondary navigation (arguably)
  • In-page navigation (within a long article, for example)

While there isn’t any right or wrong here, a straw poll coupled with my own interpretation tells me that the following shouldn’t be enclosed by <nav>:

  • Pagination controls
  • Social links (although there may be exceptions where social links are the major navigation, in sites like About me or Flavours, for example)
  • Tags on a blog post
  • Categories on a blog post
  • Tertiary navigation
  • Fat footers

html5doctor.com (strikethrough mine)

Breadcrumbs are another piece of content that should be wrapped in a <nav> element as evidenced by this W3C breadcrumb HTML example.

A <nav> is unnecessary around a search form

I disagree with HTML5 Doctor’s opinion that a site search form should be wrapped in a <nav> element (thus why I crossed it out). <nav> is intended to be wrapped around navigation links, not a form. The site search actually has its own special role that defines it as a search landmark. If you add role="search" to the search <form> element, it is announced to screen reader users as a search landmark. Screen reader users will also be able to navigate to it when navigating via landmarks. If there are multiple search forms on the page, they should be differentiated using aria-label or aria-labelledby (more details on these attributes later). Don’t include the word “search” in the aria label though — that’s like saying “image of” in image alt text; it’s unnecessary. Instead, focus on what the search form is searching through. So, for the global site search, giving it aria-label="site" would be appropriate.

<!-- <nav> is not needed on a search form. --> <!-- role="search" is enough --> <form role="search" aria-label="site">   <label>     <span>Search</span>     <input type="search" />   </label>   <buton type="submit">Submit</button> </form>

A role="search" form won’t appear in a document outline but I think this is okay considering search forms are often small and self-contained. It still gets the majority of benefits that you get from using sectioning elements. Adding a sectioning element to the mix bombards the screen reader user with messages telling them that it is a search form (one for the sectioning element, one for the search role, and one for the search input label).

Don’t use the word “nav” or “navigation” in the label

Like with role="search", adding “navigation” to the label of a <nav> element only results in a screen reader saying “navigation” twice.

<nav aria-label="primary navigation">   <!-- Screen reader: "primary navigation navigation landmark" --> </nav>  <nav aria-label="primary">   <!-- Screen reader: "primary navigation landmark" --> </nav>

Questions to ask yourself

That same HTML5 Doctor article lists two questions that you can ask yourself to help you figure out if something should be wrapped in a <nav> or not:

  • Would another sectioning element also be appropriate? If yes, maybe use that instead.
  • Would you add a link to it in a “skip to” block for accessibility? If not, then it might not be worth using a <nav> element.

In those cases where the navigation is too minor to justify the use of the <nav> element, <section> is most likely the element that you should use instead.

A <nav> doesn’t have to be a list of links

The most common use case for a <nav> is to wrap it around a list of links but it doesn’t have to be a list of links. If your navigation works in a different sort of way, you can still use the <nav> element.

<!-- Example taken from the <nav> element specification --> <!-- https://html.spec.whatwg.org/multipage/sections.html#the-nav-element:the-nav-element-5 --> <nav>   <h1>Navigation</h1>   <p>You are on my home page. To the north lies <a href="/blog">my   blog</a>, from whence the sounds of battle can be heard. To the east   you can see a large mountain, upon which many <a   href="/school">school papers</a> are littered. Far up thus mountain   you can spy a little figure who appears to be me, desperately   scribbling a <a href="/school/thesis">thesis</a>.</p>   <p>To the west are several exits. One fun-looking exit is labeled <a   href="https://games.example.com/">"games"</a>. Another more   boring-looking exit is labeled <a   href="https://isp.example.net/">ISP&#x2122;</a>.</p>   <p>To the south lies a dark and dank <a href="/about">contacts   page</a>. Cobwebs cover its disused entrance, and at one point you   see a rat run quickly out of the page.</p> </nav>

In this same vein, it’s okay to have small bits like intro text in the <nav> element as long as the primary focus of the content is on the navigation links. Introductory content is best placed inside a <header> in the <nav> element. I’ll go into more depth on headers and footers later.

<nav>   <header>     <h2>In this section</h2>     <p>This is some intro text describing what you will find in this section.</p>   </header>   <ul>     <li><a href="#">Sub section one</a></li>     <li><a href="#">Sub section two</a></li>   </ul> </nav>

Avoid nesting an <aside> inside an <aside>

In the same way that <nav> shouldn’t really ever be nested inside another <nav> element, <aside> elements also tend not to be nested inside each other. <aside> is used to represent content that is tangentially related to the content around it. That means placing an aside inside an aside is basically announcing a tangent away from something that in itself is a tangent away from the main content.

<!-- Don't do this --> <aside aria-label="Side bar">    <aside>     <h2>Share</h2>     <ul>       <!-- List of social media links -->     </ul>       </aside>    <aside>     <h2>Recommendations:</h2>     <ul>       <li>         <article>           <h2><a href="#">Related article title</a></h2>           <p>Article description</p>         </article>       </li>       <!-- List of recommended articles continues -->     </ul>   </aside>  </aside>

If you have a sidebar that has multiple sections, don’t nest <aside> elements inside of <aside> elements like in the example above. Instead, make the sidebar a single <aside> and then use <section> (or another appropriate sectioning element) to create the different sections.

<!-- Do this instead --> <aside aria-label="Side bar">    <section>     <h2>Share</h2>     <ul>       <!-- List of social media links -->     </ul>       </section>    <section>     <h2>Recommended articles:</h2>     <ul>       <li>         <article>           <h2><a href="#">Related article title</a></h2>           <p>Article description</p>         </article>       </li>       <!-- List of recommended articles continues -->     </ul>   </section>  </aside>

Article is like “Block”; Section is like “Element”

<section> and <article> are easy to get confused with one another. If you are familiar with “Block Element Modifier” (BEM) syntax, then an easy way to think of the difference between the two is that an <article> is a bit like the “B” (or “Block”) in BEM. It is a container that stores self-contained content that still makes sense when placed in a different context. Individual tweets on Twitter and each list item on a search results page would be considered <article> elements.

<section> is like the “E” (or “Element”) in BEM. It is a sub-section that requires context from its parent sectioning element to make sense. <section> is a generic catch-all sectioning element that you use when it doesn’t make sense to use the other sectioning elements. So, if in doubt, go with <section>.

Note that if something is styled as a “Block” in BEM, that doesn’t automatically mean that it is an <article> element. Same goes for BEM “Elements” and <section> elements. The element of something should be based on the meaning of the content, not how the content looks.

Comments sections

Something that may surprise people is that individual comments on a blog post are also considered articles, even though they are in reply to the main blog post. The <article> element wrapping around the main blog post should also wrap around the comments section though. This is to represent that the comments go with the main article.

<article>   <h1>I am an awesome blog post!</h1>   <p>I am some body text content.</p>    <section>     <h2>Comments</h2>     <ul>       <li>         <article>           <h2>Username</h2>           <p>This is the comment body text.</p>           <footer>             <p>               Meta data like post date makes sense               in either the header or the footer.             </p>           </footer>         </article>       </li>     </ul>   </section> </article>

Don’t swap <div> for <section>

Just because we have these fancy sectioning elements now, it doesn’t mean that the good old <div> element has lost all of its usefulness. <div> has no semantic meaning, so it is quite useful whenever we are altering the HTML purely for the sake of styling purposes.

Let’s say that we have a blog post contained inside an <article> element that we need to wrap in something for the sake of styling purposes.

<!-- I need a wrapper element --> <article>   <h1>I am a blog post</h1>   <p>I am some content</p> </article>

Reaching for the <section> element in this circumstance is not the right thing to do.

<!-- Do not do this --> <section class="wrapper">   <article>     <h1>I am a blog post</h1>     <p>I am some content</p>   </article> </section>

Though <section> is technically a generic element, <div> is the far more appropriate option in this circumstance. This new wrapping container is not meant to have any semantic meaning behind it and that is exactly what <div> is designed to be used for.

<!-- Use a <div> if the element is only used for styling purposes --> <div class="wrapper">   <article>     <h1>I am a blog post</h1>     <p>I am some content</p>   </article> </div>

Another way to remember this: if you can’t think of a meaningful heading to apply to a <section>, then it probably shouldn’t be a <section>.

Headers and footers

Although they don’t necessarily need to, sectioning elements may contain a single <header> and a single <footer> with the header being at the top of the section and the footer being at the bottom.

A basic sectioning element with a header and a footer.

Sectioning elements can be nested inside one another as many times as is needed based on the content.

Nested sectioning elements

The header and footer in a sectioning element can also contain sectioning elements.

Headers and footers containing sectioning elements

The one major restriction around nesting sectioning elements is that headers and footers cannot be nested inside other headers and footers.

Nesting headers and footers inside one another is not allowed.

What goes inside headers?

Headers are used for introductory content. Appropriate things to include in <header> elements include (but are not limited to):

  • The heading element (<h1><h6>)
  • An introductory paragraph or statement.
  • A profile picture
  • A logo
  • A search form
  • Primary navigation
  • Author’s name
  • Post/updated date
  • Meta data
  • Social media links

What goes inside footers?

Footer elements primarily hold things like meta data and minor supporting content. Appropriate things to include in <footer> elements include (but are not limited to):

  • Copyright information
  • Legalities
  • Footnotes
  • Low priority site navigation
  • Author’s name
  • Post/updated date
  • Meta data
  • Social media links

You will notice that there is some cross over between the header and the footer in terms of content that is appropriate to both. This is mostly because meta-type content fits well in either element. It mainly comes down to the design that you are trying to achieve. <header> elements do tend to signify that the content inside of them is of greater importance than the content inside of a <footer> element though.

Sectioning elements and the document outline algorithm

An important thing to know about these sectioning elements is that they are all supposed to feature a <h#> element inside of them (or be labeled in some other way, but more on that later). This is primarily for the sake of something called the document outline algorithm. This is an algorithm that uses sectioning elements to help determine what level a heading (<h#>) should be without having to rely exclusively on the number that the developer has provided. So, have you ever wondered whether or not it’s okay to have more than one <h1> on a page? This is meant to make that a non-issue (but hold on for a sec, because there is more to the story).

<!-- No Document outline algorithm --> <article>   <h1>Primary heading</h1>    <h2>Secondary heading</h2>   <p>Some text.</p>    <h3>Tertiary heading</h3>   <p>Some text.</p> </article>
<!-- With document outline algorithm --> <article>   <h1>Primary heading</h1> <!-- Recognized as <h1> -->      <!-- sectioning element sets new heading level context -->   <section>     <h1>Secondary heading</h1> <!-- Recognized as <h2> -->     <p>Some text.</p>      <h2>Tertiary heading</h2> <!-- Recognized as <h3> -->     <p>Some text.</p>   </section>  </article>

There is a lot more to learn about the document outline algorithm. I’ll stop here though because…

No browser supports the document outline algorithm

There is not a single browser that supports this method of creating a heading structure. This is a shame. It would make building accessible websites much easier if we didn’t have to worry so much about using the correct heading level all the time.

As far as I’m aware, there are two main reasons why no browser has implemented the algorithm. One is that browser vendors are afraid of breaking the heading structure of sites that have used sectioning elements incorrectly. The other reason is that the current document outline algorithm spec is difficult to implement and no browser vendor has been willing to put the time into implementing it yet.

In reference to the first reason, there is a long discussion about incorporating a new <h> element instead of using the <h1> element to tell browsers to use the document outline algorithm. I was in favor of this new <h> element idea until I realized that an attribute on the <html> element or adding a <meta> tag to the <head> would work even better as a means of telling browsers it was safe to use the algorithm. It is also better for headings to fall back to a <h1> in unsupported browsers than falling back to a <span>.

If you would like to play around with this <h> concept though, there is a plugin called hfill. It allows you to nest <hx> headings inside sectioning elements to create the document outline without having to worry about heading levels so much. There is a demo available for you to try it out. The major flaw in this plugin though is that the only way to increment heading levels is by nesting sectioning elements inside one another. There is no <h1>-is-greater-than-<h2> dynamic in this plugin which is the main reason I fell out of love with this <h> element idea. This lack of heading hierarchy would make CMS rich text editors far too difficult for clients to use.

As for the issue around implementation difficulty, work is being done to produce a simplified spec that browser vendors are more likely to adopt. The document outline algorithm has been in the HTML specifications for years. Hopefully this simplified spec will allow the algorithm to become a reality.

Although the algorithm is not supported anywhere yet, we can still build with the algorithm in mind. If we build with it in mind, then we gain the following benefits:

  1. We future-proof our sites in case the algorithm ever does get implemented.
  2. We can significantly improve the user experience for screen reader users.
  3. We potentially improve search engine optimization (SEO) due to search engines being able to better understand the site’s content.
  4. We can create a better user experience for users by allowing them to use native browser features that make use of sectioning elements, like Reader Mode.

Sectioning content

Take a look at this mock-up layout I put together and think about how you might split it up into sections.

Mock-up layout featuring a logo, primary nav, and search in the header, a secondary navigation in a left sidebar, and a main content area  in the middle with primary and secondary headings, a sidebar on the right with share links and links to recommended articles.

This is how I would split the layout up into sectioning elements (only the solid lines represent sectioning elements).

Layout showing where various sectioning elements would appear.

In terms of HTML markup, it looks like this:

<body>    <header>     <a href="/" title="Go to home page">       <img src="logo.png" alt="Site logo">     </a>     <nav>       <ul>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>       </ul>     </nav>     <form role="search" aria-label="site">       <label>         <span>Search</span>         <input type="search"/>       </label>       <button type="submit">Submit</button>     </form>   </header>    <nav>     <ul>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>     </ul>   </nav>    <main>     <article>       <h1>Main article heading</h1>       <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>        <h2>Article secondary heading</h2>       <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>       <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>     </article>   </main>    <aside>     <section>       <h2>Share</h2>       <ul>         <li><a href="#">Facebook</a></li>         <li><a href="#">Twitter</a></li>         <li><a href="#">Email</a></li>       </ul>     </section>     <section>       <h2>Recommended</h2>       <ul>         <li>           <article>             <h3><a href="#">Related article</a></h3>             <p>Article description</p>           </article>         </li>         <li>           <article>             <h3><a href="#">Related article</a></h3>             <p>Article description</p>           </article>         </li>       </ul>     </section>   </aside>    <footer>     <ul>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>     </ul>   </footer>  </body>

The <main> element

There is a very important semantic element that I used in the markup above that I haven’t covered yet and that is the <main> element. The <main> element represents the primary content of the page. It is not supposed to feature any side bars or navigation elements in it. You also must not have more than one <main> element on the page unless all other <main> elements on the page have a hidden attribute applied to them (this is for the sake of SPAs).

The <main> element is not a sectioning element. This means that it doesn’t help contribute to the document outline algorithm and it can’t feature a <header> or <footer> element as a direct child. It is a landmark element though so screen reader users are able to navigate to it quite easily.

I’m not 100% sure if using <article> in the <main> element like I have done above is necessary. Semantically, it does make sense. The main content is self-contained, thus justifying use of the <article> element in this way. From a document outline algorithm perspective, the <article> element also helps with the document structure.

From a usability point of view, it feels a bit unnecessary and the document outline algorithm doesn’t even work anywhere at the moment. I’m going to continue using it throughout my examples but I would be interested to know what other people think about this in the comments section.

You need to label your sections. Here are three methods.

I am going to be saying the word “label” a lot throughout this article. Keep in mind that I am not talking about the <label> element. The <label> element is not used to label sectioning elements.

Sectioning elements require labels so that screen reader users are able to quickly identify what content they can find inside that particular section of the site. I consider using sectioning elements without providing associated section labels as an accessibility fail, unless it is the only one of its type on the page. It is also recommended that the exact same label text not be used on multiple sectioning elements (or heading elements). This makes each section more recognizable to screen reader users which helps them navigate the site more easily.

There are three ways to label a sectioning element. In the following examples, I refer to “transport” and “portability” as a way of explaining how easy it is to save the section into a component and use that component multiple times in multiple different contexts.

I also provide lists of positives and negatives in the examples as well. In these lists, I assume that you want the section label to be readable by screen readers but hidden from sighted users.

Method 1: Add an aria-label attribute

This is the quickest and easiest way to label a sectioning element.

<section aria-label="Label for this section">   <p>Content for this section</p> </section>
#The aria-label translation issue

The main draw back of aria-label (at the time of writing) is that most browsers are unable to translate these values for users who speak a different language than you. The developers at Google recently fixed this bug in Chrome, however this is still a problem for every other browser.

If your website has a large international audience or you know that many of your users do not speak your language, you should probably avoid using this attribute until all browsers support the translation of this property. If you don’t have those sorts of users, it’s pretty safe to assume that the non-sighted users viewing your site are able to understand your language — well enough to be able to navigate your site, anyway.

If you need more convincing, let’s say your site has very few international users. That means your users generally come from the same country as you. If they come from the same country then they are likely to speak the same language as you, so there is already a fairly small percentage of your users that don’t understand the native language of your site. Now take into account that aria-label only affects screen reader users. That is now only a fraction of an already small percentage of your users who will experience the issue. And now consider that Chrome (by far the most popular browser in the world) now supports translation of the aria-label attribute. The user has to also not be using an up to date version of Chrome as their browser for the translation issue to be a problem. If you factor all of that together, it is highly probable that you may not have any users who are both able to perceive the aria-label attributes and are incapable of comprehending what they say. This makes me feel like the bad multi-lingual support in aria-label isn’t really worth worrying that much about unless you have a large international audience or you have many users that you know do not speak your language.

#Positives
  • Super quick and easy to implement.
  • Doesn’t affect heading structure.
  • Makes components easy to transport.
  • Is invisible to sighted users.
#Negatives
  • Not translated into other languages in non-Chrome browsers (at time of writing).
  • Often not supported by page structure analysis tools.
  • Confusion can arise from not knowing what level other headings inside the section should be at.

Method 2: Add a <h#> element to it

By <h#> I mean <h1>, <h2>, <h3>,<h4>,<h5>, or <h6> depending on what makes sense. Adding a heading to a sectioning element is a quick way to label it.

#Heading placement

The heading can be placed either directly in the sectioning element, like this:

<section>   <h1>Heading</h1>   <p>content</p> </section>

…or placed inside the <header> element:

<section>   <header>     <h1>Heading</h1>     <p>I'm a byline</p>   </header>    <p>Content</p> </section>

You can also place as many <div> wrapper elements between the sectioning element and the heading as you want.

<!-- This is perfectly fine --> <section>   <div>     <header>       <div>         <h1>Heading</h1>         <p>I'm a byline</p>       </div>     </header>      <p>Content</p>   </div> </section>
#Only one heading of the highest level per sectioning element

There should really only be one heading of the highest level in a sectioning element. The spec says that when there are multiple top level headings or headings of a higher level than the first, the browser is supposed to close the previous sectioning element and start a new one of the same type.

The first element of heading content in an element of sectioning content represents the heading for that explicit section. Subsequent headings of equal or higher rank start new implied subsections that are part of the previous section’s parent section. Subsequent headings of lower rank start new implied subsections that are part of the previous one. In both cases, the element represents the heading of the implied section.

HTML 5.3, Headings and Sections

In reality, the browser uses the first heading as the section label but these implied sections are never created. It just announces the heading as is when it encounters it. It’s not earth-shatteringly bad but it is somewhat confusing.

<!-- Avoid this: --> <section>   <h2>Heading level two labeling a section</h2>   <p>Content</p>    <!-- Don't use same level or higher headings as the one labeling the section -->   <h2>This is also a heading level two</h2>   <p>Content</p> </section>   <!-- Do this instead: --> <div>   <section>     <h2>Heading level two labeling a section</h2>     <p>Content</p>   </section>   <section>     <h2>Heading level two labeling a different section</h2>     <p>Content</p>   </section> </div>
#The heading always comes first

If a sectioning element has a <h#> element, that top level heading should always be the very first piece of content inside that sectioning element. Failing to do so counts as an accessibility fail.

If you find yourself needing to place content before your heading (like an image, for example), you can use Flexbox to rearrange the visual order. This will allow it to look like the image comes before the heading but in the markup the heading comes before the image. There is a bug in IE that will sometimes cause text to not wrap in a flex-direction: column; element. You can work around this issue by applying a max-width to the flex-child element.

<!-- Don't do this --> <section>   <img src="image.jpg" alt="Don't place content or images before the heading" />   <h2>Headings should always come first</h2>   <p>Place regular content after the heading</p> </section>  <!-- Do this instead --> <section class="example">   <h2>Headings should always come first</h2>   <img src="image.jpg" alt="Don't place content or images before the heading" />   <p>Place regular content after the heading</p> </section>  <style> .example {   display: flex;   flex-direction: column; } .example img {   order: -1; } </style>

Note that rearranging the visual order to satisfy WCAG Guideline 1.3.2: Meaningful Sequence can conflict directly with WCAG Guideline 2.4.3: Focus Order. For example, if that image is a link to an article and the heading you are placing it above is also a link to the article, placing the heading first breaks the focus order. Placing the image first breaks the meaningful sequence.

In situations like this where these two guidelines conflict with one another, my opinion is that the 1.3.2: Meaningful Sequence guideline is the more important guideline to follow if you aren’t able to resolve the conflict in some way. Failing focus order leads to the user suffering a moment of discomfort as they are tabbing through the content and focus is sent to an unexpected location. Failing to follow a meaningful sequence leads to a confused user unsure of the relationship between different bits of content.

#Making visually hidden section labels out of headings

Headings are visible to sighted users by default. This makes them super useful if you want the heading to be visible. A lot of the time, we don’t want the label for our sectioning element to be visible though. In order to stop our sighted users from seeing the label, we need to use some CSS.

<style> .visually-hidden {   position: absolute;   opacity: 0;   pointer-events: none; } </style>  <section>   <h1 class="visually-hidden">Heading</h1>   <p>content</p> </section>
#Headings are well-supported by structure analysis tools

Headings also have a huge advantage for developers in that any page structure analysis tool that you can find will have support for them. This makes heading structures easy to test and debug. The other two section labeling methods have very poor support in testing tools. Not even the official W3C Validator service supports the alternatives at the moment. I posted an issue to have this fixed — please consider helping to fix the issue if you are good at coding in Java.

#Positives
  • Quick to implement.
  • Reliably appears in page structure analysis tools making it easy to test and debug.
  • All browsers will translate the text into other languages.
  • No confusion over what level other headings inside the section should be.
#Negatives
  • Affects document heading structure.
  • Need to ensure that the heading is at the correct level before use.
  • Visible to the user by default.
  • Requires CSS to hide the heading from visual users.
  • Can make components less portable due to heading structure requirements.

Method 3: Use an aria-labelledby attribute

This is what it looks like to create a hidden section label using aria-labelledby.

<section aria-labelledby="unique-id">   <div hidden id="unique-id">Label for this section</div>   <p>Content for this section</p> </section>
#Labels can be hidden without CSS

Note that I used the hidden attribute in the example to hide the div rather than a visually-hidden CSS class. aria-labelledby is able to read out text that is normally hidden from screen reader users. This adds the bonus effect of preventing the text from being read out twice by the screen reader. Don’t use the aria-hidden attribute though. Screen readers will not find the label text. Well, NVDA couldn’t find the label text when I tested it. I’m not sure about other screen readers.

#Major portability issue

aria-labelledby is the most difficult to use out of all the section labeling methods. The main aspect that makes it difficult to use is that the aria-labelledby attribute works off IDs. Things always get more complicated whenever IDs are involved. This is due to web pages only being allowed to have a single instance of an ID on the page at any one time. This makes component portability difficult.

Due to this portability issue, I would really only recommend this option if you need to support a multi-lingual audience and don’t want to mess around with the heading structure.

#No need to place the label near the sectioning element

You don’t need to place the element with the label text inside or near the section element that it labels. The text for the label can be placed in a completely different location to the sectioning element. This is thanks to the ID linking the two elements together. I’m not necessarily saying that it is a good idea to do this, but it is a feature of aria-labelledby that you should be aware of.

<div hidden id="unique-id">Label for this section</div>  <!-- 1,000 lines of other HTML -->  <section aria-labelledby="unique-id">   <p>Content for this section</p> </section>
#Turn non-heading elements into section labels

There is one other key reason you may want to use aria-labelledby. If you have a visible non-heading element on the page that you want to use as the label for a section, aria-labelledby is perfect for this. A <legend> element inside a <fieldset> is a common use case for this. This doesn’t mean that you have to wrap fieldsets in sectioning elements. I’m just pointing it out in case you spot a need for it.

<section aria-labelledby="section_label">   <fieldset>     <legend id="section_label">       I am both the fieldset legend and the section label     </legend>      <!-- Form fields go here -->      </fieldset> </section>
#Positives
  • All browsers will translate the text into other languages.
  • Can assign a non-heading element as the section label.
  • Text for the label does not need to be placed near the section it is labeling.
#Negatives
  • Requires the use of IDs to work.
  • Difficult to transport.
  • It can potentially be difficult to track down where the text for the label is stored in your source code.
  • Text is visible by default unless a hidden attribute is used.
  • Text might get read out twice by some screen readers if the text is not hidden.
  • Confusion can arise from not knowing what level other headings inside the section should be at.

Only use one method at a time

Don’t use a <h#>, an aria-label and/or an aria-labelledby attribute at the same time on the same sectioning element. Only every use one labeling method at a time for each sectioning element. Using multiple methods is super confusing and leads to the label being overwritten. It’s a bit like declaring the same property twice in CSS. I wasn’t sure how a screen reader would actually handle this so I created the most ridiculous <section> ever and ran it through NVDA.

<!-- Don't do this --> <section aria-label="Is this the section label?" aria-labelledby="is_this_the_label">   <h1>Or is this the section label?</h1>   <p id="is_this_the_label">Only ever use one at a time.</p> </section>

This is the order of priority that NVDA gave to the various labeling methods from strongest to weakest:

  1. aria-labelledby
  2. aria-label
  3. <h#>

Adding section labels to our example layout

For a long time, I used headings as the only means of labeling sections. The poor multi-lingual support provided by aria-label scared me; and aria-labelledby was far too cumbersome to be my primary labeling method. We run into a bit of an issue though if we use only headings to label sections. I’ll show you what I mean.

<style>   .visually-hidden {     position: absolute;     opacity: 0;     pointer-events: none;   } </style>  <body>    <header>     <a href="/" title="Go to home page">       <img src="logo.png" alt="Site logo">     </a>     <nav>       <h2 class="visually-hidden">Primary</h2>       <ul>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>       </ul>     </nav>     <form role="search" aria-label="site">       <label>         <span>Search</span>         <input type="search"/>       </label>       <button type="submit">Submit</button>     </form>   </header>    <nav>     <h2 class="visually-hidden">Secondary</h2>     <ul>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>     </ul>   </nav>    <main>     <article>       <h1>Main article heading</h1>       <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>        <h2>Article secondary heading</h2>       <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>       <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>     </article>   </main>    <aside>     <h2 class="visually-hidden">Sidebar</h2>     <section>       <h3>Share</h3>       <ul>         <li><a href="#">Facebook</a></li>         <li><a href="#">Twitter</a></li>         <li><a href="#">Email</a></li>       </ul>     </section>     <section>       <h3>Recommended</h3>       <ul>         <li>           <article>             <h4><a href="#">Related article</a></h4>             <p>Article description</p>           </article>         </li>         <li>           <article>             <h4><a href="#">Related article</a></h4>             <p>Article description</p>           </article>         </li>       </ul>     </section>   </aside>    <footer>     <ul>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>     </ul>   </footer> </body>

If we look at our heading structure now, it will look like this (italics = visually hidden; bold = visible):

    • <h2> Primary [nav]
    • <h2> Secondary [nav]
  • <h1> Main article heading
    • <h2> Article secondary heading
    • <h2> Sidebar
      • <h3> Share
      • <h3> Recommended
        • <h4> Related article
        • <h4> Related article

Notice that our <h1> heading isn’t at the top of the list? It really doesn’t feel right having two <h2> headings above the <h1> heading.

This form of heading structure is actually allowed by the W3C so it doesn’t count as an accessibility fail. I still think that this is a pretty bad UX for screen reader users though. It is not a logical progression from <h1> to <h2>. It makes the most sense if the first heading you encounter on the page is a <h1> then progress into <h2> then <h3> and so on.

Making Heading 1 be the first heading

For a very long time, I thought the absolute best way to handle this conundrum was to make the <h1> visually hidden and have it be the very first piece of content on the page. The thing that everyone thinks is the <h1> actually becomes a <h2>.

This is what that sort of structure looks like in practice:

<style>   .visually-hidden {     position: absolute;     opacity: 0;     pointer-events: none;   } </style>  <!-- Don't do this --> <body>   <header>     <h1 class="visually-hidden">Main article heading</h1>     <a href="/" title="Go to home page">       <img src="logo.png" alt="Site logo">     </a>     <nav>       <h2 class="visually-hidden">Primary</h2>       <ul>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>       </ul>     </nav>     <form role="search" aria-label="site">       <label>         <span>Search</span>         <input type="search"/>       </label>       <button type="submit">Submit</button>     </form>   </header>    <nav>     <h2 class="visually-hidden">Secondary</h2>     <ul>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>     </ul>   </nav>    <main>     <article>       <h2><span class="visually-hidden">Body:</span> Main article heading</h2>       <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>        <h3>Article secondary heading</h3>       <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>       <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>     </article>   </main>    <aside>     <h2 class="visually-hidden">Sidebar</h2>     <section>       <h3>Share</h3>       <ul>         <li><a href="#">Facebook</a></li>         <li><a href="#">Twitter</a></li>         <li><a href="#">Email</a></li>       </ul>     </section>     <section>       <h3>Recommended</h3>       <ul>         <li>           <article>             <h4><a href="#">Related article</a></h4>             <p>Article description</p>           </article>         </li>         <li>           <article>             <h4><a href="#">Related article</a></h4>             <p>Article description</p>           </article>         </li>       </ul>     </section>   </aside>    <footer>     <ul>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>     </ul>   </footer> </body>

Now we have a document outline that looks like this (italics = visually hidden; bold = visible):

  • <h1> Main article heading
    • <h2> Primary [nav]
    • <h2> Secondary [nav]
    • <h2> Body: Main article heading
      • <h3> Article secondary heading
    • <h2> Sidebar
      • <h3> Share
      • <h3> Recommended
        • <h4> Related article
        • <h4> Related article

This mostly feels right. The <h1> is at the top and it all flows down perfectly with the <h2> elements representing major page sections and the <h3> elements representing sub sections. The main awkward bit is that the actual <h1> and the thing that everyone thinks is a <h1> are essentially duplicates of one another.

It wasn’t until I wrote up the first version of this article, had it nearly published, then had it thrown out the window, that I started to think differently. I talked with two accessibility consultants about the issue. They both agreed that, though this is a clever technical solution to the problem, it detracts from the experience of the very people that it is trying to help.

The issue is that when every other website in the world places the <h1> heading at the top of the main content area, that is what screen reader users come to expect. When your site is the special snowflake that does things differently, it confuses screen reader users and it takes them some time to figure out how your heading structure is supposed to work.

So, with that in mind, I’ve settled on a new method for handling the labeling of sectioning elements. Basically, any time I would have used a visually hidden heading, I would use an aria-label attribute now instead. If the site has a large non-native speaking audience, I would use aria-labelledby instead of aria-label.

Concerns with the simplified outline algorithm spec

If the simplified outline algorithm is approved in its current state, we will actually need to start structuring our sites like the visually hidden <h1> example anyway (just replace the <h2>, <h3> and <h4> elements with <h1> elements).

The original spec aimed to create the outline through the labeling of sectioning elements. This new spec is clearly aimed at trying to create the outline purely through heading levels. The algorithm basically calculates the heading level based on the number of ancestor sectioning elements a heading has plus the heading’s base heading level value. It’s a bit more nuanced than that in the spec, but that is the general idea of how it works in simple terms.

The simplified algorithm currently makes no mention of aria-label or aria-labelledby. This means that those attributes will not help contribute to the document outline that the simplified algorithm generates. With a lack of aria-label support, this would mean labeling a sectioning element with aria-label could easily lead to skipped heading levels deeper in the tree.

<!-- Simplified algorithm skipped heading levels issue --> <body>   <main>     <h1>Primary heading for the page</h1> <!-- interpreted as <h1> -->     <p>This is some content</p>   </main>    <!-- sectioning elements increase heading levels -->   <aside aria-label="Side bar"> <!-- aria-label does not contribute -->     <section>       <h1>Share</h1> <!-- interpreted as <h3> -->       <ul>         <!-- list of social media links -->       </ul>     </section>      <section>       <h1>Recommended articles:</h1>  <!-- interpreted as <h3> -->       <ul>         <!-- list of recommended articles -->       </ul>     </section>   </aside> </body>

The simplified spec also considers it invalid to:

It does, however, allow for there to be more than one level 1 heading at the root of the document, which I find very odd and bad for accessibility (though my concern about this seems to have been ignored).

I have voiced the issues I have with the spec and proposed possible solutions in the GitHub discussion.

For the moment, it is still best to use aria-label and/or aria-labelledby attributes instead of visually hidden headings to label sectioning elements. It isn’t worth diminishing the experience of our present day users for the sake of a spec that hasn’t even been finalized or accepted yet.

Using aria on the example layout sectioning elements

Using aria-label

This is what the HTML structure looks like if we use aria-label attributes to label the sectioning elements:

<body>   <header>     <a href="/" title="Go to home page">       <img src="logo.png" alt="Site logo">     </a>     <nav aria-label="Primary">       <ul>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>       </ul>     </nav>     <form role="search" aria-label="site">       <label>         <span>Search</span>         <input type="search"/>       </label>       <button type="submit">Submit</button>     </form>   </header>    <nav aria-label="Secondary">     <ul>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>   </ul>   </nav>    <main>     <article>       <h1>Main article heading</h1>       <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>        <h2>Article secondary heading</h2>       <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>       <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>     </article>   </main>    <aside aria-label="Sidebar">     <section>       <h2>Share</h2>       <ul>         <li><a href="#">Facebook</a></li>         <li><a href="#">Twitter</a></li>         <li><a href="#">Email</a></li>       </ul>     </section>     <section>       <h2>Recommended</h2>       <ul>         <li>           <article>             <h3><a href="#">Related article</a></h3>             <p>Article description</p>           </article>         </li>         <li>           <article>             <h3><a href="#">Related article</a></h3>             <p>Article description</p>           </article>         </li>       </ul>     </section>   </aside>    <footer>     <ul>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>     </ul>   </footer> </body>

Here is the layout in CodePen in case you want to have a play around with it (sorry mobile users, it’s not mobile friendly):

See the Pen
Mock up page layout v2 (sections article)
by Daniel Tonon (@daniel-tonon)
on CodePen.

Using aria-labelledby

But let’s assume that you have a huge international audience that speaks all sorts of languages. In that case, it is better to use the aria-labelledby attribute. Here is what that would look like:

<body>    <header>     <a href="/" title="Go to home page">       <img src="logo.png" alt="Site logo">     </a>     <nav aria-labelledby="primary-nav-label">       <div id="primary-nav-label" hidden>Primary</div>       <ul>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>         <li><a href="#">Primary nav</a></li>       </ul>     </nav>     <form role="search" aria-labelledby="search-label">       <div id="search-label" hidden>Site</div>       <label>         <span>Search</span>         <input type="search"/>       </label>       <button type="submit">Submit</button>     </form>   </header>    <nav aria-labelledby="secondary-nav-label">     <div id="secondary-nav-label" hidden>Secondary</div>     <ul>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>       <li><a href="#">Secondary nav</a></li>     </ul>   </nav>    <main>     <article>       <h1>Main article heading</h1>       <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>        <h2>Article secondary heading</h2>       <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>       <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>     </article>   </main>    <aside aria-labelledby="sidebar-label">     <div id="sidebar-label" hidden>Sidebar</div>     <section>       <h2>Share</h2>       <ul>         <li><a href="#">Facebook</a></li>         <li><a href="#">Twitter</a></li>         <li><a href="#">Email</a></li>       </ul>     </section>     <section>       <h2>Recommended</h2>       <ul>         <li>           <article>             <h3><a href="#">Related article</a></h3>             <p>Article description</p>           </article>         </li>         <li>           <article>             <h3><a href="#">Related article</a></h3>             <p>Article description</p>           </article>         </li>       </ul>     </section>   </aside>    <footer>     <ul>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>       <li><a href="#">Footer link</a></li>     </ul>   </footer> </body>

Results of using aria

The heading structure for the site at this point looks like this:

  • <h1> Main article heading
    • <h2> Article secondary heading
    • <h2> Share
    • <h2> Recommended
      • <h3> Related article
      • <h3> Related article

The document outline (assuming that the original outline algorithm is implemented) looks like this:

  • <body> Document
    • <nav> Primary
    • <nav> Secondary
    • <article> Main article heading
      • <section (implied)> Article secondary heading
    • <aside> Sidebar
      • <section> Share
      • <section> Recommended
        • <article> Related article
        • <article> Related article

You might be thinking that the document outline looks a bit bare. Shouldn’t things like the header and footer and search be announced in there as well? Keep in mind that this is just the explicit stuff. We get a lot of implicit information provided to the user for free by using correct HTML elements in a good structure. This is a simplified version of how a screen reader user might experience the site:

  • [Text used in the <title> element]
    • Banner landmark
      • Link, site logo [(on focus) “go to home page”]
      • “Primary” navigation landmark
        • [List of navigation links]
      • “Site” search landmark
    • “Secondary” navigation landmark
      • [List of navigation links]
    • Main landmark
      • “Main article heading” article landmark, heading level 1
        • [Content]
        • Heading level 2, “Article secondary heading”
          • [Content]
    • “Sidebar” complimentary landmark
      • “Share” region landmark, heading level 2
        • [List of share links]
      • “Recommended” region landmark, heading level 2
        • List with 2 items
          • Item, “Related article” article landmark, heading level 3
            • [Content]
          • Item, “Related article” article landmark, heading level 3
            • [Content]
    • Content info landmark
      • [List of footer links]

As you can see, the site structure becomes quite clear and understandable to screen reader users when you factor in all of the extra implicit information that you get from using a good HTML structure

So, even though no browser supports the document outline algorithm, it is still worth putting some effort into thinking about the outline. Screen readers still tell users what type of section something is, where sections start and (sometimes) end (depends on the screen reader), and what the section label is. This means that your efforts to make a good document structure do not go to waste.

This type of structure comes with multiple benefits:

  • The page is 100% compatible with the document outline algorithm, future proofing it in-case the algorithm is ever implemented in a real browser.
  • The heading structure is completely logical.
  • Screen reader users navigating via headings can quickly jump to important information.
  • Screen reader users navigating via landmarks have lots of useful landmarks to move about the page.
  • Screen reader users are able to quickly understand what each section contains without having to read any of the content inside of them.
  • Content is grouped into semantic sections, so screen reader users do not get confused when leaving one section and entering another.
  • Search engines are able to better understand what information each section holds, which could potentially improve SEO.
  • Sighted users can take advantage of native browser features like Reader Mode.

What happens when you need h7?

There is one more sticking point when it comes to labeling sectioning elements that I haven’t addressed yet. Let’s say you have somehow managed to use up all six native heading levels and are now stuck needing one more. What do you do?

You could use the aria-labelledby technique if it is just for the sake of labeling a section. Let’s say that you really want this heading to appear in the heading structure though, or maybe you just want to avoid using IDs as much as possible. Whatever the reason, you need an <h7> element but <h7> doesn’t exist.

This is when the aria-level attribute comes to the rescue. The aria-level attribute will define what the heading level should be for elements that have role="heading" applied to them. This is how the W3C recommend creating a <h7> element:

<div role="heading" aria-level="7">This is a valid heading level 7 element</div>

Not all screen readers support this syntax. I know that JAWS treats these like <h2> elements rather than <h7> elements. If you know of any screen readers that this doesn’t work in, please report the bug to the screen reader developer and also leave a comment down below.

When I need to reach for an <h7>, I’ll often use the implied role="heading" from an <h6> element instead. The aria-level attribute will override the implicit “6” level of the <h6> element. This isn’t exactly endorsed by the W3C though. It is cleaner and will allow the heading to still appear in document outline and heading structure testing tools (though they will typically appear as <h6> or <h2> level headings, not as <h7> level headings).

<h6 aria-level="7">This is also a valid heading level 7 element</h6>

By using aria-level, you now have access to an infinite number of heading levels!

Does your site have a good structure?

Now that you know how to do a proper HTML structure, are you able to apply what you have learned to your website?

I found a pretty good browser extension called “Headings Map” that is available for both Chrome and Firefox. This extension will allow you to easily see both a flat heading structure representation of your site (i.e. how all browsers currently read the heading structure) and what the document structure looks like in a browser that supports the document outline algorithm (i.e. how a theoretical future browser that supports the outline algorithm would present the site structure). The HTML5 Outline view needs to be enabled in the settings menu first. This is to prevent users from being fooled into thinking that they are able to use the outline algorithm in production sites.

The Headings Map extension showing the flat heading structure result on the left and the result of the Document Outline Algorithm on the right.

Headings Map does not currently support the aria-label and aria-labelledby attributes on sectioning elements in the HTML5 outline tab. I have been talking with the developer and he is working on fixing this issue. If you know of a good document outline testing tool that already takes aria-label and aria-labelledby into account, please share a link to it in the comments.

Once you have a good document structure testing tool, check that both the heading structure and the document outline display a logical order with no missing headings or missing section labels anywhere.

Download and use a screen reader

The best way to test the implied semantics that you get from using correct HTML is to download an actual screen reader and try navigating your site with it. NVDA is one of the most used screen readers used by real screen reader users. It’s also free!

Be aware that the default settings for NVDA are optimized for usage by blind users. These default settings can drive sighted users insane. To enjoy your time using NVDA, perform the following steps (steps are based on a Windows set up, I don’t have a Mac):

  1. Download NVDA and install it
  2. Create a shortcut to NVDA in your task bar (You will be opening and closing it regularly while testing)
  3. Open NVDA from the task bar
  4. Find NVDA in your system tray

    Location of NVDA on Windows
  5. Right click the tray icon > “preferences” > “settings”
  6. Select “mouse” in the left panel
  7. Deselect “Enable mouse tracking” (You can now move your mouse without NVDA screaming at you)
  8. Press “OK”
  9. Right click the tray icon > “Tools” > “Speech Viewer” (You can now see a log of everything NVDA says, don’t rely purely on this when testing though)
  10. In the Speech Viewer, check the “Show Speech Viewer on Startup” checkbox (It will open the Speech Viewer when you open NVDA)
  11. Familiarize yourself with some of the keyboard controls
  12. To close NVDA, Right click the tray icon > “Exit” > “OK”

NVDA currently doesn’t support <article> and <section> elements. There is an issue on GitHub for supporting <article> elements. When I began writing this article <section> elements were already supported. Support for <section> seems to have dropped for some reason. This means NVDA should be fixed. It doesn’t mean you should stop using the correct semantics in your HTML.

Build your website with the document outline in mind then test the semantics with Headings Map and NVDA (or another screen reader). If you do, you will make your screen reader users very happy. You might even make the search engines happier too. 😊


Special thanks to Eric Bailey (accessibility adviser for CSS Tricks) and Kevin Galvin (a principal consultant at me 2 accessibility) for their advice around the usability issues of using a visually hidden <h1> element at the top of the page and suggesting aria-label as an alternative to using visually hidden headings.

The post How to Section Your HTML appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

Why, How, and When to Use Semantic HTML and ARIA

Semantic HTML and Accessible Rich Internet Applications (ARIA) help create interfaces that work for everyone in the most performant, robust, and simple way possible. They add essential meaning to your content, which lets web browsers, search engines, screen readers, RSS readers, and ultimately users understand it.

And yet, many people still don’t use them. I wanted to know why, so I set up a Twitter poll. The most common reason people gave was a lack of awareness and understanding of the benefits of using semantic HTML and ARIA.

Let’s look over the benefits of using HTML and ARIA, why starting with semantic HTML is the way to go, and why ARIA ought to come in as a last resort.

Starting with raw text

The <body> element of an HTML document contains the main content a user sees on a page. If content is put inside the body without any additional elements, the browser has no way of differentiating between different types of content, like paragraphs and headings.

<body> A Study of Butterflies  Butterflies are little bugs with cute wings.  Butterfly Habitats  Butterflies live in flower houses and hang out at dank coffeeshops. </body>

If the browser can’t differentiate between pieces of content, then it can’t present that content to the user in a meaningful way. That means:

  • We can’t style the headings differently from paragraphs.
  • It’s harder for search engines to interpret the content, meaning it’s likely to rank poorly and be difficult for users to find.
  • Screen readers and other assistive technology can’t communicate it properly to the user.

Not to mention, it’s more than a bit awkward visually:

A screenshot of the HTML rendered on the front end, which displays as a single line of text.

Adding some structure with HTML

To provide some structure we could wrap the lines of text here in divs like this:

<div>A Study of Butterflies.</div> <div>Butterflies are little bugs with cute wings.</div> <div>Butterfly Habitats</div> <div>Butterflies live in flower houses and hang out at dank coffeeshops.</div>

This is slightly better because each piece of content is displayed in the browser on its own line instead of one long unbroken line of text.

A screenshot of the HTML rendered on the front-end showing the content on four lines, one for each div.

But there’s still a distinct lack of meaning.

Which are headings and which are paragraphs? It’s hard to tell, and impossible for assistive technology to determine. That’s because the headings and paragraphs are wrapped in divs which are meaningless on their own. In this example, browsers, CSS, search engines and screen readers are still none the wiser.

Communicating meaning with styles

We could add styling to the divs because they can be targetted with CSS. This lets us improve the visual appearance to provide meaning, context, and hierarchy.

See the Pen
Non-Semantic HTML Demo
by Geoff Graham (@geoffgraham)
on CodePen.

Here the CSS targets the first and third divs to apply heading styles. This isn’t maintainable because another paragraph added afterward, for example, would get styled as a heading.

We could give each div a unique attribute such as an ID or class name, to give us more styling control, like this:

<div class="heading1">A Study of Butterflies</div> <div class="paragraph">Butterflies are little bugs with cute wings.</div> <div class="heading2">Butterfly Habitats</div> <div class="paragraph">Butterflies live in flower houses and hang out at dank coffeeshops.</div>

I explain why you should use classes instead of IDs for styling in my online book, MaintainableCSS.

Now we can target the different elements with CSS like this:

.heading1 { /* styles here */ } .paragraph { /* styles here */ } .heading2 { /* styles here */ }

While this approach is a little better, it only communicates meaning for sighted users. It doesn’t provide meaning to search engines, RSS readers and screen readers. In other words, it’s not semantic and not very accessible as a result.

Introducing semantic HTML

HTML provides many elements that are designed to give meaning to content, including elements for headings and paragraphs. So, instead of relying on divs with classes named by the developer, we can use predefined HTML elements instead.

<h1>A Study of Butterflies</h1> <p>Butterflies are little bugs with cute wings.</p> <h2>Butterfly Habitats</h2> <p>Butterflies live in flower houses and hang out at dank coffeeshops.</p>

Much better! With semantic HTML like this, the content will inherit default styles from the browser (aka User Agent). We can even use other semantic HTML elements, like <b> which tells the browser to “bring to attention” by making text bold.

A screenshot of the HTML rendered on the front end showing the content with a clearer hierarchy of a Heading 1, paragraph, Heading 2 and paragraph, thanks to semantic HTML.

Crucially, using semantic HTML also means:

  • We can use CSS to add our own styling.
  • Search engines can index the content so that it ranks well enough that users can find it.
  • RSS readers can parse and style the elements appropriately.
  • Screen readers and other assistive technologies can communicate elements properly to the user.

While it’s not massively important in these short examples, the code is also more concise which makes a big difference when considering an entire site.

Semantic HTML is standards-based and stable. This means any HTML processor in the future will be able to understand it and present it correctly to users. It will also help subsequent code authors if they need to make changes.

Additional benefits of semantic HTML

In addition to the benefits we’ve covered so far, some browsers add useful enhancements to semantic HTML for free.

For example, using the HTML telephone input (<input type="tel">) will give users a telephone-specific keypad on some mobile browsers.

Identifying a form input as a telephone field will produce a telephone-specific keypad in iOS. Careful though, because it’s just for telephone numbers and not meant for any number, like credit cards.

Other browsers give users the option to switch to a simplified view of the page, like Safari’s Reader Mode. Without semantic HTML, Reader Mode would produce something much like the one-line string of text we started with. But, by using semantic HTML, we get a clean reading experience without any additional styling on our end:

The About page on my personal website viewed with Safari’s Reader Mode, comparing unsemantic HTML (left) with semantic HTML (right).

You can read more about this in Mandy Michael’s article on building websites for Safari Reader Mode and other reading apps.

When ARIA makes things better

Like semantic HTML, ARIA is a W3 standard that helps make interfaces more accessible to people who use screen readers and other assistive technologies to consume content.

Error messages are a good example. If a user leaves a required form field blank, the HTML for the error might look like this:

<label for="first-name">First name</label> <span>Enter your first name</span>  <input type="text" name="first-name" id="first-name">

A sighted user will be able to see the error above the field. But when a screen reader focuses on the input, the error won’t be announced because the error message isn’t linked to the input.

ARIA can be used to associate the error with the input like this:

<label for="first-name">First name</label> <span id="first-name-error">Enter your first name</span> <input type="text" name="first-name" id="first-name" aria-describedby="first-name-error">

Now the error message is announced when the input is in focus.

Using ARIA and JavaScript together

ARIA is most useful when JavaScript is involved. JavaScript is usually required to create more complex and dynamic interactions like hiding, showing and changing elements without a page refresh. Think toggle menus, accordions, tabs, auto-completes, sortable tables, loading content and saving, sending or getting data. Enhancing interfaces like this often breaks the experience for screen reader users.

Take a button that, when selected, reveals other content. In the original state, a sighted user will initially see a button and no content and, when the button is clicked, the content appears.

A visually-impaired user with a screen reader, however, usually relies on spoken cues as they navigate through an interface. But when a screen reader focuses on the button, there’s nothing to tell it if the content is currently in view and needs to be read.

The aria-expanded attribute can be added to the button, and JavaScript can toggle its value between true (content is showing) and false (content is hidden). This helps to meet Inclusive Design Principle #1, provide a comparable experience to screen reader users.

<button aria-expanded="false">Toggle content</button> <div hidden>Some content</div>

Try to avoid using ARIA to fix unsemantic HTML

ARIA attributes can be used to make unsemantic HTML more accessible to screen reader users. For example, a developer who is struggling to style a native checkbox across multiple browsers might decide to use a div and some JavaScript to emulate one.

We can add a role of checkbox to make the div identity itself as a checkbox to screen reader users:

<div role="checkbox"></div>

We must also use the aria-checked attribute to indicate whether or not the checkbox is checked like this:

<div role="checkbox" aria-checked="false"></div>

But, this still isn’t enough to make it behave like a checkbox because divs aren’t focusable by keyboards like <input type="checkbox"> is. We could make them focusable by adding tabindex="0":

<div role="checkbox" aria-checked="false" tabindex="0"></div>

But even then, a real checkbox, when submitted as part of a form, will send its value. Because this isn’t an actual a checkbox, it won’t submit its value without using JavaScript.

And if that weren’t enough already, users can check or un-check a real checkbox by pressing the Space key. And, the form the checkbox belongs to can be submitted by pressing Enter when the checkbox is in focus. But the div-version checkbox won’t do this without even more JavaScript.

Not only is this more work and more code, but the approach only actually works for people who use technology that understands these particular ARIA attributes. That’s a lot of effort, a lot of code and a lot of problems that we can avoid entirely if we just use semantic HTML:

<input type="checkbox">

There’s no denying that ARIA is useful in certain situations, but starting with semantic, accessible HTML where possible is infinitely simpler and more reliable. That’s why the first rule of ARIA is not to use it.

Conclusion

Inclusive design is about providing the best possible experience to the broadest range of users. Semantic HTML helps technologies and therefore users understand content on the web. Enhancements offered by some browsers and devices mean that users get an even better experience baked in.

And when semantic HTML alone is not enough on its own, ARIA can provide more context for users of assistive technologies, but use it with caution. It’s not a hard and fast cure for unsemantic markup and can become complicated, as we saw in that last example.

In short, do the hard work to make things inclusive. It’s a win for you and a win for the web.

The post Why, How, and When to Use Semantic HTML and ARIA appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

The Simplest Ways to Handle HTML Includes

It’s extremely surprising to me that HTML has never had any way to include other HTML files within it. Nor does there seem to be anything on the horizon that addresses it. I’m talking about straight up includes, like taking a chunk of HTML and plopping it right into another. For example the use case for much of the entire internet, an included header and footer for all pages:

... <body>    <include src="./header.html"></include>     Content     <include src="./footer.html"></include> </body> ...

That’s not real, by the way. I just wish it was.

People have been looking to other languages to solve this problem for them forever. It’s HTML preprocessing, in a sense. Long before we were preprocessing our CSS, we were using tools to manipulate our HTML. And we still are, because the idea of includes is useful on pretty much every website in the world.

Use PHP

Can you use PHP instead?

... <body>    <?php include "./header.html" ?>     Content     <?php include "./footer.html" ?> </body> ...

This will perform the include at the server level, making the request for it happen at the file system level on the server, so it should be far quicker than a client-side solution.

Use Gulp

What’s even faster than a server-side include? If the include is preprocessed before it’s even on the server. Gulp has a variety of processors that can do this. One is gulp-file-include.

That would look like this:

... <body>    @@include('./header.html')     Content     @@include('./footer.html') </body> ...

And you’d process it like:

var fileinclude = require('gulp-file-include'),   gulp = require('gulp');   gulp.task('fileinclude', function() {   gulp.src(['index.html'])     .pipe(fileinclude({       prefix: '@@',       basepath: '@file'     }))     .pipe(gulp.dest('./')); });

Looks like this particular plugin has fancy features where you can pass in variables to the includes, making it possible to make little data-driven components.

Use Grunt

This is what the grunt-bake plugin does. You’d configure Grunt to process your HTML:

grunt.initConfig({     bake: {         your_target: {             files: {                 "dist/index.html": "app/index.html",             }         }     } });

Then your HTML can use this special syntax for includes:

... <body>    <!--(bake header.html)-->     Content     <!--(bake footer.html)--> </body> ...

Use Handlebars

Handlebars has partials.

You register them:

Handlebars.registerPartial('myPartial', '{{name}}')

Then use them:

{{> myPartial }}

There is also fancy features of this that allow for evaluation and passing data. You’ll still need a processor to run it, probably something like gulp-handlebars.

Speaking of templating languages which make use of curly braces… Mustache has them, too.

Use Pug

Pug is an HTML preprocessor that has a whole new syntax for HTML that is a bit more terse. It’s got includes though.

... body    include ./header.html"     p Content     include ./footer.html"     ...

Then you run it with something like gulp-pug.

Use Nunjucks

I love me some Nunjucks! Nunjucks has includes. You’d do it like this:

... <body>    {% include "./header.html" %}     Content     {% include "./footer.html" %} </body> ...

If you put that in a file called index.njk, you could process it with a simple Node script into index.html like this:

const nunjucks = require("nunjucks"); const fs = require("fs");  fs.writeFile("index.html", nunjucks.render("index.njk"), function(err, data) {   if (err) console.log(err);   console.log("Compiled the Nunjucks, captain."); });

Or process it with something like gulp-nunjucks.

11ty has Nunjucks built-in, along with many of the other mentioned so far. Might be good for you if you’re actually building a little site.

Use Ajax

Say you had…

<body>      <header></header>      Content.      <footer></footer>  </body>

You could fetch the contents for the header and footer from respective files and dump the contents in.

fetch("./header.html")   .then(response => {     return response.text()   })   .then(data => {     document.querySelector("header").innerHTML = data;   });  fetch("./footer.html")   .then(response => {     return response.text()   })   .then(data => {     document.querySelector("footer").innerHTML = data;   });

Speaking of JavaScript… If you’re building your site using a JavaScript framework of just about any kind, building through components is kind of the main deal there and breaking parts you want to include in other files should be no problem. Some kind of import Header from "./header.js"; and <Header /> is the territory you’d be in in React land.

Use iframes

You could do this:

<body>      <iframe src="./header.html"></iframe>      Content.      <iframe src="./footer.html"></iframe>    </body>

But the content in those iframes does not share the same DOM, so it’s a bit weird, not to mention slow and awkward to style (since iframes don’t know the heights of their contents).

Scott Jehl documented a cool idea though: You can have the iframe inject the content of itself onto the parent page then remove itself.

<body>      <iframe src="header.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe>      Content.      <iframe src="footer.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe>    </body>

Use Jekyll

Jekyll is a Ruby-based static site generator with includes. You keep your includes in the /_includes/ folder, then:

<body>   {% include header.html %}      Content.    {% include footer.html %} </body>

Jekyll is a big one, so I’m calling it out here, but there are a ton of static site generators and I’d wager any of them can do includes.

Use Sergey

OK, I’ll call out one more SSG because it’s new and super focused. Sergey has a web components style format:

<body>   <sergey-import src="header" />    Content.    <sergey-import src="footer" /> </body>

You’d name the files header.html and footer.html and put them in /includes/ and then it’ll make a build with the includes processed when you run the npm script it has you do.

Use Apache SSI

Apache, a super duper common web server, can do includes. You do it like this:

<body> 		   <!--#include file="./header.html" -->      Content      <!--#include file="./footer.html" -->    </body>

But you need the right Apache configuration to allow stuff. I tried my best to get a working demo going but didn’t have much luck.

I tried using .htaccess within a folder on an Apache server and flipping on what I thought was the right stuff:

Options +Includes  AddType text/html .html AddOutputFilter INCLUDES .html

I’m sure there is some way to get it working though, and if you do, it’s kinda neat that it needs zero other dependencies.

Use CodeKit

Mac only, but CodeKit has a special language called Kit it processes where 90% of the point of it is HTML includes. It uses special HTML comments:

... <body>    <!-- @import "./header.html" -->     Content     <!-- @import "./footer.html" --> </body> ...

Use Dreamweaver

Lol jk. But it really is a thing. DWTs, baby.

Holy Crap

That’s a lot of ways, isn’t it?

Like I said at the top, it’s very surprising to me that HTML itself hasn’t addressed this directly. Not that I think it would be a great idea for performance to have <include> statements that trigger network requests all over our code, but it seems in-line with the platform. Using ES6 imports directly without bundling isn’t a great idea always either, but we have them. @importing CSS within CSS isn’t a great idea always, but we have it. If the platform had a native syntax, perhaps other tooling would key off that, much like JavaScript bundlers support the ES6 import format.

The post The Simplest Ways to Handle HTML Includes appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Could Grouping HTML Classes Make Them More Readable?

You can have multiple classes on an HTML element:

<div class="module p-2"></div>

Nothing incorrect or invalid there at all. It has two classes. In CSS, both of these will apply:

.module { } .p-2 { }
const div = document.querySelector("div"); console.log(div.classList.contains("module")); // true console.log(div.classList.contains("p-3"));    // false

But what about grouping them? All we have here is a space-separated string. Maybe that’s fine. But maybe we can make things more clear!

Years ago, Harry Roberts talked about grouping them. He wrapped groups of classes in square brackets:

<div class="[ foo  foo--bar ]  [ baz  baz--foo ]">

The example class names above are totally abstract just to demonstrate the grouping. Imagine they are like primary names and variations as one group, then utility classes as another group:

<header class="[ site-header site-header-large ]  [ mb-10 p-15 ]">

Those square brackets? Meaningless. Those are there to visually represent the groups to us developers. Technically, they are also classes, so if some sadist wrote .[ {}, it would do stuff in your CSS. But that’s so unlikely that, hopefully, the clarity from the groups outweighs it and is more helpful.

That example above groups the primary name and a variation in one group and some example utility classes in another group.

I’m not necessarily recommending that approach. They are simply groups of classes that you might have.

Here’s the same style of grouping, with different groups:

<button class="[ link-button ] [ font-base text-xs color-primary ] [ js-trigger ]" type="button" hidden>

That example has a single primary name, utility classes with different naming styles, and a third group for JavaScript specific selectors.

Harry wound up shunning this approach a few years ago, saying that the look of it was just too weird for the variety of people and teams he worked with. It caused enough confusion that the benefits of grouped classes weren’t worth it. He suggested line breaks instead:

<div class="media  media--large             testimonial  testimonial--main"> 

That seems similarly clear to me. The line breaks in HTML are totally fine. Plus, the browser will have no trouble with that and JSX is generally written with lots of line breaks in HTML anyway because of how much extra stuff is plopped onto elements in there, like event handlers and props.

Perhaps we combine the ideas of line breaks as separators and identified groups… with emojis!

See the Pen
Grouping Classes
by Chris Coyier (@chriscoyier)
on CodePen.

Weird, but fun. Emojis are totally valid there. Like the square brackets, they could also do things if someone wrote a class name for them, but that’s generally unlikely and something for a team to talk about.

Another thing I’ve seen used is data-* attributes for groups instead of classes, like…

<div    class="primary-name"   data-js="js-hook-1 js-hook-2"   data-utilities="padding-large" >

You can still select and style based on attributes in both CSS and JavaScript, so it’s functional, though slightly less convenient because of the awkward selectors like [data-js="js-hook-1"] and lack of convenient APIs like classList.

How about you? Do you have any other clever ideas for class name groups?

The post Could Grouping HTML Classes Make Them More Readable? appeared first on CSS-Tricks.

CSS-Tricks

, , , , , ,
[Top]

Crafting Reusable HTML Templates

In our last article, we discussed the Web Components specifications (custom elements, shadow DOM, and HTML templates) at a high-level. In this article, and the three to follow, we will put these technologies to the test and examine them in greater detail and see how we can use them in production today. To do this, we will be building a custom modal dialog from the ground up to see how the various technologies fit together.

Article Series:

  1. An Introduction to Web Components
  2. Crafting Reusable HTML Templates (This post)
  3. Creating a Custom Element from Scratch (Coming soon!)
  4. Encapsulating Style and Structure with Shadow DOM (Coming soon!)
  5. Advanced Tooling for Web Components (Coming soon!)

HTML templates

One of the least recognized, but most powerful features of the Web Components specification is the <template> element. In the first article of this series, we defined the template element as, “user-defined templates in HTML that aren’t rendered until called upon.” In other words, a template is HTML that the browser ignores until told to do otherwise.

These templates then can be passed around and reused in a lot of interesting ways. For the purposes of this article, we will look at creating a template for a dialog that will eventually be used in a custom element.

Defining our template

As simple as it might sound, a <template> is an HTML element, so the most basic form of a template with content would be:

<template>   <h1>Hello world</h1> </template>

Running this in a browser would result in an empty screen as the browser doesn’t render the template element’s contents. This becomes incredibly powerful because it allows us to define content (or a content structure) and save it for later — instead of writing HTML in JavaScript.

In order to use the template, we will need JavaScript

const template = document.querySelector('template'); const node = document.importNode(template.content, true); document.body.appendChild(node);

The real magic happens in the document.importNode method. This function will create a copy of the template’s content and prepare it to be inserted into another document (or document fragment). The first argument to the function grabs the template’s content and the second argument tells the browser to do a deep copy of the element’s DOM subtree (i.e. all of its children).

We could have used the template.content directly, but in so doing we would have removed the content from the element and appended to the document’s body later. Any DOM node can only be connected in one location, so subsequent uses of the template’s content would result in an empty document fragment (essentially a null value) because the content had previously been moved. Using document.importNode allows us to reuse instances of the same template content in multiple locations.

That node is then appended into the document.body and rendered for the user. This ultimately allows us to do interesting things, like providing our users (or consumers of our programs) templates for creating content, similar to the following demo, which we covered in the first article:

See the Pen
Template example
by Caleb Williams (@calebdwilliams)
on CodePen.

In this example, we have provided two templates to render the same content — authors and books they’ve written. As the form changes, we choose to render the template associated with that value. Using that same technique will allow us eventually create a custom element that will consume a template to be defined at a later time.

The versatility of template

One of the interesting things about templates is that they can contain any HTML. That includes script and style elements. A very simple example would be a template that appends a button that alerts us when it is clicked.

<button id="click-me">Log click event</button>

Let’s style it up:

button {   all: unset;   background: tomato;   border: 0;   border-radius: 4px;   color: white;   font-family: Helvetica;   font-size: 1.5rem;   padding: .5rem 1rem; }

…and call it with a really simple script:

const button = document.getElementById('click-me'); button.addEventListener('click', event => alert(event));

Of course, we can put all of this together using HTML’s <style> and <script> tags directly in the template rather than in separate files:

<template id="template">   <script>     const button = document.getElementById('click-me');     button.addEventListener('click', event => alert(event));   </script>   <style>     #click-me {       all: unset;       background: tomato;       border: 0;       border-radius: 4px;       color: white;       font-family: Helvetica;       font-size: 1.5rem;       padding: .5rem 1rem;     }   </style>   <button id="click-me">Log click event</button> </template>

Once this element is appended to the DOM, we will have a new button with ID #click-me, a global CSS selector targeted to the button’s ID, and a simple event listener that will alert the element’s click event.

For our script, we simply append the content using document.importNode and we have a mostly-contained template of HTML that can be moved around from page to page.

See the Pen
Template with script and styles demo
by Caleb Williams (@calebdwilliams)
on CodePen.

Creating the template for our dialog

Getting back to our task of making a dialog element, we want to define our template’s content and styles.

<template id="one-dialog">   <script>     document.getElementById('launch-dialog').addEventListener('click', () => {       const wrapper = document.querySelector('.wrapper');       const closeButton = document.querySelector('button.close');       const wasFocused = document.activeElement;       wrapper.classList.add('open');       closeButton.focus();       closeButton.addEventListener('click', () => {         wrapper.classList.remove('open');         wasFocused.focus();       });     });   </script>   <style>     .wrapper {       opacity: 0;       transition: visibility 0s, opacity 0.25s ease-in;     }     .wrapper:not(.open) {       visibility: hidden;     }     .wrapper.open {       align-items: center;       display: flex;       justify-content: center;       height: 100vh;       position: fixed;         top: 0;         left: 0;         right: 0;         bottom: 0;       opacity: 1;       visibility: visible;     }     .overlay {       background: rgba(0, 0, 0, 0.8);       height: 100%;       position: fixed;         top: 0;         right: 0;         bottom: 0;         left: 0;       width: 100%;     }     .dialog {       background: #ffffff;       max-width: 600px;       padding: 1rem;       position: fixed;     }     button {       all: unset;       cursor: pointer;       font-size: 1.25rem;       position: absolute;         top: 1rem;         right: 1rem;     }     button:focus {       border: 2px solid blue;     }   </style>   <div class="wrapper">   <div class="overlay"></div>     <div class="dialog" role="dialog" aria-labelledby="title" aria-describedby="content">       <button class="close" aria-label="Close">&#x2716;&#xfe0f;</button>       <h1 id="title">Hello world</h1>       <div id="content" class="content">         <p>This is content in the body of our modal</p>       </div>     </div>   </div> </template>

This code will serve as the foundation for our dialog. Breaking it down briefly, we have a global close button, a heading and some content. We have also added in a bit of behavior to visually toggle our dialog (although it isn’t yet accessible). In our next article, we will put custom elements to use and create one of our own that consumes this template in real-time.

See the Pen
Dialog with template with script
by Caleb Williams (@calebdwilliams)
on CodePen.

Article Series:

  1. An Introduction to Web Components
  2. Crafting Reusable HTML Templates (This post)
  3. Creating a Custom Element from Scratch (Coming soon!)
  4. Encapsulating Style and Structure with Shadow DOM (Coming soon!)
  5. Advanced Tooling for Web Components (Coming soon!)

The post Crafting Reusable HTML Templates appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Extracting Text from Content Using HTML Slot, HTML Template and Shadow DOM

Chapter names in books, quotes from a speech, keywords in an article, stats on a report — these are all types of content that could be helpful to isolate and turn into a high-level summary of what’s important.

For example, have you seen the way Business Insider provides an article’s key points before getting into the content?

That’s the sort of thing we’re going to do, but try to extract the high points directly from the article using HTML Slot, HTML Template and Shadow DOM.

These three titular specifications are typically used as part of Web Components — fully functioning custom element modules meant to be reused in webpages.

Now, what we aim to do, i.e. text extraction, doesn’t need custom elements, but it can make use of those three technologies.

There is a more rudimentary approach to do this. For example, we could extract text and show the extracted text on a page with some basic script without utilizing slot and template. So why use them if we can go with something more familiar?

The reason is that using these technologies permits us a preset markup code (also optionally, style or script) for our extracted text in HTML. We’ll see that as we proceed with this article.

Now, as a very watered-down definition of the technologies we’ll be using, I’d say:

  • A template is a set of markup that can be reused in a page.
  • A slot is a placeholder spot for a designated element from the page.
  • A shadow DOM is a DOM tree that doesn’t really exist on the page till we add it using script.

We’ll see them in a little more depth once we get into coding. For now, what we’re going to make is an article that follows with a list of key points from the text. And, you probably guessed it, those key points are extracted from the article text and compiled into the key points section.

See the Pen
Text Extraction with HTML Slot and HTML Template
by Preethi Sam (@rpsthecoder)
on CodePen.

The key points are displayed as a list with a design in between the points. So, let’s first create a template for that list and designate a place for the list to go.

<article><!-- Article content --></article>  <!-- Section where the extracted keypoints will be displayed --> <section id='keyPointsSection'>   <h2>Key Points:</h2>   <ul><!-- Extracted key points will go in here --></ul> </section>  <!-- Template for the key points list --> <template id='keyPointsTemplate'>   <li><slot name='keyPoints'></slot></li>   <li style="text-align: center;">&#x2919;&mdash;&#x291a;</li> </template>

What we’ve got is a semantic <section> with a <ul> where the list of key points will go. Then we have a <template> for the list items that has two <li> elements: one with a <slot> placeholder for the key points from the article and another with a centered design.

The layout is arbitrary. What’s important is placing a <slot> where the extracted key points will go. Whatever’s inside the <template> will not be rendered on the page until we add it to the page using script.

Further, the markup inside <template> can be styled using inline styles, or CSS enclosed by <style>:

<template id='keyPointsTemplate'>     <li><slot name='keyPoints'></slot></li>     <li style="text-align: center;">&#x2919;&mdash;&#x291a;</li>     <style>         li{/* Some style */}     </style> </template>

The fun part! Let’s pick the key points from the article. Notice the value of the name attribute for the <slot> inside the <template> (keyPoints) because we’ll need that.

<article>   <h1>Bears</h1>   <p>Bears are carnivoran mammals of the family Ursidae. <span><span slot='keyPoints'>They are classified as caniforms, or doglike carnivorans</span></span>. Although only eight species of bears <!-- more content --> and partially in the Southern Hemisphere. <span><span slot='keyPoints'>Bears are found on the continents of North America, South America, Europe, and Asia</span></span>.<!-- more content --></p>   <p>While the polar bear is mostly carnivorous, <!-- more content -->. Bears use shelters, such as caves and logs, as their dens; <span><span slot='keyPoints'>Most species occupy their dens during the winter for a long period of hibernation</span></span>, up to 100 days.</p>   <!-- More paragraphs -->  </article>

The key points are wrapped in a <span> carrying a slot attribute value (“keyPoints“) matching the name of the <slot> placeholder inside the <template>.

Notice, too, that I’ve added another outer <span> wrapping the key points.

The reason is that slot names are usually unique and are not repeated, because one <slot> matches one element using one slot name. If there’re more than one element with the same slot name, the <slot> placeholder will be replaced by all those elements consecutively, ending in the last element being the final content at the placeholder.

So, if we matched that one single <slot> inside the <template> against all of the <span> elements with the same slot attribute value (our key points) in a paragraph or the whole article, we’d end up with only the last key point present in the paragraph or the article in place of the <slot>.

That’s not what we need. We need to show all the key points. So, we’re wrapping the key points with an outer <span> to match each of those individual key points separately with the <slot>. This is much more obvious by looking at the script, so let’s do that.

const keyPointsTemplate = document.querySelector('#keyPointsTemplate').content; const keyPointsSection = document.querySelector('#keyPointsSection > ul'); /* Loop through elements with 'slot' attribute */ document.querySelectorAll('[slot]').forEach((slot)=>{   let span = slot.parentNode.cloneNode(true);   span.attachShadow({  mode: 'closed' }).appendChild(keyPointsTemplate.cloneNode(true));   keyPointsSection.appendChild(span); });

First, we loop through every <span> with a slot attribute and get a copy of its parent (the outer <span>). Note that we could also loop through the outer <span> directly if we’d like, by giving them a common class value.

The outer <span> copy is then attached with a shadow tree (span.attachShadow) made up of a clone of the template’s content (keyPointsTemplate.cloneNode(true)).

This “attachment” causes the <slot> inside the template’s list item in the shadow tree to absorb the inner <span> carrying its matching slot name, i.e. our key point.

The slotted key point is then added to the key points section at the end of the page (keyPointsSection.appendChild(span)).

This happens with all the key points in the course of the loop.

That’s really about it. We’ve snagged all of the key points in the article, made copies of them, then dropped the copies into the list template so that all of the key points are grouped together providing a nice little CliffsNotes-like summary of the article.

Here’s that demo once again:

See the Pen
Text Extraction with HTML Slot and HTML Template
by Preethi Sam (@rpsthecoder)
on CodePen.

What do you think of this technique? Is it something that would be useful in long-form content, like blog posts, news articles, or even Wikipedia entries? What other use cases can you think of?

The post Extracting Text from Content Using HTML Slot, HTML Template and Shadow DOM appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , ,
[Top]

HTML, CSS and our vanishing industry entry points

Rachel Andrew:

There is something remarkable about the fact that, with everything we have created in the past 20 years or so, I can still take a complete beginner and teach them to build a simple webpage with HTML and CSS, in a day. We don’t need to talk about tools or frameworks, learn how to make a pull request or drag vast amounts of code onto our computer via npm to make that start. We just need a text editor and a few hours. This is how we make things show up on a webpage.

That’s the real entry point here and yes, in 2019 they are going to have to move on quickly to the tools and techniques that will make them employable, if that is their aim. However those tools output HTML and CSS in the end. It is the bedrock of everything that we do, which makes the devaluing of those with real deep skills in those areas so much more baffling.

Speaking of entry points, I compiled a bunch of ideas for how and where to learn HTML and CSS for the present day.

Direct Link to ArticlePermalink

The post HTML, CSS and our vanishing industry entry points appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Where Do You Learn HTML & CSS in 2019?

The topic of how accessible it is for newbies and seasoned developers alike to learn CSS has been gaining steam as the complexity of the tools around it has become skewed more toward traditional programming. Rachel Andrew has much more to say about this in her post, HTML, CSS and our vanishing industry entry points. Robin also has thoughts on where and how to learn CSS in the modern age.

The question of how and where to learn CSS is a highly reasonable thing to ask. The answer depends on all sorts of things: how serious you are, your current foundation, what other resources are available to you, what you hope to do with what you learn, and how much time you have, among probably a zillion other things.

Let me dump a bunch of possible answers here and you can apply all those “well, that depends” caveats as you see fit.


You could read a book.

There are a ton of books out there that cover HTML and CSS (and often together). They probably all do a fine job. There’s no need to chronicle all the choices here. These two are my personal recommendations. You probably don’t even need both.

Jon Duckett’s is incredibly well-designed and approachable:

Jennifer Robin’s covers a bit more ground and is designed to be useful for either personal reading or classroom learning.

You could read through all the posts in our Beginner’s Guide.

We have a guide (a collection of articles, videos, and links) called Just Starting Out with CSS & HTML. I hope there is stuff in there that can help kickstart or augment your early learning because that’s the intent.

You could go through other free online guides.

Oliver James has a wonderful online course called Internetting is Hard (But it doesn’t have to be).

We designed HTML & CSS Is Hard to be the only introduction to HTML and CSS that you’ll ever need. If you put in the effort to read every section and write every code snippet, this tutorial has the potential to replace hundreds or even thousand of dollars worth of online courses and live training.

A screenshot of a webpage with a white background and large heading that says Basic Web Pages.

Prefer video? Jessica Hische and Russ Maschmeyer’s Don’t Fear the Internet is a super eight-part series that gets you going with HTML & CSS — it even delves into the all-important topic of typography.

A screenshot of the Don’t Fear the Internet webpage, which is sage green, has a large heading with the course title, two columns of text and a video player.

Khan Academy has an Intro to HTML/CSS: Making webpages course that’s packaged in a super cool format. It’s like video in that you get to hear the instructor talk you through the learning, but what you see is a real live text editor and real live output. Sometimes the teacher is controlling the code, and then sometimes it breaks for challenges in which you take over and edit the code yourself.

A screenshot of the Khan Academy course. It has a white background, blue navigation bar across the top, sidebar containing the course contents, and a video player in the main area.

Eric Tirado has an Intro to HTML course on Scrimba, which is also a neat platform in that Eric’s voice guides you through the course, but visually it’s a combination of slides with a real code editor and preview.

A screenshot of the Scrimba course. It resembles a code editor with a dark gray background, sidebar outlining web assets, and an editor with code in the main area.

You could find and take a paid online course.

I often join gyms because the accountability of paying for something gets me to do it. I know I can do situps, pushups, and go for a jog for free, but the gym membership makes a thing of it. Well, same could be said about paying for a course on HTML and CSS.

These are broad generalizations, but good places to start:

You could go to a code school or coding bootcamp

If you wanna put even more skin in the game, you could consider literally going to school. If you don’t have a college degree, that’s an option, although you’ll be looking at a broad education rather than a ticket to leveling up your web design and development skills alone. I’m a fan of that just for the general mind-broadening it involves.

But assuming you’re going to go to a coding-specific school…

There are probably dozens — if not hundreds — more, so this is more to inform you of the possibility of schooling. You don’t even have to go to a physical school since plenty of these offer online courses, too (but with the advantage of live instruction and cohorts). For example, LambdaSchool has the novelty of being free to start and paid later in the form of letting them take a portion of your salary after you get a job in the industry.

You could practice on CodePen.

Not every second of your learning should be strictly following some course laid out by a book, class, or teacher. It wouldn’t even be that way if you tried. You might as well embrace that. If something tickles your muse, go play! I hope CodePen is a rewarding place to do that, making it both easy and useful, while providing a place to connect with other folks in the field.

You could build a personal site and learn what you need to get it done.

That’s how absolutely countless developers have cut their teeth, including me. I wanted a personal website years ago, and I struggled through getting a self-hosted WordPress site online so I could have full control over everything and bend it to my will. Once you have an actual website online, and you know at least some people are seeing it, it gives you all the motivation in the world to keep going and evolve further.

The way you actually learn is going to be a combination of all this stuff.

People are obsessed with asking musicians if they’re self-taught. Like, if they are, their amazingness triples because it means their creative genius was delivered by a lightning bolt at birth. They don’t need anyone else to learn; they merely look at those guitar strings and know what to do.

And if they were taught be a teacher, then, well, that’s all out the door. If they are good at all, then it’s because the teacher delivered that to them.

Total nonsense.

People learn anything — music and web development included — inside a hurricane of influences. Let’s stick with music for a second. Learning to play comes in many forms. You learn by listening to music an awful lot. You can do fundamental practice, like finger exercises and going up and down scales. You can learn to transpose chords on a chalkboard. You can watch YouTube all day and night. You can sign up for online courses. You can go to local jams to watch and play along. You can join a band. You can take lessons from someone advertising on Craigslist. You can go to a local music school. You can read books about music.

You get the idea.

You can and probably will do all of that. With learning web design and development, getting anywhere will involve all sorts of ways. There’s no silver bullet. It takes bashing on it lots of different ways. There’s no requirement to sprinkle money on it, but you do need multiple angles, time, and motivation.

Go forth and build websites!

The post Where Do You Learn HTML & CSS in 2019? appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Designing for the web ought to mean making HTML and CSS

David Heinemeier Hansson has written an interesting post about the current state of web design and how designers ought to be able to still work on the code side of things:

We build using server-side rendering, Turbolinks, and Stimulus. All tools that are approachable and realistic for designers to adopt, since the major focus is just on HTML and CSS, with a few sprinkles of JavaScript for interactivity.

And it’s not like it’s some well kept secret! In fact, every single framework we’ve created at Basecamp that allows designers to work this way has been open sourced. The calamity of complexity that the current industry direction on JavaScript is unleashing upon designers is of human choice and design. It’s possible to make different choices and arrive at different designs.

I like this sentiment a whole lot — not every company needs to build their websites the same way. However, I don’t think that the approach that Basecamp has taken would scale to the size of a much larger organization. David continues:

Also not interested in retreating into the idea that you need a whole team of narrow specialists to make anything work. That “full-stack” is somehow a point of derision rather than self-sufficiency. That designers are so overburdened with conceptual demands on their creativity that they shouldn’t be bordered or encouraged to learn how to express those in the native materials of the web. Nope. No thanks!

Designing for the modern web in a way that pleases users with great, fast designs needn’t be this maze of impenetrable complexity. We’re making it that! It’s possible not to.

Again, I totally agree with David’s sentiment as I don’t think there’s anyone in the field who really wants to make the tools we use to build websites overly complicated; but in this instance, I tend to agree with what Nicolas recently had to say on this matter:

The interesting thing to note here is that the act of front-end development changes based on the size and scale of the organization. As with all arguments in front-end development, there is no “right” way! Our work has to adapt to the problems that we’re trying to solve. Is a large, complex React front-end useful for Basecamp? Maybe not. But for some organizations, like mine at Gusto, we have to specialize in certain areas because the product that we’re working on is so complicated.

I guess what I also might be rambling about is that I don’t think it’s engineers that are making front-end development complicated — perhaps it’s the expectations of our users.

Direct Link to ArticlePermalink

The post Designing for the web ought to mean making HTML and CSS appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]