スタイリング

This page is a guide to the styling options available for LitElement components.

Shady CSSポリフィルを使用している場合、いくつかの制限があることに注意してください。 詳細については、Shady CSS READMEを参照してください。

Styling options for component developers

The shadow DOM API allows the creation of encapsulated DOM trees that are attached to a custom element.

The root node of a shadow DOM tree is called the shadow root. The element in the main document that has a shadow root attached to it is called the host element, or host.

By default, LitElement creates a shadow root for your host element. LitElement renders the DOM structure described in your element template into this shadow root.

Shadow DOM scopes CSS so that styles defined in a shadow root only apply to DOM inside the shadow root, and do not “leak” to outside DOM. With the exception of inherited CSS properties, shadow roots are also isolated from styles defined outside the shadow root, whether in the main page or an outer shadow root.

This section describes how to create styles in your shadow root to style your host element and its shadow DOM.

Where to define your styles

There are three main places in which you can define styles for your host element and its shadow DOM:

Define styles in a static styles property

LitElement lets you define static styles that apply to all instances of a component.

We recommend using static styles for optimal performance. LitElement uses Constructable Stylesheets in browsers that support it, with a fallback for browsers that don’t. Constructable Stylesheets allow the browser to parse styles exactly once and reuse the resulting Stylesheet object for maximum efficiency.

The styles in the static styles property are evaluated once only and applied to all instances of the element. You can modify styles per element instance by using CSS custom properties:

If you don’t want to use custom properties, you can define per-instance styles in a <style> element inside shadow DOM. See the section on Defining your styles in a style element for more information.

</div>

To define a static styles property:

  1. Import the css helper function from the lit-element module:

    import {LitElement, css} from 'lit-element';
    
  2. Create a static styles property and define your styles in plain CSS.

    The value of the static styles property can be:

    • A single tagged template literal:

      class MyElement extends LitElement {
        static styles = css`
          :host {
            display: block;
          }
        `;
      }
      
    • Or an array of tagged template literals:

      class MyElement extends LitElement {
        static styles = [ css`:host { display: block; }`, ...];
      }
      

      Using an array of tagged template literals lets you inherit the styles from a LitElement superclass, and add more:

      class MySubElement extends MyElement {
        static styles = [
          super.styles,
          css`
            :host([.important]) {
              color: red;
            }
          `
        ];
      }
      

Expressions in static styles

Static styles apply to all instances of an element. Any expressions in your CSS are evaluated and included once, then reused for all instances.

For security reasons, expressions must be tagged with the cssLiteral template literal tag:

import { LitElement, css, cssLiteral } from 'lit-element';

const mainColor = cssLiteral`red`;

class MyElement extends LitElement {
  static styles = css`
    :host {
      display: block;
      color: ${mainColor}
    }
  `;
}

Define styles in a style element

We recommend using static styles to style LitElement components. However, in some cases you may want to evaluate and apply styles per instance, rather than to all instances of a LitElement component. One way to do this is to include inline styles in a <style> element in your template, and use your element’s properties in your CSS rules to evaluate styles per instance.

Expressions inside a <style> element won’t update per instance in ShadyCSS. Due to limitations of the ShadyCSS polyfill, you can’t use element properties in CSS rules as the expressions won’t be evaluated.

import {LitElement, property} from 'lit-element';

class MyElement extends LitElement {
  @property() mainColor = 'blue';
  render() {
    return html`
      <style>
        :host {
          color: ${this.mainColor};
        }
      </style>
    `;
  }
}

Define styles in an external stylesheet

We strongly recommend static styles, CSS custom properties, or lit-html’s classMap or styleMap directives if you’re stying non-host shadow root contents.

However, you can load an external stylesheet into a shadow root with a <link> element:

import {LitElement} from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`
      <link rel="stylesheet" href="./styles.css">
    `;
  }
}

This can be a good way to load CSS generated from tools like SASS/LESS.

There are some important caveats though:

Write CSS styles for a host element and its shadow DOM

In this section:

Write CSS styles for a host element

An element can apply styles to itself with the :host and :host() CSS psuedo-classes used inside the element’s ShadowRoot. The tern “host” is used because an element is the host of its own shadow root.

Two best practices for working with custom elements are:

See Custom Element Best Practices for more information.

Write CSS styles for elements in shadow DOM

To style elements in a shadow root, simply use standard CSS selectors.

Since CSS selectors in a shadow root only apply to elements in the shadow root, you don’t need to be defensive against accidentally styling other elements in the page. This means you can generally write much simpler selectors, that are easier to reason about, and faster, than without shadow DOM.

Simple selectors, like *, tagname, id, and class selectors, are fine in a shadow root because they don’t match outside the root:

* {
  color: black;
}

h1 {
  font-size: 4rem;
}

#main {
  padding: 16px;
}

.important {
  color: red;
}

Write CSS styles for slotted children

Use the ::slotted() CSS pseudo-element to select light DOM children that have been included in shadow DOM via the <slot> element.

import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`
      <style>
        :host([hidden]) { display: none; }
        :host { display: block; }
        ::slotted(*) { font-family: Roboto; }
        ::slotted(span) { color: blue; }
        div ::slotted(*) { color: red; }
      </style>
      <slot></slot>
      <div><slot name="hi"></slot></div>
    `;
  }
}
customElements.define('my-element', MyElement);

Styling options for component consumers

When you use a LitElement component, you can set styles from the main document by using its custom element tag as a selector. For example:

index.html

<style>
  my-element { 
    font-family: Roboto;
    font-size: 20;
    color: blue;
  }
</style>
...
<my-element></my-element>

An element type selector has higher specificity than the :host pseudo-class selector.

Styles set for a host element from outside its shadow DOM will override styles set with the :host or :host() pseudo-class selectors inside shadow DOM. See Inheritance.

Theming

This section describes how to use CSS inheritance and custom CSS properties to:

CSS Inheritance and shadow DOM

Inherited CSS properties like color, font-family, and all CSS custom properties (--*) inherit through shadow root boundaries.

This means that by default an element will share some important styles from its outside context.

Component authors can take advantage of this to style all of a shadow root’s contents by setting inherited properties on the host with the :host CSS pseudo-class:

my-element.js

render() {
  return html`
    <style>
      :host { 
        display: block; 
        font-family: Roboto;
        font-size: 20;
        color: blue;
      }
    </style>
    <p>Inherits font styles</p>
  `;
}

shadow DOMの子要素を:hostから継承したプロパティでスタイルする

テンプレートの子要素 :hostはCSS疑似クラスを介してホストに割り当てたCSSプロパティを継承します:

my-element.js

render() {
  return html`
    <style>
      :host { 
        display: block; 
        font-family: Roboto;
        font-size: 20;
        color: blue;
      }
    </style>
    <p>継承されたフォントスタイル</p>
  `;
}

ホスト要素自体が別の要素のプロパティを継承する場合、そのホストのシャドーDOMの子は、それらのプロパティを順番に継承します:

  <style>
    div { font-family: Roboto; }
  </style>
  ...
  <div><my-element>Robotoフォントが使われる</my-element></div>

A LitElement component can be styled by using its custom element tag as a selector. For example:

index.html

<style>
  my-element { 
    font-family: Roboto;
    font-size: 20;
    color: blue;
  }
</style>
...
<my-element></my-element>

An element type selector has higher specificity than the :host pseudo-class selector.

Styles set for a host element from outside its shadow DOM will override styles set with the :host or :host() pseudo-class selectors inside shadow DOM. For example:

index.html

<style>
  /* Overrides the `color` property of the `:host` styles in my-element.js */
  my-element { 
    color: blue;
  }
</style>
...
<my-element></my-element>

my-element.js

<style>
  :host {
    color: red;
    background-color: aliceblue;
  }
</style>

Custom CSS Properties

Custom properties inherit down the DOM tree, and through shadow root boundaries. You can use this to let your users apply styles and themes to your elements.

For example, the following element sets its background color to a CSS variable that uses the value of the custom property --myBackground if it is available, and uses yellow otherwise:

my-element.js

<style>
  :host {
    display: block;
    background-color: var(--myBackground, yellow);
  }
</style>

The user can now set the custom property --myBackground in their main document in order to style the background of my-element.

index.html

<style>
  my-element {
    --myBackground: rgb(67, 156, 144);
  }
</style>

If the user has an existing app theme, they can easily apply their theme properties to my-element:

<style>
  html {
    --themeColor1: rgb(67, 156, 144);
  }
  my-element {
    --myBackground: var(--themeColor1);
  }
</style>

メインドキュメントからホストをスタイルする

独自のテンプレートの外からホストをスタイルすることもできます。

カスタム要素タグをセレクタとして使用する

カスタム要素タグをセレクタとして使用して、ホストのスタイルをメインドキュメントから設定できます。例えば:

index.html

<style>
  my-element { 
    font-family: Roboto;
    font-size: 20;
    color: blue;
  }
</style>
...
<my-element></my-element>

:host CSS疑似クラスは要素の型セレクタよりも特殊です 独自のテンプレートの中から :host疑似クラスを持つホスト用に設定されたスタイルは、メインドキュメントに設定されているスタイルを上書きします。例えば:

index.html

<style>
  my-element { 
    color: blue;
  }
</style>
...
<my-element></my-element>

my-element.js

<style>
  /* index.htmlのmy-elementに設定されているスタイルをオーバーライドします。 */
  :host {
    color: red;
  }
</style>

カスタムプロパティを使用する

カスタムプロパティはDOMツリー全体で継承されます。これを使用すると、ユーザーが要素にスタイルやテーマを適用できるようになります。

たとえば、次の要素は、背景色をカスタム変数 --myBackgroundの値を使用するCSS変数に設定し、使用可能な場合はyellowを使用します:

my-element.js

<style>
  :host {
    display: block;
    background-color: var(--myBackground, yellow);
  }
</style>

my-elementの背景をスタイルするために、メイン文書でカスタムプロパティ--myBackgroundを設定できるようになりました。

index.html

<style>
  my-element {
    --myBackground: rgb(67, 156, 144);
  }
</style>

ユーザーが既存のアプリテーマを持っている場合、テーマプロパティを my-elementに簡単に適用できます:

<style>
  html {
    --themeColor1: rgb(67, 156, 144);
  }
  my-element {
    --myBackground: var(--themeColor1);
  }
</style>
import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`
      <style>
        :host([hidden]) { display: none; }
        :host { display: block;
          background-color: var(--myBackground, yellow);
          color: var(--myColor, black);
          padding: var(--myPadding, 8px);
        }
      </style>
      <p>Hello world</p>
    `;
  }
}
customElements.define('my-element', MyElement);

See CSS Custom Properties on MDN for more information.

A simple example theme

index.html

<!DOCTYPE html>
<html>
  <head>
    <script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
    <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
    <title>lit-element code sample</title>
    <style>
      body {
        --theme-primary: green;
        --theme-secondary: aliceblue;
        --theme-warning: red;
        --theme-font-family: Roboto;
      }

      my-element { 
        --my-element-text-color: var(--theme-primary); 
        --my-element-background-color: var(--theme-secondary); 
        --my-element-font-family: var(--theme-font-family);
      } 

      my-element.warning {
        --my-element-text-color: var(--theme-warning); 
      }
    </style>
  </head>
  <body>
    <my-element></my-element>
    <my-element class="warning"></my-element>
  </body>
</html>

my-element.js

import { LitElement, html, css } from 'lit-element';

class MyElement extends LitElement {
  static styles = css`
    :host { 
      display: block;
      color: var(--my-element-text-color); 
      background: var(--my-element-background-color);  
      font-family: var(--my-element-font-family);
    }
    :host([hidden]) {
      display: none;
    }
  `;
  render() {
    return html`
      <div>Hello from my-element</div>
    `;
  }
}
customElements.define('my-element', MyElement);