cssshadow-domnative-web-component

HTML `part` and `class` attributes – what's the difference?


HTML has recently been added a part attribute plus corresponding CSS selector.

What's the difference between part and class? What can I do with the part attribute that I can't archive using the class attribute?


Solution

  • ::part() is much more limited in a sense where you can only do compound selector (selecting element that contains the parts you specified). This is also part of the design decision to not expose the layer structures inside web component.

    In other words, if you are comparing it with normal CSS classes, the only type that it supports is: .class1 or .class1.class2. Even if you try to use ::part(parent)::part(children), it will not match .parent .children.

    By default, styles inside shadow DOM cannot be customised by outside of shadow tree unless you have some custom props / use JavaScript to workaround.

    However, with the use of part and ::part(), you can now override the styles of your Web Component. You can specifically specify which part of your Web Component (using part) that is intended to be override by the user.

    This is intended to be used for people who are using your component, not so much for your styling inside your Web Component. Example below illustrated the behaviour:

    window.customElements.define(
      'sample-component',
      class extends HTMLElement {
        constructor() {
          super()
            .attachShadow({ mode: 'open' })
            .append(document.getElementById('sample-component').content);
        }
      }
    );
    .component .name {
      text-decoration: underline; /* Not working as shadow DOM encapsulates the styling */
    }
    .component::part(name) {
      color: red; /* Working as you can now access it using ::part */
    }
    .component::part(contact number) {
      font-weight: bold; /* You cannot do child selector using part() */
    }
    .component::part(age number) {
      font-style: italic; /* You can do multiple parts selector (age AND number) */
    }
    <template id="sample-component">
      <style>
        .name {
          font-size: 24px;
        }
      </style>
      <div part="name" class="name">Name</div>
      <div part="age number">Age</div>
      <div part="contact">
        <div part="number">+1234567890</div>
      </div>
    </template>
    
    <sample-component class="component"></sample-component>