Using CSS ::part to Style SVG Sub-Elements

Web Components encapsulate their internal markup inside a Shadow DOM, which inherently blocks external CSS stylesheets from modifying nested SVG shapes. By utilizing the HTML part attribute on internal SVG sub-elements (such as <path>, <circle>, or <g>) and targeting them with the CSS ::part() pseudo-element, developers can selectively expose specific styling hooks to outside stylesheets while maintaining DOM encapsulation.


The Problem: Shadow DOM Encapsulation and SVGs

When an SVG is embedded inside a Web Component’s Shadow Root, global styles cannot pierce the shadow boundary to adjust SVG presentation attributes like fill, stroke, or opacity. Traditional solutions like CSS Custom Properties (CSS variables) work for simple values, but they become cumbersome when managing complex SVG layouts with multiple interactive or themeable paths.

Exposing SVG Elements with the part Attribute

To make an internal SVG sub-element stylable from outside the component, assign a part attribute to the desired SVG tag inside the Shadow DOM template.

Web Component Template Example

<my-icon>
  #shadow-root (open)
    <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
      <circle part="background" cx="50" cy="50" r="45" />
      <path part="glyph" d="M30 50 L45 65 L70 35" />
    </svg>
</my-icon>

In this component: - The <circle> element is assigned part="background". - The <path> element is assigned part="glyph".

Styling the Exposed Parts via External CSS

External stylesheets can target these exposed sub-elements directly using the host selector combined with the ::part() pseudo-element:

/* Style the SVG background circle */
my-icon::part(background) {
  fill: #f0f4f8;
  stroke: #0070f3;
  stroke-width: 2px;
}

/* Style the inner glyph path */
my-icon::part(glyph) {
  fill: none;
  stroke: #0070f3;
  stroke-width: 4px;
  stroke-linecap: round;
}

/* Apply hover and state transitions externally */
my-icon:hover::part(background) {
  fill: #0070f3;
}

my-icon:hover::part(glyph) {
  stroke: #ffffff;
}

Supported CSS Properties for SVG Parts

When targeting SVG elements through ::part(), all standard SVG presentation attributes that map to CSS properties can be manipulated, including:

Nested Components and exportparts

If an SVG is located within a nested Web Component inside another Shadow DOM, you can forward the part to the outer context using the exportparts attribute:

<!-- Outer Component Shadow DOM -->
<nested-icon exportparts="glyph: icon-glyph, background"></nested-icon>

This allows the top-level document to access the internal SVG element using outer-component::part(icon-glyph).

Benefits of Using ::part for SVGs