Sharing Style Sheets
Avoid copy-pasting the same CSS in multiple style sheets.
You can share a style sheet between the global scope and multiple component scopes. One common use case for shared style sheets is to define typographic styles which you want to be applied consistently across the whole application.
Prerequisites
You should be familiar with Style Scopes and Importing Style Sheets.
Creating Shared Style Sheets
To be able to share styles across many style scopes, you need to create a shared style sheet.
If you want to share style sheets in server-side views (Java), place the shared styles in a separate .css
file.
You make it shareable by using the @CssImport
annotation and giving it a unique id
.
The style sheet will not be imported to any scope until another style sheet includes it using the id
.
Source code
ImportingStyleSheets.java
package com.vaadin.flow.tutorial.theme;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dependency.StyleSheet;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.tutorial.annotations.CodeFor;
@CodeFor("../../themes/importing-style-sheets.asciidoc")
public class ImportingStyleSheets {
@Route(value = "")
// Import a style sheet into the global scope
@CssImport("./styles/shared-styles.css")
@CssImport(value = "./styles/shared-styles.css", include = "common-styles")
@CssImport(value = "./styles/shared-typography.css",
id = "shared-typography")
@CssImport(value = "./styles/shared-styles.css",
include = "shared-typography")
// Import a style sheet into the local scope of the TextField component
@CssImport(value = "./styles/text-field.css",
themeFor = "vaadin-text-field")
@CssImport(value = "./styles/shared-overlays.css",
themeFor = "vaadin-select-overlay vaadin-combo-box-overlay")
@CssImport(value = "./styles/shared-styles.css",
include = "shared-typography",
themeFor = "vaadin-confirm-dialog-overlay")
// Link to external style sheets
@StyleSheet("context://custom-font.css")
@StyleSheet("https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css")
public class MyApplication extends Div {
}
}
shared-typograhy.css
shared-typograhy.css
h1 {
font-weight: 300;
font-size: 40px;
}
h2 {
font-weight: 300;
font-size: 32px;
}
h3 {
font-weight: 400;
font-size: 24px;
}
.heading {
margin-top: 0;
}
p {
/* Assuming we are using the Lumo theme. If not, fall back to 1.2em */
font-size: var(--lumo-font-size-l, 1.2em);
}
.back-button {
background-color: var(--lumo-shade-90pct);
}
.image-bg {
background-image: url("/my-image.png");
}
shared-typography.css.js
shared-typography.css.js
// tutorial::../documentation-themes/importing-style-sheets.asciidoc
// Import the function that allows you to register style sheets for components
import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Import the tagged template function that is used to define
// a multi-line CSS string
import { css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Define and register a style sheet for the <vaadin-text-field> component
registerStyles('vaadin-text-field', css`
[part="input-field"] {
border: 1px solid;
...
}
`);
// Register the same style sheet for both the <vaadin-select-overlay>
// and the <vaadin-combo-box-overlay> elements
registerStyles('vaadin-select-overlay vaadin-combo-box-overlay', css`
/* Styles which will be imported in
vaadin-select-overlay and vaadin-combo-box-overlay
local style scopes */
`);
// Define and export a string of reusable CSS
export default css`
h1 {
font-weight: 300;
font-size: 40px;
}
h2 {
font-weight: 300;
font-size: 32px;
}
h3 {
font-weight: 400;
font-size: 24px;
}
`;
// Import a string of shared CSS
import sharedTypography from 'styles/shared-typography.css.js';
// Create a new <style> element and add the shared CSS to it.
const style = document.createElement('style');
style.innerHTML = sharedTypography.toString();
// Add the new style sheet to the global scope (document)
document.head.appendChild(style);
// Register the shared typography styles for
// the <vaadin-confirm-dialog-overlay> element
registerStyles('vaadin-confirm-dialog-overlay', sharedTypography);
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
class MyView extends PolymerElement {
static get template() {
return html`
${sharedTypography}
<h2>My view title</h2>
...
`;
}
static get is() {
return 'my-view';
}
}
customElements.define(MyView.is, MyView);
// Import a theme-specific component, for example <vaadin-button>
import '@vaadin/vaadin-button/theme/lumo/vaadin-button.js';
// Import the color style sheet if you are using some of
// the custom color properties Lumo offers
import '@vaadin/vaadin-lumo-styles/color.js';
Using Shared Style Sheets
Once you have created and defined a shared style sheet, you can include it in another style sheet which you can import either to the global style scope or to a component’s local style scope.
Global Style Scope
In server-side views (Java), reference the id
of the shared style sheet in the include
attribute of the @CssImport
annotation. This will include the shared style sheet in the global scope, together with the other style sheet the annotation references using the file path.
Source code
ImportingStyleSheets.java
package com.vaadin.flow.tutorial.theme;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dependency.StyleSheet;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.tutorial.annotations.CodeFor;
@CodeFor("../../themes/importing-style-sheets.asciidoc")
public class ImportingStyleSheets {
@Route(value = "")
// Import a style sheet into the global scope
@CssImport("./styles/shared-styles.css")
@CssImport(value = "./styles/shared-styles.css", include = "common-styles")
@CssImport(value = "./styles/shared-typography.css",
id = "shared-typography")
@CssImport(value = "./styles/shared-styles.css",
include = "shared-typography")
// Import a style sheet into the local scope of the TextField component
@CssImport(value = "./styles/text-field.css",
themeFor = "vaadin-text-field")
@CssImport(value = "./styles/shared-overlays.css",
themeFor = "vaadin-select-overlay vaadin-combo-box-overlay")
@CssImport(value = "./styles/shared-styles.css",
include = "shared-typography",
themeFor = "vaadin-confirm-dialog-overlay")
// Link to external style sheets
@StyleSheet("context://custom-font.css")
@StyleSheet("https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css")
public class MyApplication extends Div {
}
}
ImportStyleSheets.js
// tutorial::../documentation-themes/importing-style-sheets.asciidoc
// Import the function that allows you to register style sheets for components
import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Import the tagged template function that is used to define
// a multi-line CSS string
import { css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Define and register a style sheet for the <vaadin-text-field> component
registerStyles('vaadin-text-field', css`
[part="input-field"] {
border: 1px solid;
...
}
`);
// Register the same style sheet for both the <vaadin-select-overlay>
// and the <vaadin-combo-box-overlay> elements
registerStyles('vaadin-select-overlay vaadin-combo-box-overlay', css`
/* Styles which will be imported in
vaadin-select-overlay and vaadin-combo-box-overlay
local style scopes */
`);
// Define and export a string of reusable CSS
export default css`
h1 {
font-weight: 300;
font-size: 40px;
}
h2 {
font-weight: 300;
font-size: 32px;
}
h3 {
font-weight: 400;
font-size: 24px;
}
`;
// Import a string of shared CSS
import sharedTypography from 'styles/shared-typography.css.js';
// Create a new <style> element and add the shared CSS to it.
const style = document.createElement('style');
style.innerHTML = sharedTypography.toString();
// Add the new style sheet to the global scope (document)
document.head.appendChild(style);
// Register the shared typography styles for
// the <vaadin-confirm-dialog-overlay> element
registerStyles('vaadin-confirm-dialog-overlay', sharedTypography);
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
class MyView extends PolymerElement {
static get template() {
return html`
${sharedTypography}
<h2>My view title</h2>
...
`;
}
static get is() {
return 'my-view';
}
}
customElements.define(MyView.is, MyView);
// Import a theme-specific component, for example <vaadin-button>
import '@vaadin/vaadin-button/theme/lumo/vaadin-button.js';
// Import the color style sheet if you are using some of
// the custom color properties Lumo offers
import '@vaadin/vaadin-lumo-styles/color.js';
Component Style Scope
To use a shared style sheet in a component scope, add the include
attribute to a component scoped @CssImport
annotation.
Source code
ImportingStyleSheets.java
package com.vaadin.flow.tutorial.theme;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dependency.StyleSheet;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.tutorial.annotations.CodeFor;
@CodeFor("../../themes/importing-style-sheets.asciidoc")
public class ImportingStyleSheets {
@Route(value = "")
// Import a style sheet into the global scope
@CssImport("./styles/shared-styles.css")
@CssImport(value = "./styles/shared-styles.css", include = "common-styles")
@CssImport(value = "./styles/shared-typography.css",
id = "shared-typography")
@CssImport(value = "./styles/shared-styles.css",
include = "shared-typography")
// Import a style sheet into the local scope of the TextField component
@CssImport(value = "./styles/text-field.css",
themeFor = "vaadin-text-field")
@CssImport(value = "./styles/shared-overlays.css",
themeFor = "vaadin-select-overlay vaadin-combo-box-overlay")
@CssImport(value = "./styles/shared-styles.css",
include = "shared-typography",
themeFor = "vaadin-confirm-dialog-overlay")
// Link to external style sheets
@StyleSheet("context://custom-font.css")
@StyleSheet("https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css")
public class MyApplication extends Div {
}
}
ImportStyleSheets.js
// tutorial::../documentation-themes/importing-style-sheets.asciidoc
// Import the function that allows you to register style sheets for components
import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Import the tagged template function that is used to define
// a multi-line CSS string
import { css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Define and register a style sheet for the <vaadin-text-field> component
registerStyles('vaadin-text-field', css`
[part="input-field"] {
border: 1px solid;
...
}
`);
// Register the same style sheet for both the <vaadin-select-overlay>
// and the <vaadin-combo-box-overlay> elements
registerStyles('vaadin-select-overlay vaadin-combo-box-overlay', css`
/* Styles which will be imported in
vaadin-select-overlay and vaadin-combo-box-overlay
local style scopes */
`);
// Define and export a string of reusable CSS
export default css`
h1 {
font-weight: 300;
font-size: 40px;
}
h2 {
font-weight: 300;
font-size: 32px;
}
h3 {
font-weight: 400;
font-size: 24px;
}
`;
// Import a string of shared CSS
import sharedTypography from 'styles/shared-typography.css.js';
// Create a new <style> element and add the shared CSS to it.
const style = document.createElement('style');
style.innerHTML = sharedTypography.toString();
// Add the new style sheet to the global scope (document)
document.head.appendChild(style);
// Register the shared typography styles for
// the <vaadin-confirm-dialog-overlay> element
registerStyles('vaadin-confirm-dialog-overlay', sharedTypography);
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
class MyView extends PolymerElement {
static get template() {
return html`
${sharedTypography}
<h2>My view title</h2>
...
`;
}
static get is() {
return 'my-view';
}
}
customElements.define(MyView.is, MyView);
// Import a theme-specific component, for example <vaadin-button>
import '@vaadin/vaadin-button/theme/lumo/vaadin-button.js';
// Import the color style sheet if you are using some of
// the custom color properties Lumo offers
import '@vaadin/vaadin-lumo-styles/color.js';
If you want to share a style sheet with a custom web component or client-side template, import it in the template directly.
Source code
ImportStyleSheets.js
// tutorial::../documentation-themes/importing-style-sheets.asciidoc
// Import the function that allows you to register style sheets for components
import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Import the tagged template function that is used to define
// a multi-line CSS string
import { css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
// Define and register a style sheet for the <vaadin-text-field> component
registerStyles('vaadin-text-field', css`
[part="input-field"] {
border: 1px solid;
...
}
`);
// Register the same style sheet for both the <vaadin-select-overlay>
// and the <vaadin-combo-box-overlay> elements
registerStyles('vaadin-select-overlay vaadin-combo-box-overlay', css`
/* Styles which will be imported in
vaadin-select-overlay and vaadin-combo-box-overlay
local style scopes */
`);
// Define and export a string of reusable CSS
export default css`
h1 {
font-weight: 300;
font-size: 40px;
}
h2 {
font-weight: 300;
font-size: 32px;
}
h3 {
font-weight: 400;
font-size: 24px;
}
`;
// Import a string of shared CSS
import sharedTypography from 'styles/shared-typography.css.js';
// Create a new <style> element and add the shared CSS to it.
const style = document.createElement('style');
style.innerHTML = sharedTypography.toString();
// Add the new style sheet to the global scope (document)
document.head.appendChild(style);
// Register the shared typography styles for
// the <vaadin-confirm-dialog-overlay> element
registerStyles('vaadin-confirm-dialog-overlay', sharedTypography);
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
class MyView extends PolymerElement {
static get template() {
return html`
${sharedTypography}
<h2>My view title</h2>
...
`;
}
static get is() {
return 'my-view';
}
}
customElements.define(MyView.is, MyView);
// Import a theme-specific component, for example <vaadin-button>
import '@vaadin/vaadin-button/theme/lumo/vaadin-button.js';
// Import the color style sheet if you are using some of
// the custom color properties Lumo offers
import '@vaadin/vaadin-lumo-styles/color.js';
96CC1CBA-FF72-4F10-8393-B49BDB3D1C67