Valo

Customization

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.

What is a “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).


Common use cases

Built-in theme variations

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:

Example: making a button more prominent using built-in variations

The built-in variations are documented per component, including source code examples how to apply them. See Button’s color variations for example.

Light and dark themes

Read more about light and dark themes from the colors documentation.


Small adjustments

CSS custom properties

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.

Global changes

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.

Example: changing the border radius of all elements with a global style

Scoped changes

If you wish to adjust the border radius for vaadin-button specifically, for example, you can do the following:

Example: Changing the border radius of one component using a common custom property

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:

Example: Changing the border radius of one component using a component specific custom property in the global style scope

Advanced styling

Theme modules

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.

Defining a theme module

A theme module is basically the same as a Polymer style module, with an additional theme-for attribute.

Module ID

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 attribute

The 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:

Writing styles in a theme module

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:

Supported selectors

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.

Example: Styling text field’s focused and invalid states

You can find links to the shadow parts documentation at the end of each element’s styling API documentation. See vaadin-button for example.

Theme modules are global

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.

Scoping styles in a theme module

There are two ways to scope the styles that you write in a theme module.

  1. Expose new custom properties
    This is the recommened first option for simple situations. If you end up exposing more than a handful of properties, you should consider the second option.
  2. Use scoping selectors
    This approach is used by the built-in theme variations (i.e. 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.
Example: Exposing new custom properties
Example: Use scoping selectors

Define theme modules before importing elements

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.