muted Set via JS PropertyBug (ENG-1727): Access Engine tests 17 and 39 (autoplaying media must not produce sound — WCAG 1.4.2 Audio Control) decided "is this element muted?" by reading the HTML muted attribute only. When a page mutes media via the JavaScript IDL property (videoEl.muted = true), no muted attribute is added to the DOM. The engine saw no attribute, assumed the media was audible, and produced a false-positive autoplay violation even though the media was actually silent.
Impact: False positives on autoplay media that is muted via JavaScript — background hero videos, JS-driven video players, and framework-bound media all reported audio-control failures despite playing no sound.
<video autoplay> / <audio autoplay>) must not produce sound automatically — it must be muted, not autoplay, or expose a control.muted content attribute reflects the initial (default) muted state only. The IDL .muted property reflects the live state and does not serialize back to an attribute when changed.muted content attribute or its live .muted IDL property is true. The fix adds the live-property read on top of the pre-existing attribute check. (Note: .volume === 0 is not consulted — the engine has no volume heuristic.)autoplay (user must press play) is out of scope for tests 17/39.player.muted = true through their API rather than setting the attribute.muted as a property, which never reaches the serialized DOM attribute..muted IDL property (not just the serialized muted attribute). When an element is muted via the property but has no muted attribute, stamp a marker attribute the test selectors can exclude:
if (n.muted === true && !n.hasAttribute("muted")) { n.setAttribute("data-ae_muted", "true"); }
video:not([muted]):not([data-ae_muted])[autoplay][data-ae_ar="null"][data-ae_vis]
.muted property is true, regardless of whether a muted attribute is serialized in the DOM. There is no .volume check — the engine does not consult volume.
autoplay — user must press play no autoplayNo autoplay, so playback is user-initiated. Tests 17/39 apply only to auto-playing media. Should not be flagged.
autoplay — user must press play no autoplayNo autoplay means no automatic sound. Out of scope for tests 17/39. Should not be flagged.
autoplay video with display:none, NOT muted hidden(Media element is present but hidden via display:none.)
Arguably a real WCAG 1.4.2 issue — display:none does not silence audio — but tests 17/39 only evaluate visible media: the base selector requires [data-ae_vis], and a display:none element is marked data-ae_invis instead. The engine therefore reports N/A (out of scope as not visible), not a flag, regardless of mute state.
<video autoplay muted> muted via ATTRIBUTE (control) attr mutedMuted via the serialized muted attribute. Worked before and after the fix. Should not be flagged.
<video autoplay> WITHOUT muted attribute, .muted = true set by JS JS mutedNo muted attribute in the DOM, but the live .muted IDL property is true. Pre-fix this was a false positive; post-fix the engine reads .muted and does not flag it.
<audio autoplay> muted via JS .muted = true property JS mutedAutoplay audio with no muted attribute but .muted === true after JS runs. Post-fix the effective muted state is honored. Should not be flagged.
<video> with both muted attribute AND JS .muted = true (belt-and-braces) attr + JS mutedAttribute present and property re-set to true in JS — fully silent. Should not be flagged either way.
<video autoplay> with sound — not muted at all audibleAutoplay with no muting via the muted attribute or the .muted property. Genuine WCAG 1.4.2 violation. Correctly flagged by tests 17/39 — the fix must not suppress this.
<audio autoplay> unmuted audibleAutoplaying audio with no mute and no control to stop it pre-emptively. Genuine violation. Correctly flagged.
<video autoplay muted> whose JS later sets .muted = false (now audible) attr muted, JS unmutesKnown false negative — NOT addressed by ENG-1727. The muted attribute is present in the DOM, so the tests 17/39 selector :not([muted]) excludes the element and the engine reports N/A — even though JS has flipped the live .muted property to false and the media is actually audible. The ENG-1727 fix only adds a data-ae_muted marker when .muted === true && !hasAttribute("muted"); it never reads .muted === false to override a present muted attribute. Catching this (attribute present, property false) is the opposite-direction problem and remains out of scope.
muted attribute ABSENT JS mutedPre-fix: flagged ❌ (engine saw no muted attribute). Post-fix: not flagged ✓ (engine reads .muted === true). This is the core ENG-1727 case.
muted attribute ABSENT JS mutedPre-fix: flagged ❌. Post-fix: not flagged ✓. Test 39 audio equivalent of the false positive.
Common framework/hero pattern: el.muted = true applied after mount, no muted attribute serialized. Pre-fix: false positive ❌. Post-fix: not flagged ✓.
player.muted = true) JS mutedPlayer libraries mute through the IDL property, never the attribute. Pre-fix: every slide a false positive ❌. Post-fix: not flagged ✓.