https://jakearchibald.com/2024/attributes-vs-properties/ Jake Archibald wrote...who? HTML attributes vs DOM properties Posted 24 April 2024 Attributes and properties are fundamentally different things. You can have an attribute and property of the same name set to different values. For example:
...
It seems like fewer and fewer developers know this, partially thanks to frameworks: If you do the above in a framework's templating language, you're using attribute-like syntax, but under the hood it'll sometimes be setting the property instead, and when it does that differs from framework to framework. In some cases, it'll set a property and an attribute as a side-effect, but that isn't the framework's fault. Most of the time, these distinctions don't matter. I think it's good that developers can have a long and happy career without caring about the differences between properties and attributes. But, if you need to dig down into the DOM at a lower level, it helps to know. Even if you feel you know the difference, maybe I'll touch on a couple of details you hadn't considered. So let's dig in... The key differences Before we get to the interesting stuff, let's get some of the technical differences out of the way: HTML serialisation Attributes serialise to HTML, whereas properties don't: const div = document.createElement('div'); div.setAttribute('foo', 'bar'); div.hello = 'world'; console.log(div.outerHTML); // '
' So when you're looking at the elements panel in browser developer tools, you're only seeing attributes on elements, not properties. Value types In order to work in the serialised format, attribute values are always strings, whereas properties can be any type: const div = document.createElement('div'); const obj = { foo: 'bar' }; div.setAttribute('foo', obj); console.log(typeof div.getAttribute('foo')); // 'string' console.log(div.getAttribute('foo')); // '[object Object]' div.hello = obj; console.log(typeof div.hello); // 'object' console.log(div.hello); // { foo: 'bar' } Case sensitivity Attribute names are case-insensitive, whereas property names are case-sensitive.
However, attribute values are case-sensitive. Ok, here's where things start to get blurry: Reflection Take a look at this:
This seems to contradict the first example in the post, but the above only works because Element has an id getter & setter that 'reflects' the id attribute. When a property reflects an attribute, the attribute is the source of the data. When you set the property, it's updating the attribute. When you read from the property, it's reading the attribute. For convenience, most specs will create a property equivalent for every defined attribute. It didn't work in the example at the start of the article, because foo isn't a spec-defined attribute, so there isn't a spec-defined foo property that reflects it. Here's the spec for
    . The "Content attributes" section defines the attributes, and the "DOM interface" defines the properties. If you click on reversed in the DOM interface, it takes you to this: The reversed and type IDL attributes must reflect the respective content attributes of the same name. But not all of these reflectors are as simple as these. Naming differences Ok, this is relatively minor, but sometimes the property has a different name to the attribute it reflects. In some cases it's just to add the kind of casing you'd expect from a property: * On , el.crossOrigin reflects the crossorigin attribute. * On all elements, el.ariaLabel reflects the aria-label attribute (the aria reflectors became cross browser in late 2023. Before that you could only use the attributes). In some cases, names had to be changed due to old JavaScript reserved words: * On all elements, el.className reflects the class attribute. * On