9

Today I learned that for boolean HTML attributes, they are considered true if they're present on the element at all, regardless of their value. And that as a rule, you should specify the empty string("") in value.

This wounds me on a logic level since everywhere else in JS, "" is false.

What.

The.

Fuck.

Seriously. Why?

Comments
  • 3
    Well the attribute exists....
  • 3
  • 1
    "" being false in JS isn't good here. From a language design perspective, strings coercing to a boolean seems weird.

    However in HTML, there is no consideration of "boolean", other than just "attribute". If it was specified, then it exists, and it can have an optional value associated with it.

    The philosophies are different and javascript. Javascript was borne out of a hack.
  • 2
    @koes Hilariously this realization occurred because I was trying to add the ability to pass something in for disabled on the autosuggest component I’ve been working on (you know, like disabled={country && country != “United States”} for a state dropdown) and when I went to write testing around it, I was passing disabled={true} and when I went to screen.debug() to see why the test was failing for expecting the input to have the attribute “disabled” and that value equal to true, it showed that input had disabled=“”.
  • 4
    HTML is a markup language and is void of logic. It doesn't get more declarative to make an input disabled than typing <input disabled>. It's the first time I hear adding empty "" is recommended, never had to do that and would argue the exact opposite especially for "attributes that are translated into boolean properties in the DOM".

    The fact <input disabled=""> still translates to input.disabled === true in JS is awkward, but with <input disabled> it makes all the sense in the world.

    For your usecase (dynamic values in disabled) I would not re-use the std. input attr but use data-disabled which translates to el.dataset.disabled and which you have full freedom to intrepret as you see fit.
  • 2
    @webketje I just find it fascinating that if you’re working with a JavaScript library like React and you add a literal boolean value to it, it turns it into an empty string, considering how empty strings are evaluated in JS. And that you can’t just check the value directly (node.disabled) but by using the hasAttribute function. Also, looking at the html spec for empty attributes, it looks like it’s implicitly an empty string. https://html.spec.whatwg.org/multip...
  • 2
    Yeah disabled gets me once in a while. I just kinda memorized that it is weird... not that it makes sense.
  • 0
    When you realize, that different languages are actually different...
  • 2
    It's more infuriating when you discover this after hours/days of debugging.
  • 1
    @GXGOW I can imagine!
  • 1
    @AmyShackles Yes it is implicitly an empty string because the spec declares "Attributes have a name and a value", but as per the spec https://html.spec.whatwg.org/multip... the value is meaningless as the mere presence/absence indicates its value for boolean attrs. <input disabled="whatever"> is actually invalid HTML (w3c validator will throw an error).

    Why couldn't you check "input.disabled"? It will return true / false, the only 2 valid DOM-translated values for boolean attrs. You'd never want to use hasAttribute to check for the value of a standard boolean attr..
  • 2
    Yeah, god @AmyShackles why didn't you? So easy.
    Why didn't you just do the thing?

    (/s)
  • 1
    @junon Lol, it was not meant in that tone.. I just find it interesting that @AmyShackles' frustration stems from using a JS loose type comparison for empty string ("" == false) as the model for how the DOM API should translate boolean HTML attrs, while it never struck me as being odd, so I suppose it is familiarity bias.
  • 2
    @webketje You misunderstood my original frustration. My original frustration was that the spec calls it a boolean. I passed it a literal boolean (true) and it converted it to an empty string, which evaluates to false in JavaScript. The frustration was more that I was unaware that this behavior existed and was thrown off by it - if for no other reason than I write primarily in JavaScript and feel I should have known this sooner.
Add Comment