Each row in a Likert element gets an aria-labelledby pointing at the row's question label (the fix from #3001852: likert radio buttons needs aria-labelledby attr for accessibility), but that's still the only thing wired up - every radio in the row ends up with the identical accessible name.
There's nothing tying an individual radio to its column ("Low" vs. "Medium" vs. "High").
Practical effect: a screen reader user tabbing through one row's radios (control-to-control, not cell-to-cell) hears the same question announced 5-6 times in a row with no way to tell which answer is which. Users who navigate the table cell-by-cell are fine, since the <td>'s own computed name does concatenate row + column — it's specifically the <input> that's missing it.
Steps to reproduce
- Create a webform with a Likert element, 2+ questions, 3+ scale options.
- Tab through one row's radios with a screen reader — control to control, not cell to cell.
- Every radio in the row announces the identical name.
Confirmed on 6.3.0. I also checked #3001852: likert radio buttons needs aria-labelledby attr for accessibility and #2982067: [accessibility] Elements must have labels. (includes select other, color, likert, multiple, and table select) but both are closed and already in this release, neither covers this. Row-only aria-labelledby needs to also pick up the column header so each radio's name is "{question} — {answer}", not just "{question}".
AI disclosure: Drafted with help from Claude Code while auditing my own site for accessibility issues.
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | 3621031 after.png | 985.38 KB | csakiistvan |
| #8 | 3621031 before.png | 714.95 KB | csakiistvan |
Issue fork webform-3621031
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
Comment #2
liam morlandComment #5
andres alvarez commentedConfirmed the root cause. Every radio in a Likert row sets
aria-labelledbyto only the row's question id (src/Element/WebformLikert.php, insideprocessWebformLikert()). Per the WAI-ARIA accessible-name algorithm,aria-labelledbyon a form control overrides its associated<label>entirely, so the per-radio visually-hidden answer text (already present in the markup, wrapped as a<label>) is never used for the accessible name. Every radio in a row ends up announcing the identical question text, regardless of which answer/column it represents.The fix gives each answer/column header cell a unique id (same
Html::getUniqueId()pattern already used for the question id) and has each radio'saria-labelledbyreference both the question id and its own column's header id, so the computed accessible name becomes "question answer" rather than "question" alone.Updated the functional test's hardcoded markup assertions and added an explicit assertion that two radios within the same question row resolve to different
aria-labelledbyvalues. Confirmed the new assertion fails against the unpatched code and passes with the fix.MR to follow.
Comment #6
andres alvarez commentedComment #7
csakiistvanComment #8
csakiistvan✅ Tested and works — applied MR !939 on top of 6.3.x (e0f2f213b), ran
drush crand reloaded a webform with a Likert element (2 questions, 3 answers): before the patch all three radios in a row carriedaria-labelledby="edit-satisfaction-table-q1-likert-question", after it each answer column header gets its ownidand every radio references question + its own column (...-q1-likert-question edit-satisfaction-table-header-2), so the radios in a row no longer share one accessible name.