Visitar URL original
USWDS - Character Count: Defer aria-live to prevent iOS VoiceOver announcement on page load by daresTheDevil · Pull Request #6595 · uswds/uswds · GitHub
Skip to content

USWDS - Character Count: Defer aria-live to prevent iOS VoiceOver announcement on page load - #6595

Merged
ethangardner merged 11 commits into
uswds:developfrom
daresTheDevil:fix/character-count-aria-live-6541
Jun 18, 2026
Merged

ethangardner merged 11 commits into
uswds:developfrom
daresTheDevil:fix/character-count-aria-live-6541

Conversation

@daresTheDevil

Copy link
Copy Markdown
Contributor

Summary

Deferred the aria-live attribute on character count status messages so iOS VoiceOver doesn't announce them on page load.

Breaking change

This is not a breaking change.

Related issue

Closes #6541

Related pull requests

None.

Problem statement

When a page with character count inputs loads, iOS VoiceOver immediately announces the status messages ("25 characters allowed", "50 characters allowed") before the user has done anything. Browsers treat the initial content of a newly-inserted aria-live region as a live update, so VoiceOver reads it out loud on mount.

This affects every iOS VoiceOver user who lands on a page with character count components. It's confusing and noisy -- you hear counts for inputs you haven't touched yet.

Solution

Defer setting aria-live="polite" by 100ms after the status message element is inserted into the DOM. The element gets appended first, then the live region attribute is added after the delay. By the time aria-live is present, the browser no longer treats the existing content as a new update.

This is the same approach @mfairchild365 suggested in the issue. Simple, no side effects. Live updates still fire normally during typing since aria-live is in place well before any user interaction.

Major changes

  • packages/usa-character-count/src/index.js: Wrapped setAttribute("aria-live", "polite") in a setTimeout with 100ms delay inside createStatusMessages.

Testing and review

  • Verified on iPhone 16 Pro Max, iOS 26.4, Safari with VoiceOver. No announcement on page load. Live updates still work during typing.
  • Added two tests: one confirming aria-live is not set synchronously, one confirming it's present after the delay.
  • All existing character count tests pass (44/44).

daresTheDevil and others added 2 commits March 26, 2026 22:23
…cement on init

Browsers treat the initial content of a newly-inserted aria-live region
as a live update. On iOS VoiceOver, this causes the character count
message to be announced immediately on page load before any user input.

Deferring the aria-live attribute by 100ms after DOM insertion prevents
the false announcement while preserving live updates during typing.

Closes uswds#6541
@annepetersen annepetersen added Affects: Accessibility 🟡 Affects access for disabled users or assistive tech. Record the barrier; not a severity score. Needs: Confirmation Reported behavior needs validation. Remove after recording reproduction or investigation results. Role: Dev Dev expertise is relevant. Project Active Role tracks ownership; this label is not an assignment. Package: Character count Work affecting Character count. Apply only when this area helps route or find the issue. Role: A11Y A11Y expertise is relevant. Project Active Role tracks ownership; this label is not an assignment. Affects: Markup 🟡 Suggestion would change the markup of a component labels Mar 30, 2026

@ethangardner ethangardner left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@chandracarney - Code-wise this looks fine to me, but I'd like to defer to you on the screen reader behavior.

@chandracarney

Copy link
Copy Markdown
Contributor

Thanks for this contribution @daresTheDevil. We've been sorting out a lot of logistics, including testing. I'm going to tag in @jonathanbobel as a reviewer, then hopefully can get this merged soon!

@chandracarney
chandracarney requested review from jonathanbobel and removed request for chandracarney June 4, 2026 19:51

@jonathanbobel jonathanbobel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is an acceptable solution to this issue. 🚀

@jerseycheese

jerseycheese commented Jun 10, 2026 •

Copy link
Copy Markdown

Confirmed on iPhone 16 Pro, iOS 26.5 (Safari + VoiceOver): on page load VoiceOver announces the status message ("You can enter up to 25 characters") on its own, before any interaction, so the bug reproduces.

Worth flagging for anyone else confirming: it's load-timing-sensitive. It reproduces on a real page that initializes on DOMContentLoaded (and on the live docs site), but not in the Storybook story, where init runs inside a requestAnimationFrame and the live region lands at a different point relative to VoiceOver's page snapshot. So confirm against a real page load, not the story.

This PR resolves it on my device.. silent on load, and still announces the count while typing.

@chandracarney

Copy link
Copy Markdown
Contributor

Thanks for the review and confirmation, @jonathanbobel and @jerseycheese! 🚀

@ethangardner
ethangardner merged commit 23ab001 into uswds:develop Jun 18, 2026
5 checks passed
@chandracarney chandracarney removed the Needs: Confirmation Reported behavior needs validation. Remove after recording reproduction or investigation results. label Jun 18, 2026
@chandracarney chandracarney moved this from Fed Final Review to Done in USWDS Core Project Data Jul 20, 2026
@ethangardner ethangardner added this to the uswds 3.14.0 - Aug 2026 milestone Aug 4, 2026
@annepetersen annepetersen added the ❤️ Thanks Historical appreciation marker. Prefer a reaction; not required for triage. label Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Affects: Accessibility 🟡 Affects access for disabled users or assistive tech. Record the barrier; not a severity score. Affects: Markup 🟡 Suggestion would change the markup of a component Package: Character count Work affecting Character count. Apply only when this area helps route or find the issue. Role: A11Y A11Y expertise is relevant. Project Active Role tracks ownership; this label is not an assignment. Role: Dev Dev expertise is relevant. Project Active Role tracks ownership; this label is not an assignment. ❤️ Thanks Historical appreciation marker. Prefer a reaction; not required for triage.

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

USWDS - Bug: Character Count announced on component render on iOS VoiceOver

6 participants