Search code examples
javascripthtmldomhtml5-videostandards

Is HTMLMediaElement.muted = true portable?


I tried to mute an audio, only to find out setAttribute doesn't work at all under Firefox 80.0.1 and Chrome 85.0.4183.102. As far as I know, that's the standard way of setting a boolean attribute.

video.setAttribute("muted", "muted");

Surprisingly, video.muted = true works. I'm not sure if it's even portable, since it's not using a standard function SetAttribute, and the value is not the canonical copy of muted.


Solution

  • The muted attribute maps to the .defaultMuted IDL, not directly to the .muted property.

    The .muted property is first set to this .defaulMuted value, but afterwards changing the .defaultMuted value won't change the .muted value.

    This means that at parsing, the attribute will set the initial value of .muted, but then, changing the attribute won't.

    const vid = document.getElementById("vid");
    console.log( "defaultMuted:", vid.defaultMuted ); // true (because it has the attribute)
    vid.removeAttribute( "muted" ); // set defaultMuted to false
    console.log("### removed Attribute");
    console.log( "has attribute:", vid.getAttribute( "muted" ) !== null );
    console.log( "defaultMuted:", vid.defaultMuted ); // false (no attribute anymore)
    console.log( "muted:", vid.muted ); // true (still muted anyway)
    vid.defaultMuted = true; // set back the attribute through IDL
    console.log("### set defaultMuted to true");
    console.log( "has attribute:", vid.getAttribute( "muted" ) !== null ); // "" (which is a truthy value for booleans, would have been `null` if unset)
    <video controls id="vid" muted></video>

    The correct way to mute/unmute an HTMLMediaElement dynamically is indeed through its .muted property, but this won't set any attribute on the element.