Documentation versions (currently viewingVaadin 24)

Shadow DOM Styling of Components

Details and instructions on isolating JavaScript and CSS from the surrounding page.

Vaadin components use a native HTML feature called Shadow DOM which isolates their JavaScript and CSS from the surrounding page. This helps simplify the internal scripting and styling of the components. It also means that traditional, global, or page-level CSS doesn’t affect the elements inside the components. Instead, shadow parts and style properties are used to expose many of these internal elements and styles for customization.

HTML structure of a component
HTML Structure of a Component with Shadow DOM on Gray Background

In some cases, these recommended and officially supported approaches may be insufficient. For example, if there’s a need to customize the styling of an element that is not exposed as a shadow part, the ::part() selector won’t be of any use. The Vaadin platform provides a mechanism for this by allowing developers to inject CSS into the Shadow DOM of Vaadin components.

Shadow DOM Style Injection Not Recommended

Although mechanisms for injecting custom styles into the Shadow DOM of Vaadin components is still supported, this is no longer the recommended approach to styling. See Styling Vaadin Components for a description of the recommended way to style components.

Stylesheets placed in a sub-folder called components, inside the application theme folder, and named according to the root HTML element of components, are automatically injected into the Shadow DOM of those components. In the example below, the components folder contains Shadow DOM stylesheets for Text Field and Dialog:

[project root]
└── frontend
    └── themes
        └── my-theme
            └── components
                ├── vaadin-text-field.css
                └── vaadin-dialog-overlay.css
Disable Pre-Compiled Frontend Bundle

The loading of shadow DOM stylesheets from the components sub-folder isn’t compatible with the pre-compiled frontend bundle. To use this mechanism for loading shadow DOM styles, you need to disable the pre-compiled bundle.

Don’t add imports for Shadow DOM stylesheets.
Shadow DOM stylesheets placed in the components folder are loaded automatically into components with matching names. You shouldn’t use @import in styles.css or @CssImport annotations in your Java code to import these stylesheets.

Writing CSS for Shadow DOM Stylesheets

Shadow DOM stylesheets are regular stylesheets, with a few Shadow DOM-specific CSS peculiarities:

  • :host() denotes the root element of the component. Additional selectors like class names and attributes are placed inside the parenthesis (e.g., :host([focused]) and :host(.special))

  • ::slotted() denotes child elements located outside the Shadow DOM, but rendered as child elements of a Shadow DOM element through the slot feature. Additional elements, class and attribute selectors can be placed inside the parenthesis (e.g., ::slotted(span)).

  • There’s no way to style a Shadow DOM element based on a parent element of the component.

The DOM inspector feature in the developer tools of web browsers can be used to inspect the DOM structure of Vaadin components and identify the elements to target with Shadow DOM stylesheets.

Note that the Shadow DOM structure is subject to change in later versions. The internal structure of Vaadin components may need to change in later versions to enable new features, improve accessibility, or as part of bug fixes. This is likely to affect Shadow DOM CSS which targets elements by means other than part attributes. Shadow DOM styling is inherently less future-proof than the recommended styling approaches.