Skip to content

CSS Parts — Complete Guide

DodaTech Updated 2026-06-28 1 min read

In this tutorial, you will learn about CSS Parts. We cover key concepts, practical examples, and best practices to help you master this topic.

CSS parts expose specific Shadow Dom elements for external styling, giving users controlled access to internal component elements without breaking Encapsulation.

What You'll Learn

  • How to expose shadow elements with the part attribute
  • How to style exposed parts with ::part()
  • How to use part hierarchies with ::part()
  • How part theming differs from CSS custom properties

Why It Matters

CSS custom properties are great for theming values, but they cannot target specific elements. CSS parts let users style the component's internal elements directly, like changing the icon size or the button padding.

flowchart LR
  A[Component] --> B[part=button]
  A --> C[part=icon]
  A --> D[part=label]
  E[External CSS] --> F[::part(button)]
  E --> G[::part(icon)]

Defining Parts

class SplitButton extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
            <style>
                .container { display: inline-flex; border-radius: 4px; overflow: hidden; }
                .main-btn { padding: 8px 16px; background: #3498db; color: white; border: none; cursor: pointer; }
                .toggle-btn { padding: 8px 12px; background: #2980b9; color: white; border: none; cursor: pointer; border-left: 1px solid rgba(255,255,255,0.3); }
            </style>
            <div class="container">
                <button part="main-button" class="main-btn"><slot></slot></button>
                <button part="toggle-button" class="toggle-btn">\u25BC</button>
            </div>
        `;
    }
}
customElements.define('split-button', SplitButton);

Styling Parts

/* External CSS */
split-button::part(main-button) {
    background: #e74c3c;
    font-weight: bold;
    text-transform: uppercase;
}

split-button::part(toggle-button) {
    background: #c0392b;
    font-size: 10px;
}

split-button::part(main-button):hover {
    background: #c0392b;
}

Part Hierarchies

class NestedPanel extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
            <my-card exportparts="header: card-header, body: card-body">
                <span slot="header">Panel Title</span>
                <p>Panel content</p>
            </my-card>
        `;
    }
}
customElements.define('nested-panel', NestedPanel);

Common Mistakes

  1. Exposing too many parts (breaks encapsulation)
  2. Not documenting available parts for users
  3. Using part names that conflict with other components

Practice Questions

  1. What attribute exposes an element for styling? The part attribute.
  2. How do nested components expose parts? Using the exportparts attribute.

Mini Project

Build a modal component with exposed parts for overlay, container, header, body, footer, and close button. Allow users to style each part independently.

What's Next

Lesson 13: CSS Theming

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro