Problem/Motivation

Current heading structure in Drupal 8 includes visibly hidden headings, plus H2 and H3 headings that proceed the first H1. This deviates from the following best practices:

  • Use H1 to markup the most important heading on the page. Typically this will be the site name on the home page, and on other pages it will be the top-level heading or title of the main unique content.
  • Use H2 to markup headings that are secondary to the H1, thereby forming an outline of the page content.
  • Don't overuse headings. Headings provide important organizational clues for screen reader users and facilitate navigation (screen reader users can jump between headings with a single keystroke). If there are too many headings or if headings don't form an outline that is consistent with the organizational structure of the page, the benefits of having headings are diminished.
  • Avoid hidden headings that are only intended for screen reader users. Instead use HTML5 semantic elements, ARIA roles, and aria-label attributes. These are now widely supported by screen readers, rendering hidden headings obsolete.

Proposed resolution

  • Remove all headings that have class="visually-hidden"
  • Add an aria-label attribute to the nearest semantic parent element (e.g., nav) and use the text of the visually hidden heading as the value of aria-label
  • Repeat this same procedure for headings that are visibly hidden using other methods (not class="visually-hidden"). An example of this is div#block-footer, which doesn't use class="visually-hidden" but replicates that same style using the #footer .block > h2 selector (in bartik/styles/style.css).

Example:

  • Remove <h2 class="visually-hidden">Toolbar Items</h2>
  • Add aria-label="Toolbar Items" to nav#toolbar-administration

Another justification for resolving this is that any given Drupal page includes multiple nav elements and/or elements with role="navigation". Adding aria-label attributes to these elements enables screen reader users to tell them apart. Otherwise, each of these elements is generically identified by screen readers as "Navigation region" and users have to drill into their content to more precisely identify them.

Comments

bowersox’s picture

Issue tags: +TwinCities
jessebeach’s picture

Assigned: Unassigned » jessebeach
falcon03’s picture

Status: Needs work » Active
Issue tags: +dream markup

@terrill: well, I agree and disagree at the same time...

We should be really, really careful about removing headings. In fact, the most important benefit that they give us is to allow screen reader users to jump back and forth between them. Now, is there any shortcut/hotkey provided by screen readers (in any platform, including IOS and, eventually, Android) that allows a blind user to quickly reach a "nag" element or another element which the navigation ARIA role is assigned to?

If the content of the nav element is a list there will be no problems in most platforms, since screen readers generally allow to jump between lists; but, if the content of the element is not a list, then we should make a case-by-case decision on what to do!

On a side note: Did you intentionally set the issue status to "needs work"?

mgifford’s picture

Version: 8.x-dev » 9.x-dev

I do think this is something that should be done for D9, but there have been a few places where this has been discussed where it is too soon to do so for D8.

There is what the latest screen reader's support, but also realities about how blind people navigate the web. I expect this will change as ARIA usage becomes more standardized.

Interesting to know that a heading may not enhance the accessibility of a list... It still provides context mind you.

terrill’s picture

@falcon03 I think screen reader support for ARIA landmark roles is mature enough now that we can rely exclusively on them for facilitating screen reader navigation.

Landmark roles are supported in JAWS, NVDA, ORCA, Chromevox, Window Eyes and VoiceOver. JAWS has supported them since JAWS 10 (current version is 13). When a page is loaded JAWS announces the number of landmarks, and users can navigate between them using semi-colon or backwards using Shift+semi-colon. They can also bring up a list of landmarks using CTRL + INS + semi-colon.

VoiceOver includes landmarks in the rotor, both on the desktop and in iOS.

Screen reader support for HTML5 semantic elements is relatively new, but if these elements are supplemented with ARIA landmark roles that ensures solid support for screen reader users.

This frees up heading elements to be used exclusively for marking up visible headings, which increases the likelihood that headings will form an outline of the page content. That's much cleaner and better for accessibility than having a bunch of orphaned headings that don't fit within the structural hierarchy.

mgifford’s picture

Mentioned this issue in @jessebeach's patch here #2047175: Make the status message field discoverable by assistive technology agents; alert AT agent users to error messages removes the heading.

It's really tempting to remove the headings. Particularly as we're reviewing the code for Twig & DreamMarkup.

Everett & I have talked about this in the past, and really great that @terrill brought it up. After posting this question on Twitter I'm less certain that we will be able to remove headings in D9. That might change, but I'll pull some highlights from the thread.

This is a summary of the discussion on Twitter. I didn't copy/paste my tweets, but don't think they were that important. Mostly trying to ask questions & clarify things.

Most folks are building solutions for individual sites rather than for general systems. It is ok to follow a different path for a generalized system, but would be good to have some user testing first.

@ppatel 4:53am - I think people do know breadcrumbs. so, @terrillthompson, is the intention then to expose the breadcrumb content? Or would a CSS class be applied to hide the actual content, merely getting rid of the heading?

@deborah_gu 8:45pm - Huh. Do non-webby end users even know words like "breadcrumbs"?

@terrillthompson 8:37pm -"Toolbar Menu" raises another issue - how to meaningfully label UI features. Assuming we have a meaningful label for a <nav>, how best to markup that label? As aria-label, hidden heading, or both?

@ppatel 8:06pm - @terrillthompson What does "toolbar menu" mean to the user who's listening to it? @mgifford

@icaaq 11:40am - that's how i did on my last project as well

@terrillthompson 11:02am - I'm proposing <nav role="navigation" aria-label="Toolbar menu"> rather than <nav><h2 class="hidden">Toolbar Menu</h2>

@ppatel 10:14am - @terrillthompson I disagree. ARIA-labels don't provide the navigation advantages that headings do. Besides, ARIA-label requires an object to label. You can sue a <div>. Not sure how else to replace w/ ARIA-label. I agree that redundancy creates extra verbiage. But, headings and landmarks have keyboard advantages.

@terrillthompson Jul 24, 11:25pm - In Drupal8 most of the headings in question are invisible <h2>, nested inside <nav role="navigation">. My recommendation is to remove these hidden h2 elements and use their values in aria-label attributes

@MartianWebDev Jul 24, 9:22pm - "magazine > 2013 > March" is more like the breadcrumb's content, not heading. "You are here:" would be the invisible beadcrumb-heading, that nav landmark role would let us dispose of. As a sighted, structured-document geek, I prefer "you are here:" to be a visible header, whatever designers say ;-) I do actually agree for breadcrumbs. It's a peculiar kind of nav where the extra "you are here" context helps.

@ppatel Jul 24, 8:26pm - What do you mean breadcrumbs? Do you mean the heading that says "magazine > 2013 > March"? If so, I don't recommending getting rid of that heading. No landmark can be substituted for that kind of info.

@ppatel Jul 24, 8:21pm - There may be redundancy. Think of landmarks as region markers. sure but landmarks don't provide the same info as headings about destination within a screen reader, but headings as defining document structure. The only ones you can safely get rid of are nav or search.

@deborah_gu Jul 24, 7:21pm - Yes, hidden headings can hint about specific layout-clued nav, like "breadcrumbs".

@ppatel Jul 24, 6:07pm - I do not believe that hidden headings can be replaced by landmarks. Semantics don't always make sense for landmarks. Hidden headings cannot be placed anywhere one wishes.

@LaurentGoderre Jul 24, 5:54pm - landmark are very general while headings can be way more accurate

@terrillthompson Jul 24, 4:07pm - Rephrasing question: Are invisible screen-reader-only headings necessary if there are landmarks? #a11y

@ppatel Jul 24, 2:02pm - +1. Headings could be used by anyone. RT @stevefaulkner: @mgifford @jsutt landmarks and headings serve different purposes

@deborah_gu Jul 24, 1:05pm - oh, yeah. That's a different kettle of fish. Still, headers also give you access the page outline, which gives a nice overview.

@deborah_gu Jul 24, 12:04pm - aren't many people always 3-4 versions back on jaws because of cost? Shouldn't dumping headings wait a little longer?

@kirankaja12 Jul 24, 9:56am - No, I still want my headings.

@stevefaulkner Jul 24, 9:27am - landmarks and headings serve different purposes

terrill’s picture

Since there isn't consensus within the accessibility community on this issue I'm willing to relax my position on removing invisible headings. Perhaps a good gauge to use in order to determine when it's ok to proceed is the WebAIM Screen Reader User Survey. The most recent survey reveals that as of May 2012 there were still quite a few users who seldom or never use ARIA landmarks: http://webaim.org/projects/screenreadersurvey4/#landmarks

I suspect the number of frequent landmark users have grown significantly in the last 14 months, but until we have data supporting much higher usage I guess we should stick with old tried and true methods.

That said, I still think we should add aria-label attributes to all <nav> elements. There are many of these on each page, and without a label they're each identified by screen readers as "Navigation region" - there's no means of clarifying which navigation region is which. If we add aria-label, screen readers use the value of aria-label when identifying the region (e.g., "Toolbar Items Navigation Region", "Breadcrumb Navigation Region", and the like)

A good question came up in the Twitter conversation though: In assigning labels for regions, what constitutes a good label for end-users? "Toolbar Items" may or may not be meaningful. The same applies to invisible headings. Perhaps reviewing these to be sure they're likely to be meaningful should be another issue.

mgifford’s picture

This is a great discussion @terrill. I'd love to get some feedback from the WebAIM Screen Reader User Survey. Tracking user behavior is really important.

The more ARIA landmarks are part of how a good website is built, the more folks will expect them to be there. It is interesting to also note that blind users are using headings & ARIA differently and that they may evolve to have different roles.

I'm totally in favor of adding aria-label attributes to all <nav> elements in D8. Let's do that in a new issue, and leave this one to address how/when/if we're going to clean up how Drupal deals with headings, invisible headings specifically & how structural headings are presented within Drupal.

Also, totally in favor of reviewing the headings that we are using to see that they are providing meaning to the end-users. We've talked about having a focus group to help get input from end-users, but it's difficult to organize. This would also be another good issue for D8.

Bit of a tangent, but thought I'd pull in @Jesse Beach's post from 2010 is also worth considering as far as how this affects SEO https://www.acquia.com/fr/blog/rethinking-use-h2-tags-core

Not sure what the status of that is in 2013.

falcon03’s picture

Well, I think that hearing messages like "entering navigation", "entering main" and so on doesn't give a real "context". So, as a blind user, I'm completely in favor of adding aria-labels. What I really disagree with is removing headings, though. I just want to give a real-usage example: I didn't even know that it is possible to jump properly between different ARIA landmarks with the various existing screen readers. :(

pratikp1’s picture

Please note that my position on keeping headings for now is based on current usage patterns and not because there isn't an effective method of working around headings. In fact, I agree that we can easily get rid of some headings to make navigation better. Semantically, I'd like to see headings be used for actual structure and ARIA-label with nav/other roles and landmarks. Let's hope that screen reader training makes this situation better.

Having an effective label is essential. I would like some discussion about that for D8 or D9. Let's see if we can make it more understandable. It will go a long way toward having users understand that landmarks can actually be useful.

mgifford’s picture

I added #2052473: Add aria-label or aria-describedby attributes to all <nav> elements for the aria-label.

I'd suggested that we set up an issue to review the heading to ensure that they are providing meaning to end-users. Knowing that the headings are more specific forms of navigation and ARIA landmark roles are for regions of the site, are there headings which are presently not useful that we can eliminate?

My understanding of @pratikp1's comments are that the only headings you can safely get rid of might be some of the <nav> elements. If there are some that seem redundant, please list them here. Note that we've already discussed that the breadcrumb heading isn't redundant even if there is an aria-label defined for the <nav>.

jessebeach’s picture

Most admin HTML (like the toolbar and navigation menus) should eschew using H2 elements and use aria-label instead.

So in essence, anything in page_top region should not have heading elements. This prevents an H2 or H3 appearing on the page before the page's H1.

Stomme poes’s picture

Just some 2 cents:
Does "AT" only mean "screen readers for the blind"? ARIA unfortunately is only really being implemented in screen readers, but "AT" means a much broader group. Dragon for example seems to still lack ARIA capabilities, and it's a major navigational tool. It may make sense to rely on ARIA when you need to take visual-only representation of structure and make it available for the visually-impaired, but if cognitive impairment relies on bold, visual names for chunks of page, or physically impaired for navigation (and user agents like Opera can also navigate by heading, which is teh awesome), then I think those use cases should be mentioned in these comments whenever semantic somethings might be removed and replaced with only ARIA.

ARIA refers to "accessible" but "accessible" covers more than "one kind of AT". Heck, it means more than "AT".

I suppose a pro of replacing headers with aria-label (or merely adding aria-label) is that you could get the name of the nav type as you cycle through navs rather than needing to also cycle through headings...

mgifford’s picture

@Stomme poes - nice post. With AT I meant Assistive Technologies, but you're right. I do think that ARIA could also be useful for machines looking for further semantic relationships in content.

With D8 though we're looking not to what is in place now, but where stuff is going to be. I do think that Dragon will be starting to support ARIA as it becomes more popular. I don't know what their roadmap is.

ARIA landmarks are more in place for identifying regions. That's generally used differently (from what I understand) than headings. However, we're needing to look ahead at not what user behavior is right now, but where it might be in the future.

With D8 we realistically are looking at late 2014 till we start to see the curve of adoption jump. It will be in it's strongest in 2015-2016.

We don't want to be too far ahead of the curve of behavioral change, but on the other hand, we don't want to be behind either.

And yes, definitely not just for blind users.

mgifford’s picture

Issue summary: View changes

Adding additional clarification

Rich Caloggero’s picture

Note that only Jaws supports labeling regions via aria-label and aria-labelledby. The NVDA folks have refused to support it, even after more than a few requests from users.

I strongly suggest not throwing away those hidden headings just yet.

I also strongly suggest that if section elements must be used, add role="presentation" to them. If role of presination not used, jaws creates a landmark and region start / end messages for each section element. SInce most authors use section like div, the landmarks list will grow and many extra region start / end messages will be created, making the presentation very noisy for Jaws users.

mgifford’s picture

Issue summary: View changes
Issue tags: +nvda

Making a tag for NVDA issues.

mgifford’s picture

Assigned: jessebeach » Unassigned
Issue tags: -
catch’s picture

Version: 9.x-dev » 8.1.x-dev

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Stephen Ollman’s picture

A page should never have two <H1> tags, so having "Heading 1' by default is bad practice and should be an manual additional, not available by default.

If you open a site up to decentralised content authoring the availability of the 'Heading 1" option is not a great idea. A starting level of 'Heading 2' as with D7 is the better way of going.

What's the best method in D8 to remove the 'Heading 1' option from the list.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Stephen Ollman’s picture

Will this be fixed in version 8.4?

It's still an issue with 8.3.0-rc2.

andrewmacpherson’s picture

@Stephen Ollman - I assume you're talking about the options in the "format" selector in the rich text editor? That's probably out of scope for this issue, which is mostly about markup generated by templates.

Using the Standard installation profile from Drupal 8 Core, the "Basic HTML" text format offers h2-6, while the "Full HTML" text format offers h1-h6. "Restricted HTML" also permits h2-h6, but does not have a rich text editor toolbar.

The list of available formats is configurable at admin/config/content/formats. The options offered in the editor toolbar reflect the tags permitted in the settings for the "Limit allowed HTML tags and correct faulty HTML" filter. For example, you could remove h2 from the list of allowed tags for the "Basic HTML" format, and it will no longer appear in the CKEditor toolbar options. However, this only takes effect when the "Limit allowed HTML tags and correct faulty HTML" is enabled.

Unfortunately, this setting won't allow us to remove the H1 option from the "Full HTML" text format. The "Limit allowed HTML tags and correct faulty HTML" uses a whitelist of allowed tags (rather than a blacklist of banned tags), so it isn't a good choice for the Full HTML text format. As a workaround, you could try enabling "Limit allowed HTML tags and correct faulty HTML" on the Full HTML, and listing all possible HTML5 elements except H1. This isn't very elegant (or maintainable) so I don't think it's a good solution for Drupal Core.

I agree that it would be nice to have an easy way to ban H1 from the editor.

mgifford’s picture

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

andypost’s picture

Category: Bug report » Task

It's not a bug

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.