Problem/Motivation

The system pager template(s) contain a hardcoded h4.visually-hidden element. In some common contexts, this produces a heading in the document which does not follow heading level order. This is reported as a (best practices) accessibility issue by tools such as aXe.

- https://git.drupalcode.org/project/drupal/-/blob/9.2.x/core/modules/syst...

- https://www.w3.org/WAI/tutorials/page-structure/headings/
- https://dequeuniversity.com/rules/axe/4.3/heading-order

This was raised in Drupal Slack #accessibility channel, see there for some early discussion.

aXe's report is a best practices notification, moderate impact:

Heading levels should only increase by one.

Issue description: Ensures the order of headings is semantically correct

To solve this issue, you need to... Fix the following: Heading order invalid

Steps to reproduce

This affects all default themes in 9.2.x: Bartik, Claro, Olivero, Seven, and Stark.

- Use Devel Generate to generate 50 nodes
- View the default /node view
- Observe that the headings in the document run h1 (page title), h2 (node titles), h4 (pagination), OR
- Run aXe Devtools or other a11y checker

Proposed resolution

Remove the h4 and use a aria-label and/or role on the <nav> element

There's already an aria-labelledby on the <nav>; we could replace that with aria-label and remove the <h4> entirely. This requires that the replacement provide equivalent functionality / accessibility. Is a role also appropriate here? There may be many pagination controls on a single page.

Other options considered:

Replace the h4 with an h2

This replaces one hardcoded value with another, and retains some assumptions about the page (ie that there is an h1 present at all). It probably introduces BC issues for themes which presume h4 for this, and if the pagination element is placed within a subsection it will incorrectly raise the pagination widget to a new second level section.

Make the tag used configurable

This could permit site builders to configure the heading level per View display or other pagination use. (This could be combined with changing the default tag from h4 to another heading level.)

Remaining tasks

User interface changes

Hopefully, increased accessibility. Changes to HTML output.

API changes

Proposed options will change elements in default themes.

Data model changes

Release notes snippet

Issue fork drupal-3232222

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

xurizaemon created an issue. See original summary.

xurizaemon’s picture

Issue tags: +Accessibility
xurizaemon’s picture

Issue summary: View changes
larowlan’s picture

Given this is in a twig template, and therefore can be overridden by a theme on a project, I think we're only talking about making core theme's semantically correct w.r.t to structure/heading levels.

So it would be good to use an a11y tool to see which of the core themes (seven/claro/bartik/olivero) have this issue.

Bearing in mind that we can't change markup in minor versions for seven or bartik (as they're stable) nor in stable/stable9.

xurizaemon’s picture

Issue summary: View changes
xurizaemon’s picture

@larowlan, correct. I should clarify that I've set version=9.2.x because that's where I've reproduced it; it looks like this isn't yet fixed in 9.3.x or 10.x and I'm happy for version to be set appropriately, anticipating that we would not change templates in a current release.

I'll check with each of those themes and update.

xurizaemon’s picture

Issue summary: View changes

Bartik, Seven, Claro, and Olivero (and Stark) all exhibit this behaviour in Drupal 9.2.x when tested with aXe Devtools in Firefox.

xurizaemon’s picture

Issue summary: View changes
xurizaemon’s picture

Issue summary: View changes
mikemai2awesome’s picture

Correct me if I am wrong, the aria-label method would work just as well since nav is already a landmark.

Otherwise, I think it is reasonable to "make the tag used configurable". The content creator should have full control of information architecture on a given page, the template should not have absolute opinion on the heading.

xurizaemon’s picture

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

xurizaemon’s picture

Status: Active » Needs work

Tests have failed for template hashes, will update shortly.

maiam’s picture

maiam’s picture

hi folks! i'm the accessibility lead at Catalyst IT. Here are my 2 cents:

A heading is meant to demarcate a section (https://www.w3.org/TR/REC-html40/struct/global.html#h-7.5.5 "A heading element briefly describes the topic of the section it introduces"). Are we demarcating a section here? I don't really think we are. I think the <h4> (and any other <h#>) should be removed entirely.

Instead, what is the <h4>'s purpose here? I think it is being used to indicate to screen reader users that the pagination exists. That's cool, and in which case there are certainly ways we can achieve this.

My favourite option is to use <nav> (which is already being done) since pagination is indeed a way to navigate through the page content. Screen reader users are able to pull up the aria landmarks of a page, "scanning" the page. <nav> accurately reflects the nature of the role of pagination, as well as removes the risk of messing with the page hierarchy without context since this is a reusable component.

Note there's no such thing as role=pagination. With <nav>, built into that element is role=navigation.

Here's a good design pattern for an accessible pagination: https://www.a11ymatters.com/pattern/pagination/ According to this link, I recommend:

<nav aria-label="Pagination Navigation"> <!-- the combo of nav and aria-label give a clear signal to what the purpose of this component is -->
    <ul>
        <li><a href="/page-1" aria-label="Goto Page 1">1</a></li> <!-- use aria-label here for better UX for assistive tech -->
        <li><a href="/page-2" aria-label="Goto Page 2">2</a></li>
        <li><a href="/page-3" aria-label="Current Page, Page 3" aria-current="true">3</a></li> <!-- use JS to dynamically indicate which page is the current -->
    </ul>
</nav>
xurizaemon’s picture

Thanks Maia for the review & feedback (for transparency, @maiam and I are colleagues).

I did not change the existing label text from "Pagination" to "Pagination Navigation" as IMO that would have translation impact as well.

Have updated tests to account for new hashes on Classy templates (TIL!).

Note there's no such thing as role=pagination. With <nav>, built into that element is role=navigation.

My mistake on role="pagination" I think. I double checked the intent of this statement with Maia directly who said,

role=navigation was introduced in HTML4 (i believe), when <nav> didn't exist yet. So it would be used to give more semantic meaning to a <div>. But with HTML5, they introduced aria landmarks, which build in the semantics for us

So there's an additional suggestion here to remove the role="navigation" from the nav element; I'm happy to tidy this up while I'm here, or for someone else to do so and add to the MR, but I'll await input from others who might want to comment.

xurizaemon’s picture

Issue summary: View changes
xurizaemon’s picture

Status: Needs work » Needs review

Should have set this back to NR when I fixed the tests above, I think.

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.

KurtTrowbridge made their first commit to this issue’s fork.

kurttrowbridge’s picture

Hello! I had brought this issue up today in another project that provides a Drupal design system, so we could implement the same accessibility adjustment there, and conversation there reiterated Maia's suggestion in #15 above: that role="navigation" is built into the <nav> element by default, so including it is redundant. MDN supports that removal ("Using the <nav> element will automatically communicate a section has a role of navigation. Developers should always prefer using the correct semantic HTML element over using ARIA"), and ARIA's first rule is to not use ARIA in cases where semantic HTML alone does the trick. As such, I committed the removal of those role attributes to the existing merge request. Thanks!

xurizaemon’s picture

Assigned: Unassigned » xurizaemon

Thanks @KurtTrowbridge! Appreciate having a second assessment to support the recommended course of action.

Tests had failed due to the template change no longer generating a committed hash; I've rebased the MR, and updated the relevant hash accordingly. (This issue was how I learned that those hashes exist!)

xurizaemon’s picture

Assigned: xurizaemon » Unassigned
xurizaemon’s picture

As Gitlab MR URLs are subject to unexpected changes (ref #3204538), I'm attaching a patch copy of MR !1186 as at some earlier revision.

This wants a re-roll anyway, please continue using the MR.

xurizaemon’s picture

Status: Needs review » Needs work

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.

xurizaemon’s picture

A new issue #3333401: Pager h4 causes accessibility flag on many pages has been opened for this with fix targeting Drupal 10 and has already made it to RTBC, and there is then a 10.x scoped stable9 issue #3333418: Fix pager h4 for accessibility on Stable9 to follow up on that one.

Posting this as folks interested in seeing this resolved (10 followers) may want to track those issues (less than 10) also.

mgifford’s picture

Issue tags: +wcag246

Tagging for WCAG 2.4.6

nicxvan’s picture

Status: Needs work » Closed (duplicate)