The original link

In this article, Element and Component are used in some contexts. LitElement is essentially an implementation of WebComponents, so elements can be considered components.

How do component developers define component styles

The ShadowDOM API allows the creation of an encapsulated DOM tree on a custom element. The root node of the ShadowDOM tree is shadowRoot, and the element mounted by shadowRoot is called host element (or host).

In general, LitElement creates shadowRoot for each host element and renders the DOM structure described by the template to shadowRoot.

ShadowDOM limits the scope of CSS so that styles defined within shadowRoot only apply to DOM elements within shadowRoot and do not leak to the external DOM. In addition to CSS inheritance properties, shadowRoot isolates styles outside of it, whether they are in the main document or outside of shadowRoot.

Where to define styles

There are three ways to define the host element and its shadowDOM style:

  • Static LitElement classstylesProperties (recommended)
  • renderMethod into the HTML template<style>The element
  • External style sheets, through< link rel = "stylesheet" href = "..." >Link to the LitElement template

Static LitElement classstylesattribute

LitElement allows you to define static styles that can be applied to all component instances.

Static styles improve performance; they are parsed once and reused across multiple components.

If you want to style each component instance, you need to use CSS custom properties (compatibility risk, iOS9 does not support) :

  • Component developers define CSS variables in shadowDOM
  • The component consumer defines the values of these custom CSS variables externally

Define static styles:

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

class MyElement extends LitElement {
  static get styles() {
    const mainWidth = 800;
    const padding = 20;   
    
    return css`
      :host { 
        width: ${unsafeCSS(mainWidth + padding)}px;
      }
    `; }}Copy the code

For literal strings (red), you can simply use ${}; Variables need to be wrapped in ${unsafeCSS()}.

⚠️unsafeCSS can only be used with trusted input, otherwise there may be a security risk.

HTML template<style>The element

Inserting

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

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

⚠️ do not use expressions inside

External style sheets

Load external stylesheets via the tag:

import {LitElement} from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html` 
       `; }}Copy the code

There are two main points to emphasize about this approach:

  • The first load causes unstyled content flicker (FOUC)
  • hrefThe path to the main document is not well suited for exposed reusable components

Write CSS styles for the Host Element and its ShadowDOM

Write styles for host elements

Host elements can style themselves with :host and :host()CSS pseudo-classes:

  • :host Selects the host element corresponding to shadowRoot

    :host {
      display: block;
      color: blue;
    }
    Copy the code
  • : the host (…). This takes effect only if the selector in parentheses matches the host element

    :host(.important) {
      color: red;
      font-weight: bold;
    }
    Copy the code

Two best practices for custom elements:

  • Add a display style (such as block or inline-block) to :host. The default display for :host is inline. Inline elements are sized by their contents rather than by CSS

      :host {
        display: block;
      }
    Copy the code
  • Style :host with hidden property

      :host([hidden]) {
        display: none;
      }
    Copy the code

Write styles for ShadowDOM

For elements within shadowRoot, use standard CSS selectors.

Internally defined CSS selectors work only inside shadowRoot, so they can do whatever they want inside. They don’t match external elements:

* {
  color: black;
}

h1 {
  font-size: 4rem;
}

#main {
  padding: 16px;
}

.important {
  color: red;
}
Copy the code

Style slotted Children

For elements inserted into shadowDOM with

slots, we can use ::slotted() pseudo-elements to select:

  • ::slotted(*)Matches all slot elements
  • ::slotted(p)Matches the P elements of all slots
  • div ::slotted(*)Matches all slot elements within div
import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`  
       
      
`
; } } customElements.define('my-element', MyElement); Copy the code

How do component users define component styles

When using a component, the user simply uses the tag of the custom component as selector in the main document, for example:

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

These externally defined attributes, applied to the host element, take precedence over those defined internally with :host

Three, themes,

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

  • Create the easily Stylable LitElement component
  • Create a style theme that you can easily use to import LitElement

CSS inheritance and shadowDOM

Inheriting CSS properties (such as color,font-family, and all CSS custom properties (- *) can be inherited across shadowRoot boundaries, which means that elements can generally share important styles externally.

Component authors can take advantage of this by defining inheritance properties on the hostCSS pseudo-class that will be used on elements inside shadowRoot:

my-element.js

render() {
  return html`  

Inherits font styles

`
; } Copy the code

We can also define an inherited attribute change in the external main document :host, because the external element class selector takes precedence over the host pseudo-class selector, and the external style overrides the internal style:

index.html

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

Customize CSS properties

Custom CSS properties can be inherited along the DOM tree and can cross shadowRoot boundaries, which can be used for style and theme customization.

my-element.js

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

Index.html

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

The external — myBackground custom property is used on the internal my-Element

Four, summary

  • For a common style of components, that is, one shared by all components, static is recommendedstylesProperties to set
  • For instances of components, HTML templates are recommended<style>Through the${this.myColor}Implementing instance customization
  • ::hostPseudo classes are used to style host elements,::slotted()Use to style the slot child elements. Styles in shadowRoot use the standard CSS selector
  • There are two methods for transparent transmission of attributes from the outside: CSS inherited attributes and CSS custom attributes. The custom attributes are more flexible but have certain compatibility problems