⭐ If you would like to buy me a coffee, well thank you very much that is mega kind! : https://www.buymeacoffee.com/honeyvig Hire a web Developer and Designer to upgrade and boost your online presence with cutting edge Technologies
Showing posts with label semantics. Show all posts
Showing posts with label semantics. Show all posts

Friday, November 4, 2022

 

“Do I use a <section> or an <article> element?” I have had to ask myself this question an unhealthy amount of times whenever I have to group content in a container element.

A conversation I had on Twitter led me to research this question and ultimately to write on it. It was a conversation with Grace Snow where I shared an approach to writing HTML that I love to use. I love to write out my HTML structure (boxes) first and with no content to ensure I am not thinking of styling while I write my HTML. She then spotted that I might be making problematic use of the section and article elements in my sincere attempt to be semantic.

It turns out that to choose between section and article, we need our content. In fact, to determine if our content is narrowed down enough to those two, we need our content.

We can build a mental model that ensures we make the best decision every time by taking our content into consideration.

Let’s take a deep dive in!

Document Semantics #

HTML passes two related but distinct information to user devices. The first is the visual presentation information, which tells the device how to display the document by default.

The second is known as semantic information or, simply, semantics. It conveys “meanings” in the document, i.e., each element’s purpose and the relationship between them. In this sense, the spec would say that an element “represents” something. So, when you see “represents” in the spec, what follows is the semantic information embedded in the element.

The h1 element reveals the presence of these two sets of information. The visual presentation information for the h1 element, when encountered by browsers, is why it appears bold and with a larger font size than the rest of the document. The semantic information that the h1 represents is that it is the highest rank heading for its section.

Sighted users can gleam the semantic meaning from devices like the browser by observing the visuals. For headings, we can differentiate based on differences in font size and weight, or in the case of lists, the presence of bullet point markers or numbered markers. For users who do not rely on sight, the semantics are only accessible through options or devices that allow them to request that the semantic information be announced in other ways that may not be visual. These options and devices are generally called assistive technology.

HTML prescribes some elements that convey implicit meaning to browsers which browsers can extract to the accessibility API, making it available to assistive technologies that, in turn, interpret this meaning to users. This meaning gives users a wholesome sense of the webpage they are visiting, such as document structure and navigation assistance, or in this instant case, both document structure and navigation assistance.

However, it is not only elements that directly wrap text content that carries semantic information. Elements meant for grouping other elements also carry some meaning; in some cases, it may be meaning we want to communicate.

Does My Grouping Play A Semantic Role? #

This first step in our mental model is to question if grouping the content as we are about to do is necessary for the document structure to make sense. Broken down, I would ask myself in this kind of manner:

  • Is there any possibility the content of this block shares something in common that adds some sense to my document structure overall when it is read together?
  • If I were to describe my document structure to a person without showing it to them, would I mention that there is that particular grouped area for them to appreciate the document structure?

If the answer to these questions is “no,” then you may have a situation where a <div> could be appropriate, as Scott O’Hara notes. Reading Scott’s article could help you further examine the role your grouping plays and even formulate a better set of questions than mine. I do not intend to cover the <div> element in this article as Scott sufficiently covers it. I only intend to state that first, you must confirm that the grouping you are making is influenced by document structure. If it is, you can proceed to interrogate further to determine if it is an <article> or <section>.

To be clear, I do not mean that the grouping must only be influenced by document structure for you to start to consider <article> or <section>. It is enough that it is one of the possible reasons. For instance, it is possible for content in your grouping to share a distinct design or language and, at the same time, influence the document semantics.

More after jump! Continue reading below ↓

What Semantic Role Does My Grouping Play? #

We have now decided that the grouped content serves some function in describing the document. The next step is to determine which of the semantic meaning already carried by the article or the section element most accurately describes what function your grouped content is intended to serve in the document structure.

What The HTML Spec Say #

Let us take a look at the primary source of authority on HTML and start to form our understanding of the section and article elements and their inherent semantic meaning.

The HTML Living Standard says of the article element:

The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g., in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent content item.

As relates to the section element, the HTML Living Standard defines it this way:

The section element represents a generic section of a document or application. A section, in this context, is a thematic grouping of content, typically with a heading...

Examples of sections would be chapters, the various tabbed pages in a tabbed dialog box, or the numbered sections of a thesis. A website’s home page could be split into sections for an introduction, news items, and contact information.

To help narrow it further, the specs offer this clue on when to use the section element:

...A general rule is that the section element is appropriate only if the element’s contents would be listed explicitly in the document’s outline.

The linked specs give quite elaborate examples. However, it is safe to say that the choice is seemingly heavily subjective. Authors must actively decide if the particular group they have come up with is “complete” and “independently distributable,” in which case the choice would be an article or if it is a “thematic grouping of content,” in which case the choice would be a section. Let’s consider some tasks.

If you were to build a blog like Smashing Magazine, which of these elements would you use to wrap the portion of the landing page that contains the list of all blog posts teasers? In that wrapped portion, what element would wrap each blog post teaser? If you click on one of the blog post teasers and land on the expanded post page, which elements would wrap up the blog article?

If you were to build Twitter, would you wrap each tweet fed into the users’ timeline in an article because they are “self-contained” and “in principle, independently distributable”? Or would you wrap them in a section because they are “a generic section of an application”? Or perhaps, in this case, a div is semantically appropriate? Still taking the Twitter example, is your timeline container a section of the whole Twitter application, or is your timeline an article within your Twitter application? Or perhaps everything is just cake, and nothing is real.

We will return to apply our mental model to these two scenarios.

Understanding What The Specs Mean #

I reckon the reason for the seeming confusion is the mental model we have. At least that was the case for me.

The article element was not so-named after a written article. I wrongly assumed that it was, and perhaps you might have too. I literally just learnt that an article element existed and assumed that blog articles are so important on the web that the WHATWG decided to make an element dedicated to wrapping blog posts like this one. It felt intuitive to me, but I was wrong. I guess that is why web standards exist. Intuitions are not always uniform.

It turns out that in the Oxford English Dictionary and other dictionaries, one of the definitions for the word article is “a particular item or separate thing.” This is the sense in which the specs use the article element. It is right there in the spec’s definition of the article element, but as I said, that is not how I generally use the word “article.” In fact, dictionaries give the first definition of an “article” as a written work.

So, while the spec clearly says what sense it is used in, we still do not think of it that way.

To make it more adjust our thoughts, Bruce Lawson gives the best anecdote to understand the article element:

I gave my usual answer: think of <article> not just as a newspaper article or a blog post, but as an article of clothing — a discrete entity that can be reused in another context. So your trousers are an article, and you can wear them with a different outfit; your shirt is an article and can be worn with different trousers; your knee-length patent leather stiletto boots are an article (you wouldn’t wear just one of them, would you?).

It means what an article represents is content that can be taken out of the document and away from the immediate surrounding content, dropped somewhere else, say on another page, and still make total sense as it is grouped.

In the same way that you could use an article, such as a table lamp (an independent content group), to improve the aesthetics of your living room, and it would complement your sofa, tv console, curtains, and so on (immediate surrounding content). Yet, if you were to take your table lamp into your room, and it was simply placed at your bedside or your workstation, it would still be identifiable as a complete lamp.

The section element, on the other hand, represents “a thematic grouping of content,” meaning that a section is a part of a larger group without which it may not necessarily stand to make complete sense alone. It may stand alone, but in the theme of your content overall, it is less likely to be standalone. As the spec put it, “Examples of sections would be chapters, the various tabbed pages in a tabbed dialog box, or the numbered sections of a thesis. A website’s home page could be split into sections for an introduction, news items, and contact information.”

This is why a section would usually have a heading, providing a sort of call back to what part of the larger document the section relates to.

Let us go back to our lamp analogy. Our lamp itself makes sense as an item, but in reality, it has different parts that could technically be separated but really should not. I could take off the umbrella-shaped hood of my lamp, take the light bulb out, take off the base, and take off the upright stand. Together, they make up a lamp but, taken apart, not quite. If you are presented with the umbrella-shaped hood of a lamp, you are likely to think, “What is this from? Where is the rest of it?” If you are presented with the light bulb, you are likely to think, “Where does this go?”

Let’s Group Some Content #

A Blog Website Landing Page #

Firstly, let us take the example of a blog website. Our blog is the Smashing Magazine. Let us take a look at our landing page.

Here are the major areas on our landing page:

  • Header with Site navigation,
  • Main Area,
  • Footer with Topic Navigation.
<header>
    <nav>
        <!--     Website navigation goes here -->
    </nav>
</header>

<main>
    <!--     We would group the content that should go here   -->
</main>

<footer>
    <nav>
        <!-- Topic navigation goes here   -->
    </nav>
</footer>

These are groups that already have elements to represent them. So, we are not deciding between section and article for these.

In our Main Content, these are the identifiable groups:

  • Selected Articles,
  • Newsletter Subscription,
  • Components and Guides,
  • Latest Posts,
  • Smashing products and offerings,
  • Smashing conferences,
  • External articles from community members.

What element should wrap these grouped content? Let us apply our mental model. For each of these content groups, we follow this mental model.

  • Does grouping this content play a role that may help explain my document structure?
    • If it does not, then I can use a div.
    • If it does, play a role and proceed to consider if the role matches a section or an article.
  • What role does it play in my document structure?
    • Is the content of this group thematically related such that it helps to understand the outline of my document? If it is, then it is possibly a section.
    • Is the content of this group one that contains content that I can take out and redistribute to other pages while it does not totally tie to my document theme and outline? If it is, then it is possibly an article.

I encourage you to grab a piece of paper and make your grouping before proceeding to see mine. This way, we can compare how we think of each content group’s role on our page.

Now let’s build the skeletal grouping for our Smashing Magazine:

  • Selected Articles
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Newsletter Subscription
    Does it play a role in my document structure? Hmm. Well, it is not exactly necessarily within the central theme of my landing page, so I am doubtful about this one. I’d just say “no.” Verdict: div.
  • Components and Guides
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Latest Posts
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Smashing products and offerings
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • Smashing conferences
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.
  • External articles from community members
    Does it play a role in my document structure? Yes. What role? It is a part of the outline of content on my landing page. Verdict: section.

Here is what my Smashing Magazine landing page looks like now:

<header>
    <nav>
        <!--     Website navigation   -->
    </nav>
</header>

<main>
    <section>
        <!--     Selected articles    -->
    </section>
    
    <div>
        <!--     Newsletter subscription  -->
    </div>
    
    <section>
        <!--  Components and guides  -->
    </section>
    
    <section>
        <!--     Latest posts -->
    </section>
    
    <section>
        <!--     Smashing products and offerings -->
    </section>
    
    <section>
        <!--     Smashing conferences     -->
    </section>
    
    <section>
        <!--     External articles from community members     -->
    </section>
</main>

<footer>
    <nav>
        <!-- Topic navigation     -->
    </nav>
</footer>

We all might adjudge the role some items play differently. The “Newsletter Subscription” area, for instance. I would not outline “Newsletter Subscription” in my document outline, nor would I care to encounter it on a document outline for a page I visit. Yet again, if it were Substack, a platform for newsletters, I would definitely see how an area to subscribe to the newsletter would be a section. And while I have used a div here, it could as well have been an aside, but, of course, that is not why we are here today. The point is how we adjudge our content guides our decision.

I guess my point is your decision would be marginally better provided you interrogate and justify the role you want your content group to play in each case. You would have consciously put effort into making your web content understandable for users and other developers that would encounter your technical debt.

An Article Post On A Blog Website #

So, we have clicked on one blog article from the “Selected Articles” area and have expanded that article to its own page. This specific blog article you are reading, how is it grouped? Again, here is our base template:

<header>
    <nav>
        <!--     Website navigation   -->
    </nav>
</header>

<main>
    <!-- This article is wrapped here -->
</main>

<footer>
    <nav>
        <!-- Topic navigation     -->
    </nav>
</footer>

Do you wrap it in an article, do you wrap it in a section, or perhaps a div?

Would you break this article itself into smaller grouped bits? Maybe a bunch of sections or a couple of articles? Are there redistributable parts of this article or parts that you would expose to the document outline?

I would refrain from saying what I arrived at, but I would love to know what you would use. Take a note of your answers as we shall revisit this later on.

A Web Application: Twitter #

So, we have one more exercise, a web application, specifically Twitter.

  • Is the timeline container a section of the whole Twitter application, or is your timeline an article within your Twitter application, or is it a div?
  • Would you wrap each tweet fed into the users’ timeline in an article because they are “self-contained” and “in principle, independently distributable”? Or would you wrap them in a section because they are “a generic section of an application”? Or perhaps, in this case, a div is semantically appropriate?

If I apply the mental model, below is the way how I would do it:

My timeline is a part of my document outline, and yet, to an extent, it can be independently distributed. I could take my timeline out, and it would stand well alone. It seems like it could be viable for a section or an article. So, I question further, what do I really intend? Do I want it to function for redistribution or as a part of my application? If you use Twitter, you would agree that your timeline is more of an integral part of your homepage than it is redistributable. Here I would settle for a section.

For each tweet in my timeline, it would be an article. This is because each tweet is not thematically connected to the next tweet on my timeline such that I could say it can be a part of an outline. So, tweets are not sections. They are “self-contained” and “in principle, independently distributable.” You can even click a tweet to enter a new world with comments and quote tweets, and so much more.

Truly, and indeed, if you walk your way through the div-soup of the Twitter page, nested in, there is a nice pretty section just sitting there, as it should be. This section holds your timeline. And if you proceed deeper into the section, and further down a serving of divs, you can pick up an article holding each tweet. This is where I confess that I let out a tiny scream when I discovered that my thoughts matched what Twitter did.

This inspection of Twitter also shows how the presence of divs does not mean that semantic meaning has been sacrificed or lost.

A screenshot of Twitter timeline with the code below
Nestled in between all the divs, the Twitter timeline is really wrapped in a section element. (Large preview)
A screenshot with one highlited tweet and the code below
Nested further in the section that holds your timeline, each tweet is really wrapped in an article element. (Large preview)

Nesting sections And articles And Other Groups #

You can nest these elements within each other. You probably already figured that by now after looking at the Twitter example.

divs, articles, and sections can go into each other without necessarily breaking accessibility. If you apply the mental model, you can question each nesting you are about to make and group accordingly.

Take the example of this blog post. I did not answer how I would wrap it when I asked a few paragraphs ago. Here is what I could do:

I could wrap this whole article you are reading in an article. Then I would further nest the large chunks of this article into sections because I want each portion to be really divided up for easy understanding. So far, this is what this blog post you are reading could look like:

<header>
    <nav>
        <!--     Website navigation   -->
    </nav>
</header>

<main>
    <article>
        <h1>Article versus section: Making your choice count in the larger context of accessibility</h1>

        <section>
            <h2>Quick summary</h2>
            <!--  paragraphs go here -->
        </section>

        <section>
            <h2>Introduction</h2>
            <!--  paragraphs go here -->
        </section>

        <section>
            <h2>Document Semantics</h2>
            <!--  paragraphs go here -->
        </section>

        <section>
            <h2>Does my grouping play a semantic role?</h2>
            <!--  paragraphs go here -->
        </section>

        <section>
            <h2>What semantic role does my grouping play?</h2>
            <!--  paragraphs go here -->
            <h3>What the HTML specs say</h3>
            <!--  paragraphs go here -->
            <h3>Understanding what the specs mean</h3>
            <!--  paragraphs go here -->
        </section>

        <section>
            <h2>Let's group some content</h2>
            <!--  paragraphs go here -->
            <h3>A bog website landing page</h3>
            <!--  paragraphs go here -->
            <h3>An article post on a blog website</h3>
            <!--  paragraphs go here -->
            <h3>A web application: Twitter</h3>
            <!--  paragraphs go here -->
        </section>

        <section>
            <h2>Nesting sections AND articles</h2>
            <!--  paragraphs go here -->
        </section>

        <!--     Rest of article continues here   -->
    </article>
</main>

<footer>
    <nav>
        <!-- Topic navigation     -->
    </nav>
</footer>

Notice how I give my sections appropriate headings since I have decided to use section? Recollect that the spec says a section should typically have a heading. Also, recall that you make sections if you think they should feature in your document outline. As such, a heading would provide the text to feature in the outline.

If there is a need for it, your sections and articles could have other grouped content in them. For instance, you could have a header to hold your section’s heading or a footer to hold information about a section, such as links to related documents, etc. If you will, the “Further reading” area of this post could be wrapped in a footer.

As for main, you are restricted to using it only when it is hierarchically correct, i.e., if it is a direct child of html, body, div or form. In any case, you are restricted from using more than one main element without the hidden attribute.

How section And article Are Exposed #

So far, we have looked at how to group content but only from the viewpoint of developers. How is how our grouping exposed to readers?

section And article In Browsers #

Browsers generate an Accessibility Tree which you can inspect with the developer tools. You can open the developer tools, activate the Inspector, and navigate to the Accessibility tab.

Firefox, Chrome, and Microsoft Edge similarly present the respective roles of the article and section elements on the Accessibility Tree. The article element has the role of “article” on the accessibility tree. The section element has the role of the “section.” This means that the browsers accurately recognise what our grouping of content represents.

However, while the browsers correctly understand what our grouping of content represents, users do not get any particular hints about this. So articles and sections are not perceivable or otherwise navigable by the keyboard on the browser. If the page is styled, then visual cues provided by your design could hint at the grouping of content. But there is no default underlining or outline on focus as you’d get with links.

Note: I should briefly note that we (Manuel and I) got a little tripped up on browsers exposing the section element as having a role of “section” because, in aria accessibility definitions, the aria role of section is not the same as the HTML section element. The aria role of “section” is an abstract role and should not be used by authors/developers. So please do not set a role="section" attribute in your HTML. Anyway, it would seem that the browsers may be using their own internal accessibility terms. This conclusion is especially supported by the fact that in Firefox, for instance, images have the role of “graphic,” but aria does not have any role known as a graphic. Perhaps someone more knowledgeable would definitely be able to explain what is happening. However, the expected behavior is correct.

section And article In Screen Readers #

Screen readers read the accessibility API and then handle the elements correctly. There are a couple of screen readers in use. Thankfully, AccessibilityOZ documents how sectioning elements are handled by screen readers, which still seems accurate at the time of writing this article.

article In Screen Readers #

Where grouped content is wrapped in an article, different screen readers handle it differently.

In terms of being perceivable, AccessibilityOz documents that JAWS, Talkback on Android, and VoiceOver announce the entry into and exit from an “article” if it encounters it. NVDA and Narrator do not announce an article.

I specifically was able to test on NVDA and Narrator as I use a Windows laptop, and the article was not announced. Manuel was also kind enough to help test on VoiceOver and Talkback, and the article is announced if it is encountered as you traverse the page.

I snooped around and found that NVDA allows you to turn on the option to announce the presence of an article. It is just turned off by default. I am not certain how frequently non-developer users would customise that option.

Regarding navigation, users on Narrator cannot jump to an article as it is not perceivable. Users on NVDA that have activated the option to have articles announced cannot jump to an article. There is no shortcut for that. It is only announced if encountered while traversing the page. JAWS has a dedicated shortcut for moving through articles on a page by pressing the O key. VoiceOver users can jump across articles using the shortcut (VO + Shift + left/right arrow).

While some users would get the presence of an article announced, others would not. So, the experience is not uniform. I have also wondered if there is any practical use for announcing an article. I am not sure when I heard the announcement that I am “in the article” on a webpage, I would interpret it as “in an independent, redistributable and self-contained content.” It sounds more like I am in a “written body of work.” I do not have the capacity to test this anyway, so it really is just my own thought.

The question, then, is what direct benefits do users of my page get from grouping content semantically within an article? What does it translate to for my users after I have correctly wrapped my group in an article? If there is none, why should I not just use the div instead? Bruce Lawson’s article, “Why You Should Choose HTML5 article Over section” adequately covers that. Reader for Apple’s WatchOS looks out for article elements to appropriately determine what to display on the iWatch. While this is not a use case particularly prescribed by the web standards, perhaps we might see a trend of device makers taking this approach. So if you are designing your page with WatchOS in mind, this would be an additional reason to use article, at least over a div.

But I still wondered if there are any additional reasons directly for the benefit of users. Why would I want to jump through all articles on a webpage? Why jump through independent items on a webpage without context in the manner that JAWS and Voiceover allow? So I did some digging, and here is what I found about the prescribed functionality for article role by assistive technology:

An article may be nested to form a discussion where assistive technologies could pay attention to article nesting to assist the user in following the discussion…

…When nesting articles, the child articles represent content that is related to the content of the parent article. For instance, a weblog entry on a site that accepts user-submitted comments could represent the comments as articles nested within the article for the weblog entry.

…When the user navigates to an element assigned the role of article, assistive technologies that typically intercept standard keyboard events should switch to document browsing mode, as opposed to passing keyboard events through to the web application. Assistive technologies may provide a feature allowing the user to navigate the hierarchy of any nested article elements.

I was sadly unable to reproduce this behavior directly. Jumping through articles on VoiceOver with the shortcut merely announces “article, article, article.” It does not seem they implemented the feature to allow users to navigate the hierarchy of nested articles, or I could not get it to work.

However, it doesn’t hurt to build with nested articles if it is the appropriate thing to do. If screen reader makers implement this recommended behavior, your page is already prime and ready for it. Consider it some sort of future-proofing.

section In Screen Readers #

Where grouped content is wrapped in a section, screen readers treat it more consistently.

In terms of being perceivable, all screen readers do not announce entry into or exit from a section. This also means in terms of navigation, there is no way to navigate from one section to another.

Extending section Into Navigable region #

The imperceivable nature of section is only a default behavior. As such, we can customize our section and expose it to screen readers users using WAI-ARIA (Web Accessibility Initiative — Accessible Rich Internet Applications).

Here is a summary of what WAI-ARIA is and what it does culled from the MDN Docs:

WAI-ARIA (Web Accessibility Initiative — Accessible Rich Internet Applications) is a specification written by the W3C, defining a set of additional HTML attributes that can be applied to elements to provide additional semantics and improve accessibility wherever it is lacking...

Implying that while you may already be writing semantic HTML, you can customise and provide even greater semantic meaning!

In this specific case, we are more concerned with the category of landmark roles provided by ARIA, which are roles that provide navigational context for the application or the document. To understand better, the definition of landmark provided by WAI-ARIA reads:

A type of region on a page to which the user may want quick access. Content in such a region is different from that of other regions on the page and relevant to a specific user purpose, such as navigating, searching, perusing the primary content, etc.

With landmark roles, we can provide non-sighted users with a key experience that sighted (and fully non-disabled) users of our page would have: the ability to first scan or skim through a page and then decide where to focus their attention.

For the specific case of section and the intended semantic, we intend to pass to users; namely that the content in it is thematically related or has a central idea, the particular role of region is our concern.

As a landmark role, a region is intended by the w3c to be:

A perceivable section containing content that is relevant to a specific, author-specified purpose and sufficiently important that users will likely want to be able to navigate to the section easily and to have it listed in a summary of the page.

We can make specific sections of our page into regions calculated to make it easier for screen reader users to jump to that part of the page. This could be especially useful on pages populated with a lot of content other than the primary reason users might be on the page.

To create a region, there are two things to do. Firstly, make your element a region by including the attribute-value pairing role="region" in your element’s opening tag. Secondly, you give your region an accessible name. However, where your grouping element is a section, you only have to do the second. This is because if your section element has an accessible name, then it has an implicit role as a region. As such, it is not recommended to set a role that matches the implied semantics for the element. So let’s set an accessible name.

An accessible name is simply the name of a user interface element, especially as exposed by the accessibility API to assistive technologies.

The specification for the region role requires that:

Authors must give each element with a region role a brief label that describes the purpose of the content in the region.

An accessible name is required for the region role. If there is no accessible name, then browsers and assistive technologies must not expose a region to users because users will be jumping to a region with no description or context, almost like what happens with an article.

There are multiple ways to provide a name depending on the element involved. However, we shall narrow it down to what is relevant for a section being used as a region.

The first and most preferred way to name your region is to name via the aria-labelledby attribute. To do this, you reference a visible element on your page and direct the assistive technology to use the text content of that visible element as the name of the region. This visible element should preferably be a heading.

To do this, give the element whose content you are referencing an id attribute with a value of choice. Then give your section element an aria-labelledby attribute. Then set the value of the aria-labelledby attribute to the exact value as the id of the element whose content you are referencing. Take a look at this in action:

<section aria-labelledby="posts">
<!-- This area contains teasers for all blog posts on the website  -->
    <h2 id="posts">All blog posts</h2>
    <article>
        <header>
            <p>Cosima Mielke wrote</p>
                <h2>Expand Your Horizons (June 2022 Desktop Wallpapers Edition)</h2>
        </header>
        <div>
            <p>What could be a better way to welcome June than with some colorful inspiration? Well, we might have something for you: wallpapers created with love by artists and designers from across the globe.</p>
            <p><a>Continue reading ↬</a></p>
        </div>
</article>
    <!-- More blog post teasers here  -->
</section>

Take note that your aria-labelledby does not carry an #, unlike what obtains when linking to an id with an href. It is aria-labelledby="posts" not aria-labelledby="#posts". Remember also that we do not set a role=region for a section element. It is already implied once you give an accessible name.

Using this code example, screen readers would have the region announced to them under the landmark navigation as such “all blog posts, region” or something similar.

The second way to give an accessible name is to use the aria-label attribute if there is no visible element with content that could accurately label your region. In this case, the value you give to the aria-label itself would be read as the name of the region.

<section aria-label="all blog posts">
<!-- This area contains teasers for all blog posts on the website  -->
    <article>
        <header>
            <p>Cosima Mielke wrote</p>
                <h2>Expand Your Horizons (June 2022 Desktop Wallpapers Edition)</h2>
        </header>
        <div>
            <p>What could be a better way to welcome June than with some colorful inspiration? Well, we might have something for you: wallpapers created with love by artists and designers from across the globe.</p>
            <p><a>Continue reading ↬</a></p>
        </div>
</article>
    <!-- More blog post teasers here  -->
</section>

In this code example, there is no heading for the region that we can reference. So this region would be announced as “all blog posts, region” by directly reading the value we supplied for the aria-label attribute. You will notice that the accessible name is written in lowercase. This is because screenreaders could mistake words written in all caps to be acronyms and then spell them out alphabet by alphabet instead of reading them as a single word. The sentence case is fine, but please avoid all caps. If you want to make emphasis, use the em tag.

To recap, aria-labelledby is a referential naming mechanism and is recommended because users, relying on assistive technology, get labels from existing content on the page, ensuring that the experience they are served is significantly the same as what other users get. On the other hand, aria-label is a direct naming mechanism. Using it means that users relying on assistive technology get labels from the author’s interpretation of what the element does. This is why it is recommended to use it only where no visible content on the page itself is appropriate. Active decision-making is required.

Finally, not every section has to be a region. Seriously, on learning this new power to create a region, it is tempting to look at all elements on your page and go, “you get a region, you get a region, everyone gets a region.” Please do not do this. Why? Scott O’Hara explains, “Overpopulating a web page with landmarks will reduce their ability to help users find the most important parts of web pages.” Remember, regions should be attached to areas users want to reach easily. Now let us look at real-life examples of these in play.

Smashing Magazine uses the aria-label technique for the “Quick Summary” part of this blog post. If you open your developer tool and Inspect the “Quick Summary”, this is what the markup looks like:

<section aria-label="quick summary" class="article__summary">
    <span class="summary__heading">Quick summary ↬</span>
    <!--     Rest of summary continues here -->
</section>

Now screen reader users can jump to the “Quick Summary” region using shortcuts and get an overview of what the article is about without having to first interact with the whole article.

Let’s take another look at Twitter, a web application for using the aria-labelledby technique. Look at the developer tools, particularly the section holding your timeline. You will see an aria-labelledby="accessible-list-9" attribute in the section’s opening tag. It points to the h1 element just below it, which has an id="accessible-list-9" and text content that says “Your Home Timeline.” Now users of screen readers can use the landmark navigation menu in their screen reader and navigate to “Your Home Timeline region.”

A screenshot from Twitter with the code below showing aria-labelledby technique
(Large preview)

Two questions may have crossed your mind. First, why is there a role="region" on the section element when the specs say that a section with an accessible name does not need to be assigned a region role expressly? Second, why can’t I see the h1 element with “Your Home Timeline” in my browser if the aria-labelledby is supposed to reference a visible element?

For the first question about declaring role="region" on the section element, the specs say it is not recommended to expressly set a role that is the same as the implied semantics. However, they do recognise that there might be browsers and devices that do correctly expose the implied semantics. As such, for an application like Twitter used by hundreds of millions of persons, it is reasonable to set the region role expressly to cover the bases as they cannot predict all the varying types of browsers and devices in use.

The second question is why the referenced element for the aria-labelledby is not on the page. This is a pattern/technique that people building pages with accessibility in mind employ every now and then. No rule has been broken here. An h1 element is a visible element. What has been done here is to use CSS to remove the visual rendering of elements that are not considered necessary for sighted users but crucial for non-sighted users. For sighted users, the timeline is identifiable without a heading. However, the heading is also a reference point to name the region for screen reader users, so we need it in our HTML. By using a neat CSS technique, one can take content off the screen but leave it visible to screen readers.

Here’s another interesting thing I noticed when you make your section into a region. Remember our Accessibility tab using the Inspector in our developer tools? Well, the section’s role on the accessibility tree does not directly change to region in Firefox. What happens is that a region branch is created as a child of the section. In Firefox, the tree becomes sectionregion.

A screenshot of the Accessibility Tree shows that Firefox creates a new region branch as a child of the section when a section is assigned a role of region
A screenshot of the Accessibility Tree shows that Firefox creates a new region branch as a child of the section when a section is assigned a role of region. (Large preview)

However, in Chrome and Microsoft Edge, the section itself changes to a region role.

A screenshot of the Accessibility Tree in Chrome shows that when a section made into a region, the section is removed from the accessibility tree and replaced with a region
A screenshot of the Accessibility Tree in Chrome shows that when a section made into a region, the section is removed from the accessibility tree and replaced with a region. (Large preview)
A screenshot of the Accessibility Tree in Microsoft Edge shows that when a section is made into a region, the section is removed from the accessibility tree and replaced with a region
A screenshot of the Accessibility Tree in Microsoft Edge shows that when a section is made into a region, the section is removed from the accessibility tree and replaced with a region. (Large preview)

Should I Bother? #

Yes, you absolutely should.

The truth is even if you are not designing for display on an iWatch or other smart gadgets, and even if you have no reason to create regions on your page, you should still use the correct element.

Firstly, this article by Mandy Michael reveals that browsers pay attention to your HTML structure to generate a Reader mode which strips the page of unnecessary information, images and background. Safari, Chrome, Firefox, Edge, and other reading apps specifically look out for HTML sectioning content to prioritise display for reading. The sectioning content includes article and section amongst others. Without carefully wrapping your content into appropriate elements, you risk it being ignored when a minimalist view is created.

Secondly, It helps you actively think about how you present your content. Content design is a crucial part of our page that we should be conscious about. It is the basis of our page. The words we use, the headings we use, and the length of our paragraphs all affect our users. How we group our content is also essential.

As designers and developers, we may feel that our main reason for grouping content is simply to style them. But if we start to care about the content, we may realise better ways to create our page. Grouping content does a lot more than preparing our content for visual styling. If we take care to write our HTML consciously, we can, to an extent, be certain that we have made our corner of the web a better place for all.

Writing this article and thinking about how I would have sectioned this page helped me create a coherent structure for my work. It helped me identify places where the content was out of place in terms of the surrounding context. With posts as long as this, thinking of how we group content becomes crucial.

Even where content is extremely short, thinking about how we group content helps create better content. In a recent knowledge-sharing webinar on Content Design and Accessibility, Amanda Diamond shared this slide showing how a very short content block can be broken up to make it easier for people to read. These two screenshots contain the exact same content, yet one is easier to digest. This would be a perfect place to use a section instead of just a div. Notice how each section carries an appropriate heading explaining each content block.

Two screenshots of a page giving the exact same information about ‘Being charged with a crime’. The first is split up into sections with headings making it easier to scan and scroll. The second contains the same information in just one paragraph
Two screenshots of a page giving the exact same information about ‘Being charged with a crime’. The first is split up into sections with headings making it easier to scan and scroll. The second contains the same information in just one paragraph. (Large preview)

Conclusion #

We have looked at a mental model that forces us to interact with our content to determine how best to group it. We question:

  • If the grouping plays a role in our document structure?
  • If it does, what role does it play?

From our answers, we can choose the appropriate grouping element for our content.

We have also looked at what happens when the browser builds an accessibility tree for our section or article elements and how to extend our section into a region to allow easy navigation.

Finally, I think we communicate with two sets of consumers of our content — the end-users who read our pages from an URL and others who have to interact with our markup. We may tend to think largely in terms of end-users when it comes to HTML. However, I believe writing HTML that is easy to understand and self-explanatory for whoever will work on it is sufficient reason to use the correct semantic element.

Monday, September 23, 2013

Semantic CSS With Intelligent Selectors

“Form ever follows function. This is the law.” So said the architect and “father of skyscrapers” Louis Sullivan. For architects not wishing to crush hundreds of innocent people under the weight of a colossal building, this rule of thumb is pretty good. In design, you should always lead with function, and allow form to emerge as a result. If you were to lead with form, making your skyscraper look pretty would be easier, but at the cost of producing something pretty dangerous.
So much for architects. What about front-end architects — or “not real architects,” as we are sometimes known? Do we abide by this law or do we flout it?
With the advent of object-oriented CSS (OOCSS), it has become increasingly fashionable to “decouple presentation semantics from document semantics.” By leveraging the undesignated meanings of classes, it is possible to manage one’s document and the appearance of one’s document as curiously separate concerns.
Overthinking how a functional thing should look.
In this article, we will explore an alternative approach to styling Web documents, one that marries document semantics to visual design wherever possible. With the use of “intelligent” selectors, we’ll cover how to query the extant, functional nature of semantic HTML in such a way as to reward well-formed markup. If you code it right, you’ll get the design you were hoping for.
If you are like me and have trouble doing or thinking about more than one thing at a time, I hope that employing some of these ideas will make your workflow simpler and more transferable between projects. In addition, the final section will cover a more reactive strategy: We’ll make a CSS bookmarklet that contains intelligent attribute selectors to test for bad HTML and report errors using pseudo-content.

Intelligent Selectors

With the invention of style sheets came the possibility of physically separating document code from the code used to make the document presentable. This didn’t help us to write better, more standards-aware HTML any more than the advent of the remote control resulted in better television programming. It just made things more convenient. By being able to style multiple elements with a single selector (p for paragraphs, for instance), consistency and maintenance became significantly less daunting prospects.
television remote reading DRIVEL
The p selector is an example of an intelligent selector in its simplest form. The p selector is intelligent because it has innate knowledge of semantic classification. Without intervention by the author, it already knows how to identify paragraphs and when to style them as such — simple yet effective, especially when you think of all of the automatically generated paragraphs produced by WYSIWYG editors.
So, if that’s an intelligent selector, what’s an unintelligent one? Any selector that requires the author to intervene and alter the document simply to elicit a stylistic nuance is an unintelligent selector. The class is a classic unintelligent selector because it is not naturally occurring as part of semantic convention. You can name and organize classes sensibly, but only with deliberation; they aren’t smart enough to take care of themselves, and browsers aren’t smart enough to take care of them for you.
Unintelligent selectors are time-intensive because they require styling hooks to be duplicated case by case. If we didn’t have p tags, we’d have to use unintelligent selectors to manufacture paragraphs, perhaps using .paragraph in each case. One of the downsides of this is that the CSS isn’t portable — that is, you can’t apply it to an HTML document without first going through the document and adding the classes everywhere they are required.
class selector called paragraph
Unintelligent selectors at times seem necessary, or at least easier, and few of us are willing to rely entirely on intelligent selectors. However, some unintelligent selectors can become “plain stupid” selectors by creating a mismatch between document structure and presentation. I’ll be talking about the alarming frequency with which the unintelligent .button selector quickly becomes plain stupid.

Vive la Différence

Intelligent selectors are not confined just to the basic elements offered to us in HTML’s specification. To build complex intelligent selectors, you can defer to combinations of context and functional attribution to differentiate basic elements. Some elements, such as <a>, have a multitude of functional differences to consider and exploit. Other elements, such as <p>, rarely differ in explicit function but assume slightly different roles according to context.
header p {
   /* styles for prologic paragraphs */
}

footer p {
   /* styles for epilogic paragraphs */
}
Simple descendent selectors like these are extremely powerful because they enable us to visually disclose different types of the same element without having to physically alter the underlying document. This is the whole reason why style sheets were invented: to facilitate physical separation without breaking the conceptual reciprocity that should exist between document and design.
a semantic heirarchy of needs: what it is, how it functions, where it is
Inevitably, some adherents of OOCSS treat the descendent selector with some suspicion, with the more zealous insisting on markup such as the example below, found in BEM’s “Definitions” documentation.
<ul class="menu">
  <li class="menu__item"></li>
  <li class="menu__item"></li>
</ul>
I won’t cover contextual selectors any further because, unless you have a predilection for the kind of overprescription outlined above, I’m sure you already use them every day. Instead, we’ll concentrate on differentiation by function, as described in attributes and by attribute selectors.

Hyperlink Attributes

Even those who advocate for conceptual separation between CSS and HTML are happy to concede that some attributes — most attributes besides classes and custom data attributes, in fact — have an important bearing on the internal functioning of the document. Without href, your link won’t link to anything. Without type, the browser won’t know what sort of input to render. Without title, your abbr could be referring to either the British National Party or Banco Nacional de Panama.
Some of these attributes may improve the semantic detail of your document, while others are needed to ensure the correct rendering and functioning of their subject elements. If they’re not there, they should be, and if they are there, why not make use of them? You can’t write CSS without writing HTML.

The rel Attribute

The rel attribute emerged as a standard for link relations, a method of describing some specific purpose of a link. Not all links, you see, are functionally alike. Thanks to WordPress’ championing, rel="prev" and rel="next" are two of the most widely adopted values, helping to describe the relationship between individual pages of paginated blog content. Semantically, an a tag with a rel attribute is still an a tag, but we are able to be more specific. Unlike with classes, this specificity is semantically consequential.
The rel attribute should be used where appropriate because it is vindicated by HTML’s functional specification and can therefore be adopted by various user agents to enhance the experience of users and the accuracy of search engines. How, then, do you go about styling such links? With simple attribute selectors, of course:
[rel="prev"] {
  /* styling for "previous links" */
}

[rel="next"] {
  /* styling for "next" links */
}
Attribute selectors like these are supported by all but the most archaic, clockwork browsers, so that’s no reason not to use them anywhere the attributes exist. In terms of specificity, they have the same weight as classes. No woe there either, then. However, I recall it being suggested that we should decouple document and presentation semantics. I don’t want to lose the rel attributes (Google has implemented them, for one thing), so I’d better put an attribute that means nothing on there as well and style the element via that.
  <a href="/previous-article-snippet/" rel="prev" class="prev">previous page</a>
The first thing to note here is that the only part of the element above that does not contribute to the document’s semantics is the class. The class, in other words, is the only thing in the document that has nothing functionally to do with it. In practice, this means that the class is the only thing that breaks with the very law of separation that it was employed to honor: It has a physical presence in the document without contributing to the document’s structure.
OK, so much for abstraction, but what about maintenance? Accepting that we’ve used the class as our styling hook, let’s now examine what happens when some editing or refactoring has led us to remove some attributes. Suppose we’ve used some pseudo-content to place a left-pointing arrow before the [rel="prev"] link’s text:
.prev:before {
  content: '\2190'; /* encoding for a left-pointing arrow ("←") */
}
previous link with arrow
Removing the class will remove the pseudo-content, which in turn will remove the arrow (obviously). But without the arrow, nothing remains to elucidate the link’s extant prev relationship. By the same token, removing the rel attribute will leave the arrow intact: The class will continue to manage presentation, all the time disguising the nonexistence of a stated relationship in the document. Only by applying the style directly, via the semantic attribute that elicits it, can you keep your code and yourself honest and accurate. Only if it’s really there, as a function of the document, should you see it.

Attribute Substrings

I can imagine what you’re thinking: “That’s cute, but how many instances are there really for semantic styling hooks like these on hyperlinks? I’m going to have to rely on classes at some point.” I dispute that. Consider this incomplete list of functionally disimilar hyperlinks, all using the a element as their base:
  • links to external resources,
  • links to secure pages,
  • links to author pages,
  • links to help pages,
  • links to previous pages (see example above),
  • links to next pages (see example above again),
  • links to PDF resources,
  • links to documents,
  • links to ZIP folders,
  • links to executables,
  • links to internal page fragments,
  • links that are really buttons (more on these later),
  • links that are really buttons and are toggle-able,
  • links that open mail clients,
  • links that cue up telephone numbers on smartphones,
  • links to the source view of pages,
  • links that open new tabs and windows,
  • links to JavaScript and JSON files,
  • links to RSS feeds and XML files.
That’s a lot of functional diversity, all of which is understood by user agents of all sorts. Now consider that in order for all of these specific link types to function differently, they must have mutually differential attribution. That is, in order to function differently, they must be written differently; and if they’re written differently, they can be styled differently.
In preparing this article, I created a proof of concept, named Auticons. Auticons is an icon font and CSS set that styles links automatically. All of the selectors in the CSS file are attribute selectors that invoke styles on well-formed hyperlinks, without the intervention of classes.
art_auticons
In many cases, Auticons queries a subset of the href value in order to determine the function of the hyperlink. Styling elements according to the way their attribute values begin or end or according to what substring they contain throughout the value is possible. Below are some common examples.

The Secure Protocol

Every well-formed (i.e. absolute) URL begins with a URI scheme followed by a colon. The most common on the Web is http:, but mailto: (for SMTP) and tel: (which refers to telephone numbers) are also prevalent. If we know how the href value of the hyperlink is expected to begin, we can exploit this semantic convention as a styling hook. In the following example for secure pages, we use the ^= comparator, which means “begins with.”
a[href^="https:"] {
   /* style properties exclusive to secure pages */
}
a link to a secure page with a lock icon
In Auticons, links to secure pages become adorned with a padlock icon according to a specific semantic pattern, identifiable within the href attribute. The advantages of this are as follows:
  • Links to secure pages — and only secure pages — are able to resemble links to secure pages by way of the padlock icon.
  • Links to secure pages that cease to be true links to secure pages will lose the https protocol and, with it, the resemblance.
  • New secure pages will adopt the padlock icon and resemble links to secure pages automatically.
This selector becomes truly intelligent when applied to dynamic content. Because secure links exist as secure links even in the abstract, the attribute selector can anticipate their invocation: As soon as an editor publishes some content that contains a secure link, the link resembles a secure one to the user. No knowledge of class names or complex HTML editing is required, so even simple Markdown will create the style:
[Link to secure page](https://payment.example.com/)
Note that using the [href^="https:"] prefix is not infallible because not all HTTPS pages are truly secure. Nonetheless, it is only as fallible as the browser itself. Major browsers all render a padlock icon natively in the address bar when displaying HTTPS pages.
PayPal secure page

File Types

As promised, you can also style hyperlinks according to how their href value ends. In practice, this means you can use CSS to indicate what type of file the link refers to. Auticons supports .txt, .pdf, .doc, .exe and many others. Here is the .zip example, which determines what the href ends with, using $=:
[href$=".zip"]:before, 
[href$=".gz"]:before {
   content: '\E004'; /* unicode for the zip folder icon */
}

Combinations

You know how you can get all object-oriented and use a selection of multiple classes on elements to build up styles? Well, you can do that automatically with attribute selectors, too. Let’s compare:
/* The CSS for the class approach */

.new-window-icon:after {
   content: '[new window icon]';
}

.twitter-icon:before {
  content: '[twitter icon]';
}

/* The CSS for the attribute selector approach */

[target="_blank"]:after {
   content: '[new window icon]';
}

[href*="twitter.com/"]:before {
  content: '[twitter icon]';
}
(Note the *= comparator, which means “contains.” If the value string contains the substring twitter.com/, then the style will be honored.)
<!-- The HTML for the class approach -->

<a href="http://twitter.com/heydonworks" target="_blank" class="new-window-icon twitter-icon">@heydonworks</a>

<!-- The HTML for the attribute selector approach -->

<a href="http://twitter.com/heydonworks" target="_blank">@heydonworks</a>
A twitter link with icons to show that it goes to twitter and is external
Any content editor charged with adding a link to a Twitter page now needs to know only two things: the URL (they probably know the Twitter account already) and how to open links in new tabs (obtainable from a quick Google search).

Inheritance

Some unfinished business: What if we have a link that does not match any of our special attribute selectors? What if a hyperlink is just a plain old hyperlink? The selector is an easy one to remember, and performance fanatics will be pleased to hear that it couldn’t be any terser without existing at all.
A basic anchor selector (a)
Flippancy aside, let me assure you that inheritance within the cascade works with attribute selectors just as it does with classes. First, style your basic a — perhaps with a text-decoration: underline rule to keep things accessible; then, progressively enhance further down the style sheet, using the attribute selectors at your disposal. Browsers such as Internet Explorer (IE) 7 do not support pseudo-content at all. Thanks to inheritance, at least the links will still look like links.
a {
  color: blue;
  text-decoration: underline;
}

a[rel="external"]:after {
   content: '[icon for external links]';
}

Actual Buttons Are Actual

In the following section, we’ll detail the construction of our CSS bookmarklet for reporting code errors. Before doing this, let’s look at how plain stupid selectors can creep into our workflow in the first place.
Adherents of OOCSS are keen on classes because they can be reused, as components. Hence, .button is preferable to #button. I can think of one better component selector for button styles, though. Its name is easy to remember, too.
button element selector
The <button> element represents a button.
W3C Wiki
Topcoat is an OOCSS BEM-based UI framework from Adobe. The CSS for Topcoat’s various button styles is more than 450 lines if you include the comment blocks. Each of these comment blocks suggests applying your button style in a manner similar to this introductory example:
   <a class="topcoat-button">Button</a>
This example is not a button. No, sir. If it were a button, it would be marked up using <button>. In fact, in every single browser known to man, if it were marked up as a button and no author CSS was supplied, you could count on it looking like a button by default. It’s not, though; it’s marked up using <a>, which makes it a hyperlink — a hyperlink, in fact, that lacks an href, meaning it isn’t even a hyperlink. Technically, it’s just a placeholder for a hyperlink that you haven’t finished writing yet.
Dog in a shark costume
A dog in a shark costume does not a shark make. (Image: reader of the pack)
The examples in Topcoat’s CSS are only examples, but the premise that the class defines the element and not the HTML is deceptive. No amount of class name modification via “meaningful hyphenation” can make up for this invitation to turn your unintelligent selector into a plain stupid one and to just code stuff wrong.
Update: Since writing this article, Topcoat.io has replaced these examples with <button> examples. This is great! However, I still have my reservations about the way the examples expound the use of the .is-disabled class while omitting the proper disabled attribute. To hear both sides, find my conversation with the Topcoat representative in the comments. For further examples of OOCSS-facilitated web standards mishaps, look no further than semantic-ui.com. The “standard button” in their examples is a <div> containing an empty <i>.

See No Evil, Hear No Evil

“If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.”
A link that resembles a button and triggers button-like JavaScript events is, to many, a button. However, this only means that it has passed the first two stages of the “duck test.” For all users to be able to apply inductive reasoning and discern the button as such, it must also quack like one. Because it remains a link, it will be announced by screen readers as “link,” meaning that your allegorical skyscraper is not wheelchair-accessible. Avoiding this kind of unnecessary confusion for assistive technology users is not a pursuit of semantic perfection but a responsibility we should undertake for real benefit.
Nonetheless, some will insist on using a as the basis of their buttons. Hyperlinks are (slightly) easier to restyle consistently, after all. If a is the element of choice, then there is only one way to make it a close-to-true button in the accessibility layer. You guessed it: You must apply another meaningful attribute in the form of a WAI ARIA role. To ensure that a hyperlink element looks like a button for good reason, apply only the following attribute selector.
[role="button"] {
   /* semantic CSS for modified elements that are announced as “button” in assistive technologies */
}

Quality Assurance With Attribute Selectors

“CSS gives so much power to the class attribute, that authors could conceivably design their own “document language” based on elements with almost no associated presentation (such as DIV and SPAN in HTML) and assigning style information through the “class” attribute. Authors should avoid this practice since the structural elements of a document language often have recognized and accepted meanings.”
– “Selectors,” CSS Level 2, W3C
The reason we have two elements — a and button — is to semantically demarcate two entirely different types of functional interaction. While the hyperlink denotes a means to go somewhere, the button is intended as the instigator of an event or action. One is about traversal, the other about transformation. One facilitates disengagement, the other engagement.
To make sure we don’t do anything too daft and get our links and buttons muddled up, we will now build a CSS bookmarklet that uses intelligent attribute selectors to test the validity and quality of the two respective elements.
Inspired partly by Eric Meyer’s post and taking a few cues from DiagnostiCSS, this style sheet will combine attribute selectors and the :not selector (or negation pseudo-class) to highlight problems in the HTML. Unlike these other two implementations, it will write an error to the screen using pseudo-content. Each error will be written in Comic Sans against a pink background.
By connecting function directly to form, we see that ugly markup results in ugly CSS. Consider this the revenge of an abused document, exacted on its designer. To try it out, drag revenge.css to your bookmarks, and click the bookmark to trigger it on any page that you fancy. Note: It won’t currently work for pages that are served over https.
REVENGE.CSS
Drag to your bookmarks bar.

Rule 1

“If it’s a hyperlink, it should have an href attribute.”
a:not([href]):after {
   content: 'Do you mean for this to be a link or a button, because it does not link to anything!';
   display: block !important;
   background: pink !important;
   padding: 0.5em !important;
   font-family: 'comic sans ms', cursive !important;
   color: #000 !important;
   font-size: 16px !important;
}
Notes: In this example, we are testing not the attribute’s value, but whether the attribute exists in the first place — that is, whether [href] matches any element with an href attribute. This test is only appropriate on hyperlinks, hence the a prefix. The rule reads like, “For every a element that is not also an [href] element, append some pseudo-content with an error notice.”

Rule 2

“If it’s a hyperlink and has an href attribute, it should have a valid value.”
a[href=""]:after, a[href$="#"]:after, a[href^="javascript"]:after {
   content: 'Do you mean for this link to be a button, because it does not go anywhere!';
   /*... ugly styles ...*/
}
Notes: If the href is empty, ends in a # or is using JavaScript, it’s probably being used as a button without the correct button element. Note that I am using “starts with javascript.” Standard practice for voiding hrefs is to use javascript:void(0), but we can’t depend on that always being written in the same way (with or without a space after the colon, for example).

Rule 3

“If it uses a button class, it should be a button — at least in the accessibility layer.”
.button:not(button):not([role="button"]):not([type="button"]):not([type="submit"]):not([type="reset"]):after,
.btn:not(button):not([role="button"]):not([type="button"]):not([type="submit"]):not([type="reset"]):after, 
a[class*="button"]:not([role="button"]):after {
   content: 'If you are going to make it look like a button, make it a button, damn it!';
   /*... ugly styles ...*/
}
Notes: In this example, we’re demonstrating how you can chain negation when testing for attributes. Each selector reads like this: “If the element has a class that says it’s a button but it’s not a button element and it doesn’t have the correct role to make it a button in the accessibility layer and it’s not an input being used as a button, then… well, you’re lying.” I’ve had to use [class*="button"] to catch the many Topcoat class variations (62 in total!) that fail to enforce actual buttons on hyperlinks. I’ve noticed that some authors use button-container and the like on parent elements, which is why the a qualifier is included to avoid false positives. You may recognize the .btn class from Twitter Bootstrap, which (if you’ve read the component’s documentation carefully) you’ll know is also unsure about whether links or buttons are buttons.

Rule 4

“If it is an a element with role="button", then it should link to somewhere when JavaScript is off.”
a[role="button"]:not([href*="/"]):not([href*="."]):not([href*="?"]):after {
   content: 'Either use a link fallback, or just use a button element.';
   /*... ugly styles ...*/
}
Notes: We can be fairly sure that hrefs that do not include one of /, . (usually to precede a file extension) or ? (to start a query string) are probably bogus. Getting links to act as buttons and return: false when JavaScript is on is fine — fine, that is, if they have a page to go to when JavaScript is off. In fact, it’s the only legitimate reason I can think of not to use <button> instead.

Rule 5

“You can’t disable a hyperlink.”
a.button[class*="disabled"]:after, 
a.btn.disabled:after,
a[class*="button"][class*="disabled"]:after {
   content: 'You cannot disable a hyperlink. Use a button element with disabled="disabled".';
   /*... ugly styles ...*/
}
Notes: Even ancient user agents understand the disabled attribute, so use it with an appropriate element in a compliant way. You can concatenate attribute selectors just as you can concatenate classes: In the last of the three selectors, we’re saying, “If it’s a link that contains the substring button and the substring disabled, then print an error message.” Twitter Bootstrap uses the second form, .btn.disabled, in its style sheet, but not with the a prefix. We’ll only consider it an error if used on hyperlinks.

Rule 6

“Buttons in forms should have explicit types.”
form button:not([type]):after {
 content: 'Is this a submit button, a reset button or what? Use type="submit", type="reset" or type="button"';
}
Notes: We need to determine whether buttons within forms have explicit types, because some browsers will treat any button in this context without a specified type as type="submit". We want to be absolutely sure that the form won’t submit if our button has a different purpose.

Rule 7

“Both hyperlinks and buttons should have some sort of content or an ARIA label.”
a:empty:not([aria-label]):not([aria-labelledby]):after, 
button:empty:not([aria-label]):not([aria-labelledby]):after, 
button:not([aria-label]):not([aria-labelledby]) img:only-child:not([alt]):after, 
a:not([aria-label]):not([aria-labelledby]) img:only-child:not([alt]):after {
   content: 'All buttons and links should have text content, an image with alt text or an ARIA label';
   /*... ugly styles ...*/
}
Notes: Buttons and links that don’t include any kind of direction for their usage — in either textual or graphical form — are pretty bogus. These final two selectors are perhaps the most complex I’ve ever written. For the hyperlink version, the selector reads something like this: “If it is a hyperlink that does not have either an aria-label attribute or an aria-labelledby attribute and it contains only an image as content but this image does not have an alt attribute, then write the ugly error message.” Also, note the use of the :empty selector. Arguably, no element that is not self-closing should ever be left empty.
Ten points to the first person using revenge.css who can tell me where I’ve broken my own rule in this very article. Trust me, the error is definitely there.

Conclusion

The reason I use the kinds of selectors and patterns described above is not to try something different or to have something new to write about. Attribute selectors aren’t, by themselves, anything new anyway. IE 6 is the only browser that doesn’t support them. The reason I use them is because I simply do not have the time or mental capacity to “do” HTML and CSS in parallel. My brain just isn’t good enough for that. The reason I style my page headers with [role="banner"] and not .page-header is because that’s the only way I’ll know — upon seeing the intended visual effect — that I’ve put the navigable landmark in place. How else does one keep track? You can’t just leave it to testing, because then it’s usually too late.
There’s no such thing as semantic CSS. There’s only semantic HTML and its visible form. In this article I have tried to demonstrate that, by coupling the function and form of Web pages directly, you can create mechanisms for reward and punishment. On the one hand, you can set up selectors that invoke visual motifs only when the suitable markup is used. On the other hand, you can query the markup for bad patterns and erode the visual design as a commitment to the underlying ugly truth.
It’s true that not all the styling hooks in your arsenal will likely ever be uniformly semantic or intelligent. Classes are often desirable as polyfills for much needed elements or attributes that have yet to be standardized. That’s how .footer became <footer> and type="text" (with a bunch of JavaScript) became type="url". Other times, they are helpful for doing non-semantic layout scaffolding with grid frameworks and the like.
However, if you are committed to giving CSS its own completely separate logic, then you are bound to create unnecessary arguments between form and function. In this eventuality, only constant vigilance can protect against inaccessibility and invalidity. To make matters worse, trying to manufacture pseudo-semantics purely with classes makes it easy to fall into one of those interminable discussions over what makes a semantic class name. You’ll start spending less time using the remote to control the TV and more time just sitting there, contemplating the remote control held in your hand.
Life is too short.