Style a Component

To bundle styles with a component, create a style sheet in the component’s folder. The style sheet must have the same name as the component. The style sheet is applied to the component automatically.

Each component can have only one style sheet. Components can’t share style sheets. Style sheets use standard CSS syntax and you can use most selectors.

Styles defined in a component’s style sheet are scoped to the component. This rule allows a component to be reused in different contexts without losing its style. It also prevents a component’s styles from overriding styles in other parts of a page.

CSS Scoping Examples

Important

Before we go further, we need to understand naming. A component's folder and file names are camel case, myComponent, myComponent.html, and myComponent.css. In HTML markup, camelCase maps to kebab-case. When a component renders, the <template> tag is replaced with <namespace-component-name>. Note that the tag includes the component's namespace. For example, a component with the template myComponent.html in the example namespace renders as <example-my-component>. For more information about naming, see Component Bundles.

This example demonstrates how the CSS styles defined in a parent component don’t reach into a child.

There are two components cssParent and cssChild. Each component contains text in a <p> tag. The cssParent.css style sheet defines the p style as xx-large. The style applies only to the <p> tag in the parent, not to the <p> tag in the nested child.

A parent component can style a child component, but it styles it as a single element. A parent can’t reach into the DOM of a child. In the playground, add an example-css-child selector to cssParent.css that defines the background of the child component.

/* cssParent.css */
p {
    font-size: xx-large;
}

example-css-child {
    display: block;
    background: whitesmoke;
}

Tip

To access cssParent.css in the playground, scroll to the right in the left pane header and click on the filename.

In a new playground, let’s style the example-css-child component from its own style sheet, cssChild.css.

A component’s style sheet can reach up and style its own element. Instead of using a example-css-child selector, use the :host selector.

Uncomment this code in cssChild.css. By targeting the host element with :host, we apply styling to <example-css-child>, from cssChild.css.

/* cssChild.css */
:host {
    display: block;
    background: whitesmoke;
}

Note

The cssParent.css file in this playground doesn't include the example-css-child selector. It’s not a good practice to style components from both the component and its parent, because it can be confusing and yield unexpected results.

The :host selector accepts an optional list of selectors. To match, the host element must have a class that matches the passed selector. To see how the :host selector works, in a new playground, let’s rewrite our sample code to look slightly more like a real app.

Style the p in the child component x-large, which is just a notch smaller than the p in the parent component. Make each item whitesmoke except the active item, which is thistle.

/* cssChild.css */
p {
    font-size: x-large;
}
:host {
    display: block;
    background: whitesmoke;
}

:host(.active) {
    display: block;
    background-color: thistle;
}

Right now, the child component contains just a static title, To Do Item. Add a <slot> to cssChild.html so the parent component can pass to do item text.

<!–- cssChild.html-->
<template>
     <p>To Do Item</p>
     <slot></slot>
</template>

In the parent, add three example-css-child components and make one active. In a real app, the active component would be the selected item. Because example-css-child contains a <slot>, we can pass text for each to do item.

<!-- cssParent.html -->
<template>
    <p>To Do List</p>
    <example-css-child>Buy potatoes</example-css-child>
    <example-css-child  class="active">Volunteer at a school</example-css-child>
    <example-css-child>Plan a party</example-css-child>
</template>

For more information about <slot>, see Pass Markup into Slots.

CSS Support and Performance Impact

The CSS scoping matches the CSS Scoping Module Level 1 standard, with a few exceptions.

Scoped CSS affects performance, so use it with care. Each selector chain is scoped, and each compound expression passed to :host() is spread into multiple selectors. This transformation increases the size and complexity of the generated CSS. These increases mean more bits on the wire, longer parsing time, and longer style recalculation time.

To ensure CSS encapsulation, each element has an extra attribute, which also increases rendering time. For example, the <example-parent> element has a example-parent_parent-host attribute.

<example-parent example-parent_parent-host>
    <h1 example-parent_parent>To Do List</h1>
    <example-child example-parent_parent example-child_child-host>
        <h1 example-child_child>To Do Item</h1>
    </example-child>
    <example-child class="active" example-parent_parent example-child_child-host>
        <h1 example-child_child>To Do Item</h1>
    </example-child>
</example-parent>