One of the main benefits of the Valo theme is that it allows you to customize it to your needs. Because it’s based on Web Components and Polymer, the styling is done a bit differently than for a traditional web page.
The main difference is that Web Components use shadow DOM, which prevents you from styling the internals of the components with global CSS because a shadow DOM introduces its own style scope.
A style scope is a part of the DOM hierarhcy, where the styles placed inside it can only affect the elements inside that same part of the hiearchy.
The global scope is the default, and all external stylesheets (i.e.
<link rel="stylesheet">
) and <style>
elements placed in
the index.html
end up.
Each shadow DOM introduces their own style scope, and global styles will not affect the elements inside it. And vice-versa, styles inside a shadow DOM will not affect the elements in the global scope (or in other shadow DOMs).
For common use cases, Valo offers many built-in theme variations you can apply to individual component instances. For example, there is a “primary” theme for buttons, and a ”small” theme text-fields.
The built-in variations are applied using the theme
attribute, and they work
in any style scope:
The built-in variations are documented per component, including source code examples how to apply them. See Button’s color variations for example.
Read more about light and dark themes from the colors documentation.
Valo defines global and component specific CSS custom properties that you can use to make smaller adjustments to the theme.
The pages under the “Style guide” section (Colors for example) list the custom properties that affect all elements. Component specific custom properties are listed at the end of each component’s documentation page. See Button’s custom properties for example.
As an example, if you wish to adjust the border radius for all elements that are affected by
it, you can place the following code in the top level scope of you application (e.g.
index.html
):
Use the <custom-style>
element for
cross-browser compatility.
If you wish to adjust the border radius for vaadin-button
specifically, for example, you can
do the following:
This only works if the styles are placed in the same style scope as the buttons you want to style.
To work around this limitation, we can target the button specific
--valo-button-border-radius
custom property instead, and apply that in the
global scope:
When you can’t accomplish the styling you want using the CSS custom properties provided by the theme, and you want to style the internals of an element freely, you can create new theme modules to add low level CSS for any element.
A theme module is basically the same as a
Polymer style module,
with an additional theme-for
attribute.
The id
attribute of the theme module should be unique. You can also re-use an
existing id if you want to override a previously defined/imported module.
theme-for
attributeThe theme-for
attribute specifies the custom element (read: Web Component) that
the styles in the theme module will affect. The value can be a space separated list of element
names, and can contain wildcard element names as well.
Examples of valid theme-for
attribute values:
"vaadin-button"
"vaadin-overlay vaadin-date-picker-overlay"
"vaadin-*"
The styles written inside a theme module are included in the elements shadow DOM. That means,
that in order to style the main element (a.k.a. the host element) you need to use the
:host
selector:
In addition to the :host
selector, the only other supported selectors inside a
theme module are ones that target the documented “shadow parts” (i.e. elements inside a shadow
DOM with a part
attribute) of the element. You can still write more complex
selectors, which rely on any of the state attributes applied on the host or parts.
You can find links to the shadow parts documentation at the end of each element’s styling API documentation. See vaadin-button for example.
When creating a theme module for an element, the styles in that theme module will apply to all instances of that element. The styles are always “global” in that sense and can’t be scoped by default with anything.
There are two ways to scope the styles that you write in a theme module.
theme
attribute). The downside of this approach is that
you end up adding the styles to all instances, even though only some instances will need those
styles.As with the built-in element themes, theme modules should be defined before the corresponding elements are imported to make sure they are loaded by the elements.