javascripthtmlcsspseudo-elementcustom-element

Why does CSS ::part override JavaScript element.style?


I have an HTML custom element that inherits from HTMLElement. The template contains:

<input type="text" part="input"/>

Sample CSS:

  my-element::part(input) {
    padding-right: 1px;
  }

Sample JavaScript (inside class MyElement {}):

  this.input.style.paddingRight = "25px";

The Style inspector in DevTools (Rules in Firefox) crosses out the ::part declaration for padding-right and shows:

  element.style {
    padding-right:25px;
  }

But the computed value inspector shows padding-right:1px and it's rendered as 1px.

The JS code is running after the page fully loads. I don't see a straightforward way around this behavior. If I modify a CSS property for this element in JS, then I cannot declare it CSS. At least not with padding.

Why does a pseudo-element of the custom element take precedence over the element's own style?

The fact that the Style/Rules inspector disagrees with the Computed inspector makes me think this is a bug in both browsers, but I'm no expert. I have not yet tried this on browserstack to check other platforms. Right now I'm focused on working around this unexpected behavior.

It's a bit of work to create a working demo snippet, and the behavior is the same across Firefox and Chrome in Win11, so I'll wait until someone requests it.


Solution

  • The ::part pseudo-element works in conjunction with browser rendering layers and the cascade order of styles. To fix this you can force higher specificity in JavaScript code:

    this.input.style.setProperty('padding-right', '25px', 'important');
    

    This code will ensure that the inline style with !important takes precedence over the ::part pseudo-element styles.