Styles

This guide applies only if you use the default (shadow DOM) render root. If you modify your element’s render root to render into the main DOM tree instead of a shadow root, these instructions won’t apply.

If you’re using the Shady CSS polyfill, be aware that it has some limitations. See the Shady CSS README for more information.

Use the :host and :host() CSS pseudo-classes

When styling your custom element, you can use the :host and :host() CSS pseudo-classes in a <style> block to select the host element (the element hosting the root of your shadow DOM). The two pseudo-classes slightly differ in usage:

Please note, that :host and :host() (with empty parentheses) do not behave the same. Here’s a simple example:

my-element.js

render() {
  return html`
    <style>
      :host([hidden]) { display: none; }
      :host {
        display: block; 
        border: 1px solid black;
      }
    </style>
    <p>Hello world</p>
  `;
}

See the MDN documentation on :host, :host(), and pseudo-classes for more information.

Set host element display styles

Two best practices for working with custom elements are:

<style>
  :host([hidden]) { display: none; }
  :host { display: block; }
</style>

See Custom Element Best Practices for more information.

Style shadow DOM children via properties inherited via :host

Child elements in your template will inherit CSS properties you assign to your host via 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>
  `;
}

If your host element itself inherits properties from another element, the host’s shadow DOM children will inherit those properties in turn:

  <style>
    div { font-family: Roboto; }
  </style>
  ...
  <div><my-element>Will use Roboto font</my-element></div>

Style the host from the main document

You can also style the host from outside its own template.

Use the custom element tag as a selector

You can set styles for the host 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>

The :host CSS pseudo-class has higher specificity than the element’s type selector. Styles set for your host with the :host pseudo-class from inside its own template will override styles set in the main document. For example:

index.html

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

my-element.js

<style>
  /* Overrides styles set for my-element in index.html */
  :host {
    color: red;
  }
</style>

Use custom properties

Custom properties inherit down the DOM tree. 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>
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.

Select slotted elements with the ::slotted() CSS pseudo-element

Use the ::slotted() CSS pseudo-element to select light DOM elements 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);

Use JavaScript expressions in LitElement style blocks

You can include style information in a JavaScript expression inside a LitElement template:

render() { 
  return html`
    <style>${this.myStyles}</style>
    <p>hi world</p>
  `; 
}

get myStyles() { 
  return html`p { color: red }`; 
} 

Example: A small theme

index.html

<style>
  html {
    --themeColor1: rgb(67, 156, 144);
    --themeFont: Roboto;
  }
  my-element {
    --myColor: var(--themeColor1);
    --myFont: var(--themeFont);
  }
</style>
...
<my-element></my-element>

my-element.js

render() {
  return html`
    <style>
      :host([hidden]) { display: none; }
      :host { display: block; 
        color: var(--myColor, aliceblue);
        font-family: var(--myFont, Verdana);
      }
      ${navStyles}
    </style>

    <ul class="navigation">
      ${this.menuItems.map(item => html`<li class="item">${item}</li>`)}
    </ul>
  `;
}

my-styles.js

export const navStyles = html`
  ul {
    list-style-type: none; 
    margin: 0;
    padding: 0;
  }
  .navigation {
    display: flex;
    flex-direction: row;
  }
  .item {
    padding: 8px;
  }
`;