Documentation versions (currently viewingVaadin 24)

Shadow DOM Styling of Components

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 do not 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 is a need to customize the styling of an element that is not exposed as a shadow part, the ::part() selector will not 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 CSS injection not recommended

Although mechanisms for injecting custom CSS 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

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 (for example, :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 element, class and attribute selectors can be placed inside the parenthesis (for example ::slotted(span)).

  • There is 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.

Shadow DOM structure is subject to change in later versions

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