Status: IMPLEMENTED

Champion: Unknown

Revision: latest

RFC created: 1970/01/01

Last updated: unknown

CSS Definition for a LWC Component

Template Declaration

<template>
    <a href={url}>{name}</a>
    <p>{tagline}</p>
</template>

CSS Declaration

a { color: red; }
p { margin: 10px 0; }

The CSS will be compiled, and a prefix will be added on every rule to guarantee that specificity of the rule only applies to the body of the host element (the custom element that represents the component).

Styling the host element

The :host allows you to style the element hosting the component:

:host {
  opacity: 0.4;
  transition: opacity 420ms ease-in-out;
}
:host(:hover) {
  opacity: 1;
}
:host(:active) {
  position: relative;
  top: 3px;
  left: 3px;
}

The CSS will be compiled, and a prefix will replace :host to guarantee that specificity of the rule only applies to the host element (the custom element that represents the component).

One gotcha is that rules in the parent page have higher specificity than :host rules defined in CSS file, but lower specificity than a style attribute defined on the host element.

Proposal 1

x-foo.html

<template>
    <div>
        <p>
            <x-bar>
                <div>
</template>
<style>
div { border-color: blue; }
</style>

x-bar.html

<template>
    <div>
        <slot></slot>
    </div>
</template>
<style>
div { border-color: gray; }
</style>
<link href="some.css">

some.css

:host { border-color: yellow; }

Assuming that there is a main.js that creates the instance of x-foo, the output markup will be:

<x-foo x="maintpl">
    <div x="footpl">
        <p x="footpl">
            <x-bar x="footpl">
                <div x="bartpl">
                    <slot x="bartpl">
                        <div x="footpl">

and the styles added to the document will be:

/* from foo component */
div[x="footpl"] { color: blue; }

/* from bar component */
x-bar, [is="x-bar"] { border-color: yellow; }
div[x="bartpl"] { color: blue; }

This proposal relies on the fact that a unique key can be produced (it is a function of the name of the component and the name of the template), and this key can be added to the associated css and added as an attribute to each element in the template, and used at the same time as a matching prefix on every css rule.

The host rule is special, and it is not really bound to the template, but to the host. Rendering one template vs another should not imply changes in the style of the host element, that will be a problem.

Implementation Details

Examples

:host

:host {
  background: red;
}
:host(.fancy) {
  background: purple;
}

In the example above, the host will receive background color red, but if the host matches the selector .fancy, it will receive background color purple. This also helps with cases where the component is used for different tag names or via is attribute.

From what I can infer from the spec (https://drafts.csswg.org/css-scoping/#host-selector), it only supports a simple selector in the parenthesis.

:host-context

Selects a shadow host based on a matching parent element.

:host-context(.x-foo) {
  background: red;
}

In the example above, the host will receive background color red only if the host element is inserted as a direct child of a <x-foo> tag.

From what I can infer from the spec (https://drafts.csswg.org/css-scoping/#host-selector), it only supports a simple selector in the parenthesis.

Important Notice

Implementations should not rely on or use the selectors generated by the Lightning Web Components compiler. This is an implementation detail of Lightning Web Components and relying on it in user-land can potentially break your code in future releases.

undefined