The default block template used for menu blocks includes some accessibility enhancements so that the menu is semantically treated as a navigation landmark for screen readers and is labeled appropriately based on the title of the block:
{% set heading_id = attributes.id ~ '-menu'|clean_id %}
<nav role="navigation" aria-labelledby="{{ heading_id }}"{{ attributes|without('role', 'aria-labelledby') }}>
{# Label. If not displayed, we still provide it for screen readers. #}
{% if not configuration.label_display %}
{% set title_attributes = title_attributes.addClass('visually-hidden') %}
{% endif %}
{{ title_prefix }}
<h2{{ title_attributes.setAttribute('id', heading_id) }}>{{ configuration.label }}</h2>
{{ title_suffix }}
{# Menu. #}
{% block content %}
{{ content }}
{% endblock %}
</nav>
The labeling part is sort of broken when the block is placed using Layout Builder and will cause issues if there's more than one menu output on the page. This is because the label of the block is assigned to the navigation landmark using an HTML ID, but the HTML ID is not set by Layout Builder. If instead the block is output using the block placement UI, the ID is set thanks to BlockViewBuilder.
So for Layout Builder, the template will include markup like this:
<nav role="navigation" aria-labelledby="-menu" data-block-plugin-id="menu_block:ps-utility-menu" class="block block-menu navigation menu--ps-utility-menu">
<h2 id="-menu">Utility menu</h2>
...
</nav>
The ID is not unique anymore. Any additional menu blocks on the page will have the same "-menu" ID and screen readers won't handle this well.
I don't think layout builder should assign an ID attribute for every block, but it seems like in the case of menu blocks it needs to, since the menu block template assumes it is set.
Comments
Comment #2
bkosborneThis is also probably blocked on #3072231: Custom blocks break layout builder module - Quick Edit could not associate the rendered entity field markup
Comment #3
kunalkapoor CreditAttribution: kunalkapoor as a volunteer and at OpenSense Labs commentedHi @bkosborne if you want an id of the block placed by layout builder you can use id="block-{{ elements.content['#block_content'].id() }}" this will give you a unique number for each block created by layout builder.
Comment #4
kunalkapoor CreditAttribution: kunalkapoor as a volunteer and at OpenSense Labs commentedid-"block-{{ elements.content['#block_content'].id() }}"
May be this can solve your problem
Comment #5
bkosborneIndeed, while this can be solved with template overrides, this can be fixed in out-of-the-box Drupal.
Comment #6
andrewmacpherson CreditAttribution: andrewmacpherson as a volunteer commentedThanks for filing this @bkosborne.
This is a bit vague. The actual problem lies with browsers, not screen readers. It's the browser's job to compute the accessible name of landmark regions; the screen reader just relays what it has been provided by the browser.
In practice, when an IDREF points to a non-unique ID, the first matching ID in the DOM order wins. The computed accessible names will be the same for all affected landmark regions, but only correct for one of them. To make matters worse, it's effectively random; we don't know what order the blocks have been placed in. If there is only one menu block placed by layout builder, this might not cause a problem at all.
Bumping to major, because it seriously confounds assistive tech users ability to understand the page structure or find what they need. Having incorrectly-named ARIA navigation landmarks is worse than having no accessible names at all. There are a bunch of relevant WCAG success criteria:
Note that an ID which begins with a hyphen was not valid under HTML 4 parsing rules, but is permitted by HTML 5. I don't know whether that makes any practical difference for actual browsers, but I'd suppose it's safer to stay clear of this situation.
Comment #7
andrewmacpherson CreditAttribution: andrewmacpherson as a volunteer commentedComment #8
mgiffordComment #9
mgiffordLinking open issues from the CivicActions Accessibility - VPAT.
Comment #11
kazah CreditAttribution: kazah commentedHello!
How do you use this
id-"block-{{ elements.content['#block_content'].id() }}"
Where do you put this code?
Comment #15
mgiffordComment #16
bensti CreditAttribution: bensti commentedwhat happen with this issues?
this is not only the menu block. all my block place with Layout builder dont have any ID. only a ugly class : block-block-content52048ada-f924-4fb5-a0a0-ccd02ca9ccc5
any solution?
Comment #18
DanielVezaThanks for raising an issue! In my opinion this is a duplicate issue of #3073895: System Menu blocks do not have attributes. That issue has an open MR and some further progress, so I'm closing this one as a duplicate.
Thanks!