Day 60: the ::part() pseudo-element

posted on

It’s time to get me up to speed with modern CSS. There’s so much new in CSS that I know too little about. To change that I’ve started #100DaysOfMoreOrLessModernCSS. Why more or less modern CSS? Because some topics will be about cutting-edge features, while other stuff has been around for quite a while already, but I just have little to no experience with it.


You can use the ::part CSS pseudo-element to style an element within a shadow tree.

Let's have a look at the following web component.

There's a heading and a paragraph in the shadow DOM and we can pass content via light DOM.

class NewsTeasers extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = `
      <h3>Latest news</h3>
      <p>Here's a selection of our latest blog posts.</p>
      <slot></slot>
      `
  }
}

customElements.define('news-teasers', NewsTeasers);
<news-teasers>
  <ol>
    <li><a href="#1">Blog post 1</a></li>
    <li><a href="#2">Blog post 2</a></li>
    <li><a href="#3">Blog post 3</a></li>
    <li><a href="#4">Blog post 4</a></li>
  </ol>
</news-teasers>
  1. Blog post 1
  2. Blog post 2
  3. Blog post 3
  4. Blog post 4

Sometimes it's desirable to allow authors to style web components from the outside. I've written about our options on day 10, day 18, and day 28. In summary, we can style the element itself, we can change inheritable properties, and we can style elements in light DOM.

/* the element itself */
news-teasers {
  border: 8px dashed;
}

/* inheritable properties */
news-teasers {
  color: green;
}

/* light DOM */
news-teasers ol {
  border: 4px dotted;
}

If we try to style elements in the shadow DOM, we're out of luck. We don't have access to them from the outside.

/* shadow DOM */
news-teasers h3 {
  font-size: 2rem;
}

news-teasers p {
  background-color: #000;
  color: #fff;
}

This is where [part] and ::part come into play. The part attribute exposes an element outside of the shadow tree and the ::part() pseudo-element allows you to select the exposed element.

class NewsTeasers extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = `
      <h3 part="heading">Latest news</h3>
      <p part="intro">Here's a selection of our latest blog posts.</p>
      <slot></slot>
      `
  }
}

customElements.define('news-teasers', NewsTeasers);
/* exposed parts from the shadow DOM */
news-teasers::part(heading) {
  font-size: 2rem;
}

news-teasers::part(intro) {
  background-color: #000;
  color: #fff;
}

See on CodePen

Further reading

Overview: 100 Days Of More Or Less Modern CSS