Why should HTML DOM properties be reflected into HTML DOM attributes as well?


It's said by this article that one of the important reasons for HTML properties to be reflected back to the DOM is because CSS selectors rely on attributes, but why's that? This could be done without the reflection based on the spec.

For people who don't know what I'm talking about, read below:

In browsers, CSS selectors rely on attributes to work.

#myButton[someAttribute] {
  opacity: 0.5; 
  font-weight: bold
}

So in our JavaScript if we change the property of an element, eventually we have to reflect it to the HTML DOM as well like this:

// we have changed some property
myButton.someAttribute= true; 

// but this is not adequate, we need to reflect as well
myButton.setAttribute('someAttribute', '');

so we get this:

<button id="myButton" someAttribute></button>

not this non-reflected button:

<button id="myButton"></button>

Not all DOM properties map to attributes. The ones that do reflect to and from attributes, do so to maintain parity with the document language — in this case, HTML, which only has a concept of attributes, which as you've correctly pointed out is relied on by Selectors.

If attribute selectors mapped directly to DOM properties without the DOM discriminating between attribute properties and other kinds of properties, then attribute selectors such as the following would match, even though none of these exist as attributes in HTML:

[classList]
[className]
[dataset]
[offsetLeft]
[offsetTop]
[offsetWidth]
[offsetHeight]

... as well as [someAttribute] matching elements with your non-existent someAttribute as a property even when you don't reflect it with setAttribute().

In fact, this is exactly why label[htmlFor] incorrectly matches label[for] elements in Internet Explorer 7, even though the for attribute in HTML is simply called for, not htmlFor — the DOM uses htmlFor to make up for the fact that for is a reserved word in many languages including JavaScript, the main DOM scripting language, preventing it from being used as a property ident.


DOM attributes and properties are not equivalent, but they're related.

Attributes are intended to be used to initialize DOM properties. When the HTML is parsed, all the attributes are used to initialize the corresponding DOM properties. If you later modify an attribute with setAttribute or removeAttribute, the corresponding property is also updated (similar to reloading the HTML with the new attribute).

But it doesn't go the other way. Updating a property doesn't change the corresponding attribute. This is why you can assign to the .value of an input, and see this reflected in the browser display, but when you look at the element in Developer Tools you still see the original value="whatever" attribute. In some cases this has special benefits -- when you click on the Reset button of a form, it resets all the value properties from their value attributes.


IMHO; Some attributes have a 1:1 mapping with their respective properties in the DOM. The reflection is automatically made for common attributes like id. You can also define your own attributes (your HTML will be considered invalid, but you can use the doctype to validate them). My guess is that due to this uncertainty created by rogue attributes. They preferred to map only the attribute:property which has predictable behaviour and usage. You can still use your custom attributes in your css but you're in manual mode. You got to keep your s**t together and reflect them yourself. This far west(freedom) mentality is one the things that made web tech so popular and easy to use. You can do things as you see fit. I do not recommend it for maintainability reasons but you could.


Your example uses a button, but the article is using the disabled property but with something other than a button. On a button, the browser will automatically reflect changes to the disabled property onto the attribute, and vice versa, but this doesn't happen with all elements. Change your example to use a div and you'll see that you'd need to manually coordinate the two if desired.

Or for custom attributes, use data- attributes instead. If you delete the property from my_element.dataset, I'm pretty sure the attribute will be deleted too.


This is to keep the HTML and DOM synchronized, because at some point CSS selectors will be checking the DOM element and relying on the attributes to be accurate.

If the DOM isn't accurate, then the CSS won't be accurate either. What if HTML didn't bother to reflect attributes back to the DOM?

Let's say the text of an input field is initially black, and you want the text to be red when it is disabled. Now let's say the user did something and a function you wrote disabled the input field through javascript.

If HTML didn't reflect that 'disabled' attribute back to the DOM, CSS would NEVER KNOW that the element was disabled.

So the text color would never be changed to red. Remember, CSS checks and relies on DOM attributes. If HTML doesn't change the DOM attributes, for all CSS cares about, nothing has changed so everything will remain the same.

For a less technical analogy, let's say CSS is Batman, HTML is Gotham Police Department, an Attribute is the bat-signal, and the DOM is the sky.

Batman(css) constantly checks the sky(dom) to see if his bat-signal light(attribute) is being shown by the Gotham Police Department(html). If there was some event(an attribute changed) which happened in Gotham where the Gotham Police Department(html) needed Batman(css) to help, but they just didn't bother to send him an update through the sky(dom) with the bat-signal(attribute update), Batman would never know there was a job that needs to be done.

I mean he's an awesome super hero so he would eventually find out but sadly, CSS is no Batman.


The article speaks about custom elements, and takes the example of a <div> element with it's natural behaviour for some properties like hidden or disabled.

So, first of all, don't take the sentence you mention as a directive from your god, because it's not.

Simply, if you have an application with some css using the disasbled property for specific styling, be aware that, if you want to :

  1. create some custom elements
  2. manipulate their attributes through Javascript, including disasbled
  3. see the css applied for disasbled property of custom elements you are manipulating

Then, yes, you'll need to reflect back to DOM


Well, this is the first question I'm answering but I'll try either way.

To be honest, it's kinda hard to tell what you're asking but if you're looking to reflect HTMLElement property changes back on the DOM (via attributes). Then here's the code (using HTMLElement's):

// Defines a new property on an Object.
Object.defineProperty(HTMLElement.prototype, "someAttribute", {
    // Configurable
    configurable: true,

    // Enumerable
    enumerable: true,

    /* Getter
        (Allows you get the value like this =>
            element.someAttribute // returns the value of "someAttribute"
        )
    */
    get: function() {
        return this.getAttribute("someAttribute")
    },

    /* Setter
        (Allows you to modify/ update the value like this => 
            element.someAttribute = "lorem ipsum"
        )
    */
    set: function(data) {
        this.setAttribute("someAttribute", data)
    }
})

Hope this answered your question.