webcomponents-cg
webcomponents-cg copied to clipboard
Isolating Props from Attributes in Custom Elements
When building Web Components, we often map HTML attributes directly to internal component properties. But as HTML evolves and introduces more native attributes (like size, color, variant, etc.), collisions are increasingly likely.
Consider this example:
<nn-pilar size="50% - 1rem"></nn-pilar>
Here, size is not currently a global attribute in HTML, but it could become one in the future. If it does, your component’s size prop might conflict with a native behavior, or lead to unexpected rendering quirks.
To avoid this, I’m exploring ways to clearly separate component props from native attributes.
Proposal: Use a namespaced attribute prefix for props
Instead of merging concepts like this:
<nn-pilar p-size="50% - 1rem"></nn-pilar>
Which still flattens the concept of "props" into a string key, I propose something more explicitly nested:
<nn-pilar p.size="50% - 1rem"></nn-pilar>
This form visually and semantically distinguishes component props from native attributes, and mirrors JavaScript object notation:
props: {
size: '50% - 1rem'
}
In JavaScript, you could then access these props with a method like:
this.getProp('size') // "50% - 1rem"
This approach:
- Prevents future naming collisions with HTML.
- Encourages clear mental models, where attributes like
p.sizeare clearly part of a namespaced prop system. - Keeps DOM clean, without overloading generic or ambiguous attributes.
Notes:
- While
p-sizeis valid HTML, dashes don’t convey nesting or ownership—they flatten the structure. Using.in attributes better reflects scoped data (e.g.,p.size,i18n.key,config.theme, etc.). - This mirrors the way many frameworks (Vue, React props, etc.) handle structured state or namespacing.