Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the screen reader experience for the header menu #2427

Merged
merged 5 commits into from
Dec 6, 2021

Conversation

36degrees
Copy link
Contributor

@36degrees 36degrees commented Nov 9, 2021

This brings the use of aria-label and aria-controls in the menu navigation in the header in line with other 'best practise' examples and guidance from W3C.

Move the label from the <ul> to the <nav>

Move the 'Navigation menu' label from the <ul> to the parent <nav> element - this has previously been flagged as a 'possible misuse of aria-label'.

According to WAI ARIA Practises 1.2, it's recommended to label navigation regions, especially as 'if a page includes more than one navigation landmark, each should have a unique label'.

Lists can optionally be labelled, but this is only 'potentially beneficial for users of screen readers that support both list names and navigation among lists on a page'.

Applying the label to both the list and the parent navigation could be noisy – "Potentially a source of distracting or undesirable screen reader verbosity, especially if nested within a named container, such as a navigation region."

The provided examples also apply the label consistently to the navigation region (albeit using aria-labelledby).

Remove redundant 'navigation' from the nav label

In line with the section 'Composing Effective and User-friendly Accessible Names' in WAI-ARIA Authoring Practices 1.2, remove the word navigation from the aria-label on the navigation.

'Do NOT include a WAI-ARIA role name in the accessible name. For example, do not include [..] the word "navigation" in the name of a navigation region. Doing so would create duplicate screen reader output since screen readers convey the role of an element in addition to its name.'

Without this change, assistive technologies report this as 'Navigation menu navigation'.

Also remove the word 'navigation' from the button that shows or hides the menu, as it also seems redundant – the word 'menu' should be descriptive enough for users to understand what it represents, especially when encountered inside a header landmark.

Move the button inside the <nav>

Move the menu button inside the navigation region, so that it is discoverable by screen reader users even when the nav is closed:

Place mobile open/close buttons within the <nav> element and use them to toggle state of another child wrapper of the nav. This will ensure that the navigation landmark is still discoverable by screen readers, even if it is in a closed/hidden state.

https://a11y-style-guide.com/style-guide/section-navigation.html#kssref-navigation-navigation-mobile

Where a lot of people go wrong is by placing the button outside the region. This would mean screen reader users who move to the <nav> using a shortcut would find it to be empty, which isn’t very helpful.

https://inclusive-components.design/menus-menu-buttons/#placement

For instance, a navigation on small screen devices may initially contain only a single toggle button. But that toggle button would reveal additional links and other navigational elements, when activated.

https://www.scottohara.me/blog/2018/03/03/landmarks.html#navigation

Summary of changes to markup

Before

<button type="button" class="govuk-header__menu-button govuk-js-header-toggle" aria-controls="navigation" aria-label="Show or hide navigation menu" aria-expanded="false">Menu</button>
<nav>
  <ul id="navigation" class="govuk-header__navigation " aria-label="Navigation menu">
      <li class="govuk-header__navigation-item govuk-header__navigation-item--active">
        <a class="govuk-header__link" href="#1">Navigation item 1</a>
      </li>
      <li class="govuk-header__navigation-item">
        <a class="govuk-header__link" href="#2">Navigation item 2</a>
      </li>
      <li class="govuk-header__navigation-item">
        <a class="govuk-header__link" href="#3">Navigation item 3</a>
      </li>
      <li class="govuk-header__navigation-item">
        <a class="govuk-header__link" href="#4">Navigation item 4</a>
      </li>
  </ul>
</nav>

After

<nav aria-label="Menu">
  <button type="button" class="govuk-header__menu-button govuk-js-header-toggle" aria-controls="navigation" aria-label="Show or hide menu">Menu</button>

  <ul id="navigation" class="govuk-header__navigation " >
    <li class="govuk-header__navigation-item govuk-header__navigation-item--active">
      <a class="govuk-header__link" href="#1">Navigation item 1</a>
    </li>
    <li class="govuk-header__navigation-item">
      <a class="govuk-header__link" href="#2">Navigation item 2</a>
    </li>
    <li class="govuk-header__navigation-item">
      <a class="govuk-header__link" href="#3">Navigation item 3</a>
    </li>
    <li class="govuk-header__navigation-item">
      <a class="govuk-header__link" href="#4">Navigation item 4</a>
    </li>
  </ul>
</nav>

Summary of changes to AT experience

JAWS / Chrome

Before After
Behaviour when focusing menu button (mobile viewport) Show or hide navigation menu button collapsed, to activate press enter Show or hide menu button collapsed, to activate press enter
Behaviour when entering navigation region (by tabbing to first link) Navigation region, navigation menu list with 8 items. Departments same page link. Menu navigation region, list with 8 items. Departments same page link.
Behaviour when jumping to controlled element (Insert + Alt + M) Move to controlled element, list, tab [visible focus moves to the list inside the menu] Move to controlled element, show or hide menu [visible focus remains on the menu button]
Appearance in list of navigation landmarks (Ctrl + Insert + R) Banner -> Navigation Banner -> Menu Navigation
Appearance in list of navigation landmarks with nav closed (mobile viewport) Does not appear in list of landmarks Does not appear in list of landmarks
Appearance in list of navigation landmarks with nav open (mobile viewport) Banner -> Navigation Banner -> Menu Navigation

NVDA / Firefox

Before After
Behaviour when focusing menu button (mobile viewport) Show or hide navigation menu button collapsed Menu navigation landmark, show or hide menu button collapsed
Behaviour when entering navigation region (by tabbing to first link) navigation landmark Navigation menu list with 8 items Departments link list with 8 items Departments link
Appearance in list of navigation landmarks (Insert + F7) Banner -> Navigation Banner -> Menu; navigation
Appearance in list of navigation landmarks with nav closed (mobile viewport) Does not appear in list of landmarks Banner -> Menu; navigation
Appearance in list of navigation landmarks with nav open (mobile viewport) Banner -> Navigation Banner -> Menu; navigation

VoiceOver / Safari (macOS)

Before After
Behaviour when focusing menu button (mobile viewport) Show or hide navigation menu, collapsed, button Show or hide menu, collapsed, button, Menu, navigation
Behaviour when entering navigation region (by tabbing to first link) link, Departments, list Navigation menu 8 items link, Departments, list 8 items
Appearance in list of landmarks rotor (VO + U) Navigation Menu navigation
Appearance in list of landmarks rotor with nav closed (mobile viewport) Does not appear Menu navigation
Appearance in list of landmarks rotor with nav open (mobile viewport) Navigation Menu navigation

VoiceOver / Safari (iOS)

Before After
Swiping to menu button Show or hide navigation menu, button, end banner, collapsed. Double tap to expand. Show or hide menu, button, menu, navigation landmark, collapsed. Double tap to expand.
Swiping to first link in navigation region Departments, link, list start, navigation menu, landmark Departments, link, list start
Swiping by landmark (rotor set to landmarks, swiping up/down) Departments, link, list start, navigation menu, landmark Departments, link, list start, landmark
Swiping by landmark with nav closed Swipes between start of header (GOV.UK logo) and main region ('Press release'), missing nav Show or hide menu, button, menu, navigation landmark, collapsed. Double tap to expand.

TalkBack (Android)

Before After
Swiping to menu button Collapsed, "Show or hide navigation menu", button. Double tap to activate, actions available, use tap with three fingers to view. Collapsed, "Show or hide menu", button. Double tap to activate, actions available, use tap with three fingers to view.
Swiping to first link in navigation region "Departments", link. Double tap to activate, links available, use tap with three fingers to view. "Departments", link. Double tap to activate, links available, use tap with three fingers to view.
Swiping by landmark with menu collapsed (reading controls set to 'landmarks', swiping up/down) Navigation. "menu", navigation.
Swiping by landmark with menu expanded (reading controls set to 'landmarks', swiping up/down) Navigation, "navigation menu", list. "menu", navigation, list.

Tested by @lfdebrux in #2427 (comment)

Closes #1340

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 November 9, 2021 17:42 Inactive
@36degrees
Copy link
Contributor Author

Raised as a draft for now – still need to do testing and write up an entry for the release notes.

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 November 17, 2021 17:02 Inactive
@36degrees
Copy link
Contributor Author

Still needs testing with Android / TalkBack.

@lfdebrux
Copy link
Member

lfdebrux commented Nov 22, 2021

Tested Talkback / Chrome (Android) with a Google Pixel 3 running Android 12

Before you cannot navigate to the menu navigation using the landmarks control unless the menu is already open.

Note also that by default Talkback doesn't give you the option to navigate by landmarks, the user has to enable it in the Talkback settings (see note on Deque university page starting "some ... reading controls are hidden by default").

Before After
Swiping to menu button Collapsed, "Show or hide navigation menu", button. Double tap to activate, actions available, use tap with three fingers to view. Collapsed, "Show or hide menu", button. Double tap to activate, actions available, use tap with three fingers to view.
Swiping to first link in navigation region "Departments", link. Double tap to activate, links available, use tap with three fingers to view. "Departments", link. Double tap to activate, links available, use tap with three fingers to view.
Swiping by landmark with menu collapsed (reading controls set to 'landmarks', swiping up/down) Navigation. Does not appear in list of landmarks
Swiping by landmark with menu expanded (reading controls set to 'landmarks', swiping up/down) Navigation, "navigation menu", list. "menu", navigation, list.

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 November 23, 2021 11:55 Inactive
@lfdebrux
Copy link
Member

lfdebrux commented Nov 26, 2021

Testing commit Move button inside navigation region with Talkback / Chrome (Android).

Before After
Swiping to menu button Collapsed, "Show or hide navigation menu", button. Double tap to activate, actions available, use tap with three fingers to view. Collapsed, "Show or hide menu", button. Double tap to activate, actions available, use tap with three fingers to view.
Swiping to first link in navigation region "Departments", link. Double tap to activate, links available, use tap with three fingers to view. "Departments", link. Double tap to activate, links available, use tap with three fingers to view.
Swiping by landmark with menu collapsed (reading controls set to 'landmarks', swiping up/down) Navigation. "menu", navigation.
Swiping by landmark with menu expanded (reading controls set to 'landmarks', swiping up/down) Navigation, "navigation menu", list. "menu", navigation, list.

Note that after swiping to the menu using the landmark swipe, the next item in reading swipe order is the button, but this is not necessarily obvious from the focus border.

Screenshot_Talkback_Chrome_Android_20211126-133912

Move the 'Navigation menu' label from the `<ul>` to the parent `<nav>` element.

This has previously been flagged as a 'possible misuse of `aria-label`.'

According to WAI ARIA Practises 1.2 [2], it's recommended to label navigation regions, especially as 'if a page includes more than one navigation landmark, each should have a unique label' [3].

Lists can optionally be labelled, but this is only '_potentially_ beneficial for users of screen readers that support both list names and navigation among lists on a page'.

Applying the label to both the list and the parent navigation could be noisy – "Potentially a source of distracting or undesirable screen reader verbosity, especially if nested within a named container, such as a navigation region."

The provided examples [4] also apply the label consistently to the navigation region (albeit using `aria-labelledby`)

[1]: #1340 (comment)
[2]: https://www.w3.org/TR/wai-aria-practices-1.1/#naming_role_guidance
[3]: https://www.w3.org/TR/wai-aria-practices-1.1/#aria_lh_navigation
[4]: https://www.w3.org/TR/wai-aria-practices-1.1/examples/landmarks/navigation.html
In line with the section 'Composing Effective and User-friendly Accessible Names' in WAI-ARIA Authoring Practices 1.2 [1], remove the word navigation from the aria-label on the navigation.

'Do NOT include a WAI-ARIA role name in the accessible name. For example, do not include [..] the word "navigation" in the name of a navigation region. Doing so would create duplicate screen reader output since screen readers convey the role of an element in addition to its name.'

Without this change, assistive technologies report this as 'Navigation menu navigation'.

Also remove the word 'navigation' from the button that shows or hides the menu, as it also seems redundant – the word 'menu' should be descriptive enough for users to understand what it represents, especially when encountered inside a header landmark.

[1]: https://www.w3.org/TR/wai-aria-practices-1.2/#naming_effectively
Move the menu button inside the navigation region, so that it is
discoverable by screen reader users even when the nav is closed:

> Place mobile open/close buttons within the <nav> element and use them
  to toggle state of another child wrapper of the nav. This will ensure
  that the navigation landmark is still discoverable by screen readers,
  even if it is in a closed/hidden state.

https://a11y-style-guide.com/style-guide/section-navigation.html#kssref-navigation-navigation-mobile

> Where a lot of people go wrong is by placing the button outside the
  region. This would mean screen reader users who move to the <nav>
  using a shortcut would find it to be empty, which isn’t very helpful.

https://inclusive-components.design/menus-menu-buttons/#placement

> For instance, a navigation on small screen devices may initially
  contain only a single toggle button. But that toggle button would
  reveal additional links and other navigational elements, when
  activated.

https://www.scottohara.me/blog/2018/03/03/landmarks.html#navigation
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 December 1, 2021 11:53 Inactive
@36degrees 36degrees changed the base branch from main to header-navigation-bottom-border December 1, 2021 11:53
Base automatically changed from header-navigation-bottom-border to main December 1, 2021 17:43
@36degrees 36degrees changed the title Make the menu <nav> the labelled and controlled element in the header, rather than the <ul> within it Improvements to the screen reader experience for the menu in the header Dec 2, 2021
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 December 2, 2021 09:57 Inactive
<nav aria-label="{{ params.navigationLabel | default('Menu') }}">
<button type="button" class="govuk-header__menu-button govuk-js-header-toggle" aria-controls="navigation" aria-label="{{ params.menuButtonLabel | default('Show or hide menu') }}">Menu</button>

<ul id="navigation" class="govuk-header__navigation {{ params.navigationClasses if params.navigationClasses }}" >
Copy link
Contributor Author

@36degrees 36degrees Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left the govuk-header__navigation class and any other passed navigationClasses on the <ul>. There's an argument for moving them to the <nav> as well, but I tried to make the minimum set of changes to fix the issue. Happy to revisit though – it does seem odd to have the govuk-header__navigation element class not on the <nav>.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, tricky 🤔 Like you said, it seems a bit odd to be applying them to the <ul>. But I'm also not sure what people are using the navigationClasses for, which makes it difficult to know if they'd expect/find it useful for them to be applied to the <ul> or the <nav>. If we move it to the <nav> element, will we also need to provide a way for people to pass classes to the <ul>?

I'm not sure if we can separate the two - move the govuk-header__navigation class to the <nav> but keep the navigationClasses on the <ul>? Perhaps that's even more confusing though.

Copy link
Contributor Author

@36degrees 36degrees Dec 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it'd make sense to keep the two together.

Arguments for keeping govuk-header__navigation and navigationClasses on the <ul>:

  • Preserves existing behaviour
  • We don't know what people are using navigationClasses for, so it's hard to reason about what impact the change would have

Arguments for moving govuk-header__navigation and navigationClasses to the <nav>:

  • Seems more 'correct' / what users would expect
  • Users can still style the list if they need to by passing e.g. app-header__navigation as a navigationClass and then using .app-header__navigation ul to target it, but without this change would have no equivalent way to style the nav
  • We could make it possible to add classes to the <ul> by introducing a new param, without having to make a breaking change
  • If we didn't do this and later wanted to make it possible to style the <nav> we'd have to introduce a new param with a suboptimal name (e.g. navigationWrapperClasses) or come back and make this (breaking) change

Have I missed anything?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for summarising, @36degrees, that's really helpful! I don't think you've missed anything. It's a really good point about being able to style the <ul> by using the navigationClasses but not being able to do it the other way around - I think that's convinced me that we should make the change. I think we might need to provide some additional guidance or examples somewhere to help people make the change though, maybe in the Changelog

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think I've talked myself into it too. Will push a commit…

@36degrees 36degrees marked this pull request as ready for review December 2, 2021 09:59
CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
Copy link
Contributor

@EoinShaughnessy EoinShaughnessy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update's looking good! Few small suggestions.

@36degrees 36degrees changed the title Improvements to the screen reader experience for the menu in the header Improve the screen reader experience for the header menu Dec 2, 2021
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 December 2, 2021 17:20 Inactive
Co-authored-by: EoinShaughnessy <72507742+EoinShaughnessy@users.noreply.github.com>
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 December 3, 2021 11:30 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 December 3, 2021 14:53 Inactive
@vanitabarrett
Copy link
Contributor

This change looks really good! Think we just need to add something to the Changelog about the classes change?

Move the `govuk-header__navigation` class and any additional classes provided by the `navigationClasses` param to the `<nav>` element rather than the list.

Create a new `govuk-header__navigation-list` for the list, and move the CSS properties that reset the user-agent default list styles and the properties that show and hide the list to this new class.

The `--open` modifier class is now applied to the list (the nav itself now contains the menu button is always visible) so rename it so that it's clear it's applied to the list rather than the nav.

We're making this change because it's more 'correct' and less 'surprising' – users would logically expect the `navigation` BEM element and the `navigationClasses` to be applied to the nav element itself.

There may be a need to allow users to pass classes to apply to the list – but we can do that if and when it comes up. In the meantime, users will still be able to style the list by passing a class `navigationClasses` and targeting the `ul` as a descendant.
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2427 December 3, 2021 16:49 Inactive
@36degrees
Copy link
Contributor Author

Think we just need to add something to the Changelog about the classes change?

I've added a section to the changelog entry which I think should cover it?

Any additional classes passed using the navigationClasses Nunjucks option are now applied to the <nav> rather than the <ul>. Check that the additional classes are still doing what you expect.

@36degrees
Copy link
Contributor Author

36degrees commented Dec 3, 2021

@EoinShaughnessy are you happy with that latest addition to the release notes?

Happy for this to be merged once Eoin has reviewed.

Copy link
Contributor

@EoinShaughnessy EoinShaughnessy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@vanitabarrett vanitabarrett merged commit c558ad1 into main Dec 6, 2021
@vanitabarrett vanitabarrett deleted the header-navigation branch December 6, 2021 12:45
@vanitabarrett vanitabarrett mentioned this pull request Dec 15, 2021
andymantell added a commit to surevine/govuk-react-jsx that referenced this pull request Jan 29, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 7, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 8, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 16, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 16, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 26, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 26, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Sep 28, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Oct 7, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Oct 7, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Oct 10, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Oct 10, 2022
peteryates added a commit to DFE-Digital/early-careers-framework that referenced this pull request Oct 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HTML validation error: 'Possible misuse of aria-label' in header
5 participants