# Style a Component
To bundle styles with a component, create a stylesheet in the component’s folder. The stylesheet must have the same name as the component. The stylesheet is applied to the component automatically.
Components can’t share stylesheets. Stylesheets use standard CSS syntax and you can use most selectors.
Styles defined in a component’s stylesheet 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.
For components that use native shadow DOM or server-side rendering, styles imported from multiple stylesheets are separated into different <style> tags.
# CSS Scoping Examples
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 stylesheet 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 the filename.
In a new playground, let’s style the example-css-child component from its own stylesheet, cssChild.css.
A component’s stylesheet 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.
# Create Styling Hooks
To expose styling hooks for your custom components, use CSS custom properties. CSS custom properties also make code easier to read and update.
Document your component's styling hooks as part of your component's API. To change a component's style, a consumer simply sets values for the styling hooks—they don't need to know how you implemented the styles.
To define a CSS custom property in a component's stylesheet, prefix the property with --. To insert the value of the property, use var().
:host {
--important-color: red;
}
.important {
color: var(--important-color);
}
CSS custom properties are inherited. Inherited properties pierce the shadow DOM. Some CSS properties, like color, are also inherited. Because CSS custom properties are inherited, a consumer can set their values at a higher level in the DOM tree and style your component.
These CSS custom properties create styling hooks for two themes: light and dark. Pass the fallback value as an optional second parameter to var().
.light {
background-color: var(--light-theme-backgroud-color, lightcyan);
color: var(--light-theme-text-color, darkblue);
}
.dark {
background-color: var(--dark-theme-background-color, darkslategray);
color: var(--dark-theme-text-color, ghostwhite);
}
To view the CSS in the playground, click cssCustomProps.css.
In this playground, a component consumes the cssCustomProps component and sets values for its styling hooks to change the colors for the light and dark themes. To view the CSS in the playground, click cssCustomProps2.css, and experiment by setting new values for the custom properties.
# Share CSS Style Rules
To share CSS style rules, create a module that contains only a CSS file. Import the module into the CSS file of any Lightning web component you want to style. You can import style rules from multiple CSS modules. The imported style rules are applied to the template just like non-imported style rules. Lightning Web Components supports the CSS cascade algorithm.
/* Syntax */
@import 'namespace/moduleName';
/* Example */
@import 'example/cssLibrary';
Create a Lightning web component that contains only a single CSS file. This component is your CSS module.
cssLibrary
└──cssLibrary.css
Important
Just like with any Lightning web component, the folder name and the filename must be identical.
/* cssLibrary.css */
h1 {
color: darkorchid;
font-size: xx-large;
}
p {
color: yellowgreen;
font-size: larger;
}
Import the module into the CSS file of a Lightning web component.
cssSharing
├──cssSharing.html
├──cssSharing.js
└──cssSharing.css
/* cssSharing.css */
@import 'example/cssLibrary';
/* Define other style rules for cssSharing here */
Imported style rules are applied to the template just like non-imported style rules. All style rules cascade. In the cssSharing.html template, the text in the <h1> tag uses the style defined in cssLibrary.css.
<!-- cssSharing.html -->
<template>
<h1>Title</h1>
<p>Body text</p>
</template>
For more information about @import, see MDN web docs: @import. MDN lists two syntaxes: @import url and @import url list-of-media-queries. LWC doesn’t honor the list-of-media-queries.
# Bind HTML Classes
Manipulate a component or an element's class list easily using its class attribute. You can use class object binding instead of string concatenation to generate complex class names. Class object binding is available in LWC v7.0.0 and later.
For example, you want to evaluate multiple classes on an element.
<template>
<h1>Class Object Binding Demo</h1>
<div class={computedClassNames}>Evaluate some classes here</div>
</template>
Pass in your class object to the getter.
import { LightningElement } from 'lwc';
export default class extends LightningElement {
position = "left";
fullWidth = true;
hidden = false;
get computedClassNames() {
return [
"div__block",
this.position && `div_${this.position}`,
{
"div_full-width": this.fullWidth,
"hidden": this.hidden
},
];
}
}
Your element renders like this.
<div class="div__block div_left div_full-width">
Evaluate some classes here
</div>
The class attribute removes boolean, number, and function values. For example, if you pass in true or 10, the element renders class="".
An array is evaluated based on its items. For example, if you pass in ["highlight", "yellow"], the element renders class="highlight yellow".
Note
Before LWC v7.0.0, the class attribute rendered booleans, numbers, functions, arrays, and objects differently . See LWC v7.0.0: Class object binding.
# Bind Inline Styles
Append a class or multiple classes on an element or component using its style attribute.
<div class="block" style={inlineStyles}></div>
This example uses a getter to set inline styles on an element. To provide multiple styles, separate the styles using a colon. Also, use standard kebab-cased CSS property keys like font-size.
import { LightningElement } from 'lwc';
export default class extends LightningElement {
percentage = 80;
get inlineStyles() {
return `width: ${this.percentage}%; font-size: 20px`;
}
}
When binding inline styles, follow the style global attribute guidelines. Consider using the class attribute with a stylesheet in your component bundle for reusability first. Using inline styles can be helpful when you need to compute properties to generate different styles based on a condition. For example, you want to append a background color that depends on the given icon name.
get computedStyles() {
if (this.iconName) {
const color = getIconColor(this.iconName);
if (color) {
return `background-color: ${color}`;
}
}
const fallbackColor = '#eee';
return `background-color: ${fallbackColor}`;
}
Here's an example where you can use an input field to change the size of a chart bar using inline styles. The api-property parent component assigns the percentage property based on user input. It uses the property to pass a value down to the child chart-bar component. The child component evaluates the inline style based on the percentage value that's passed down.
# CSS Support and Performance Impact
The CSS scoping matches the CSS Scoping Module Level 1 standard, with a few exceptions.
- No support for the
:host-context()pseudo-class function. - No support for ID selectors in CSS or JavaScript.
Important
LWC uses id values for accessibility only. When the template is rendered, id values are transformed into globally unique values. Don't use ID selectors in JavaScript or in CSS. If you do, the selector won’t match the transformed ID and you get an error.
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>
Due to an optimization that improves render time for your Lightning web components, values for style and class attributes of your static nodes can render with extra whitespaces or unexpected characters. Update your JavaScript code that uses class or style attributes because this change can affect them.
Previously, you could include a whitespace to query elements using their class names by using an exact attribute string match.
**Don't do this**
document.querySelector('[class="highlight yellow"]')
This used to work because the attribute highlight yellow had rendered as shown.
<div class="highlight yellow">
However, that attribute can now render with an extra whitespace.
<div class=" highlight yellow">
Revise the JavaScript code to use a selector that disregards whitespaces.
**Do this instead**
document.querySelector('.highlight.yellow')
# Assign CSS Stylesheets to a Component with the stylesheets Property
To customize a component with one or move stylesheets, add the stylesheets static property to the LightningElement constructor. This property accepts an array of stylesheets, and its default value is an empty array. You can set the stylessheets property for light DOM and shadow DOM components.
For example, to inject the header-styles.css and button-styles.css stylesheets into myComponent, configure the stylesheets property in myComponent.js.
myComponent/
├── myComponent.js
├── myComponent.html
├── myComponent.css
├── header-styles.css
└── button-styles.css
// c/myComponent.js
import { LightningElement } from 'lwc';
import headerStyles from './header-styles.css';
import buttonStyles from './button-styles.css';
export default Example class extends LightningElement {
static stylesheets = [
headerStyles,
buttonStyles
];
}
The first stylesheet the LWC engine injects is myComponent.css, since it's implicitly associated with the component's template. Then the engine loads all the stylesheets associated with the stylesheets property in the order that they're listed inside the array. Based on this configuration of stylesheets, myComponent loads its stylesheets in the following order: myComponent.css, header-styles.css, and button-styles.css.
The LWC engine caches the stylesheets array for the lifetime of the application during the component class definition. If you modify stylesheets after the component’s code is evaluated, it won’t affect the injected stylesheets.
A subclass doesn’t automatically inherit stylesheets from a superclass. If you want to extend stylesheets from a superclass to a subclass, use super.stylesheets to manually merge the superclass stylesheets with the stylesheets for the subclass component.
import { LightningElement } from 'lwc';
import superclassStylesheet from './superclass.css';
import subclassStylesheet from './subclass.css';
class Superclass extends LightningElement {
static stylesheets = [
superclassStylesheet
];
}
class Subclass extends Superclass {
static stylesheets = [
...super.stylesheets,
subclassStylesheet
];
}
# Associate CSS Stylesheets to a Component Programmatically
To dynamically apply a stylesheet to a template, use programmatic style injection:
import template from './component.html';
import stylesheet from './stylesheet.css';
export default class extends LightningElement {
static stylesheets = [stylesheet];
render() {
return template;
}
}
If you need the ability to render the same template with multiple stylesheets, consider using a mixin. For instance, start with a base class that renders a particular template:
// base.js
import template from './component.html';
export default class extends LightningElement {
render() {
return template;
}
}
Then create a StyleMixin function:
// styleMixin.js
export const StyleMixin = (superclass, stylesheet) => {
return class extends superclass {
static stylesheets = [stylesheet];
};
};
And then create a red or blue variant using red.css or blue.css:
// red.js
import Base from './base.js';
import { StyleMixin } from './styleMixin.js';
import redStylesheet from './red.css';
export default StyleMixin(Base, redStylesheet);
// blue.js
import Base from './base.js';
import { StyleMixin } from './styleMixin.js';
import blueStylesheet from './blue.css';
export default StyleMixin(Base, blueStylesheet);
This creates two components, red.js and blue.js, that share the same template but use different stylesheets.
# Deprecated template mutation
For historical reasons, it is possible to dynamically override the stylesheets for an HTML template by mutating the template object.
The code below shows an example of this, but please do not do this:
import template from './component.html';
import stylesheet from './stylesheet.css';
export default class extends LightningElement {
render() {
// NOTE: DO NOT DO THIS
template.stylesheets = [stylesheet];
template.stylesheetToken = 'foo';
return template;
}
}
In a future version of LWC, this template object will be frozen and any modifications will be disallowed.
Instead of using this deprecated workaround, you have a few options:
- To share one stylesheet with multiple HTML templates, use programmatic style injection as described above. Return any HTML template you want from the
render()function, and use thestatic stylesheetsproperty to style all HTML templates. - To share multiple stylesheets with one HTML template, if you cannot use a subclass or mixin as described above, then consider using CSS custom properties or classes instead. An example using custom properties can be found below.