CSS in Salesforce LWC: Details and Examples
A reference to CSS in Lightning Web Components. Each component has its own CSS file, and its styles stay inside that component. Use SLDS classes and styling hooks for base components, and add JavaScript for dynamic styling.
01How CSS Works in LWC
| CSS Feature | Details | Example |
|---|---|---|
myComponent.css |
A CSS file with the same name as the component folder is applied to that component automatically. No import is needed. | force-app/.../lwc/myComponent/myComponent.css |
Scoped styles |
Styles stay inside the component's shadow DOM, so they do not affect parent, child or sibling components. | .title { color: #0b5cab; } |
Class selectors |
The recommended way to target elements in an LWC template. | <p class="title">Account Details</p> |
ID selectors |
Avoid them. LWC changes id values at runtime, so #id rules may not match. | .header { } /* not #header */ |
Base components |
CSS cannot reach inside lightning-* components. Use SLDS classes or styling hooks instead. | <lightning-button class="slds-m-left_small"></lightning-button> |
02Selectors in LWC
| CSS Feature | Details | Example |
|---|---|---|
:host |
Styles the component's own host element. | :host { display: block; } |
:host(.selector) |
Styles the host only when it has a given class. | :host(.compact) { padding: 4px; } |
Element selector |
Targets tags in the component template only. | p { margin: 0; } |
Attribute selector |
Targets elements by attribute. | input[type="email"] { width: 100%; } |
:hover / :focus |
State pseudo-classes work as normal. | .card:hover { border-color: #1a73e8; } |
:nth-child() |
Styles items by position, useful for list and table rows. | tr:nth-child(even) { background: #fafcfe; } |
::before / ::after |
Adds decorative content before or after an element. | .required::after { content: " *"; color: #ba0517; } |
03Box Model and Spacing
| CSS Feature | Details | Example |
|---|---|---|
margin |
Space outside an element. | margin: 0 0 12px; |
padding |
Space inside an element. | padding: 16px; |
border |
Line around an element. | border: 1px solid #dfe7ef; |
border-radius |
Rounds the corners. | border-radius: 8px; |
box-sizing |
Includes padding and border in the element's width. | box-sizing: border-box; |
width / max-width |
Sets or limits the width. | max-width: 600px; width: 100%; |
overflow |
Controls content that does not fit. | overflow-x: auto; |
04Layout
| CSS Feature | Details | Example |
|---|---|---|
display: flex |
One-direction layout for rows or columns. | .row { display: flex; gap: 12px; } |
justify-content |
Aligns flex items on the main axis. | justify-content: space-between; |
align-items |
Aligns flex items on the cross axis. | align-items: center; |
flex-wrap |
Lets flex items move to the next line. | flex-wrap: wrap; |
display: grid |
Two-direction layout with rows and columns. | .grid { display: grid; grid-template-columns: repeat(2, 1fr); } |
gap |
Space between flex or grid items. | gap: 1rem; |
position |
Places an element relative to its container. | .badge { position: absolute; top: 8px; right: 8px; } |
05Text and Colors
| CSS Feature | Details | Example |
|---|---|---|
color |
Text color. | color: #0f172a; |
background-color |
Background color. | background-color: #edf5ff; |
font-size |
Text size. | font-size: 14px; |
font-weight |
Text thickness. | font-weight: 600; |
line-height |
Space between lines. | line-height: 1.6; |
text-align |
Horizontal alignment of text. | text-align: center; |
text-overflow |
Shows an ellipsis for long text. | white-space: nowrap; overflow: hidden; text-overflow: ellipsis; |
06Custom Properties and Responsive CSS
| CSS Feature | Details | Example |
|---|---|---|
CSS variables |
Define reusable values on :host and use them in the component. | :host { --brand-color: #0b5cab; } .title { color: var(--brand-color); } |
@media |
Changes styles for smaller or larger screens. | @media (max-width: 600px) { .grid { grid-template-columns: 1fr; } } |
Relative units |
rem, %, and fr scale better across devices. | padding: 1rem; width: 50%; |
transition |
Smooth change between states. | transition: background-color 0.2s ease; |
07SLDS Utility Classes
| CSS Feature | Details | Example |
|---|---|---|
slds-p-around_medium |
Adds medium padding on all sides. | <div class="slds-p-around_medium">Content</div> |
slds-m-top_small |
Adds small top margin. | <p class="slds-m-top_small">Note</p> |
slds-text-heading_medium |
Medium heading text style. | <h2 class="slds-text-heading_medium">Contacts</h2> |
slds-grid / slds-col |
SLDS grid layout. | <div class="slds-grid slds-gutters"><div class="slds-col">One</div></div> |
slds-size_1-of-2 |
Sets a column to half width. | <div class="slds-col slds-size_1-of-2">Half</div> |
slds-align_absolute-center |
Centers content both ways. | <div class="slds-align_absolute-center">Loading</div> |
slds-truncate |
Cuts long text with an ellipsis. | <p class="slds-truncate">Long account name</p> |
08Styling Hooks for Base Components
| CSS Feature | Details | Example |
|---|---|---|
What they are |
CSS custom properties that Salesforce exposes to change the look of base components safely. | --slds-c-button-brand-color-background |
Button background |
Sets the brand button background color. | :host { --slds-c-button-brand-color-background: #0b5cab; } |
Button border |
Sets the brand button border color. | :host { --slds-c-button-brand-color-border: #0b5cab; } |
Where to set them |
Set hooks on :host or a wrapper class so they only affect this component. | .actions { --slds-c-button-brand-color-background: #2e844a; } |
09Sharing and Loading CSS
| CSS Feature | Details | Example |
|---|---|---|
CSS-only module |
Create a component folder with only a CSS file and a meta file, then import it into other components. | @import 'c/sharedStyles'; |
@import rule |
Must be placed at the top of the component's CSS file. | @import 'c/sharedStyles'; .title { font-weight: 600; } |
Static resource |
Upload a CSS file as a static resource and load it with loadStyle. | import { loadStyle } from 'lightning/platformResourceLoader'; |
loadStyle() |
Loads the file once, usually in renderedCallback. The styles apply to the whole page, so use unique class names. | loadStyle(this, customCss); |
Light DOM |
With renderMode set to light, use a myComponent.scoped.css file to keep styles scoped. | static renderMode = 'light'; |
10Dynamic Styling with JavaScript
| CSS Feature | Details | Example |
|---|---|---|
Dynamic class |
Return a class string from a getter. | get boxClass() { return this.isActive ? 'box active' : 'box'; } |
Using the class |
Bind the getter in the template. | <div class={boxClass}>Status</div> |
Dynamic inline style |
Return a style string from a getter. | get barStyle() { return `width: ${this.percent}%`; } |
Using the style |
Bind the style getter in the template. | <div class="bar" style={barStyle}></div> |
CSS variable from JS |
Set a custom property on the host element. | this.template.host.style.setProperty('--accent', '#2e844a'); |
11Rules and Limitations
| CSS Feature | Details | Example |
|---|---|---|
:host-context() |
Not supported in LWC. | :host(.dark) { } /* use instead */ |
::slotted() |
Not supported with synthetic shadow DOM. Style slotted content from the parent component. | .parent-item { color: #0b5cab; } |
Deep selectors |
You cannot style the inside of child or base components from a parent. | :host { --slds-c-button-radius-border: 4px; } |
!important |
Avoid it. Prefer clearer, more specific classes. | .card .title { color: #0b5cab; } |
Global styles |
CSS loaded with loadStyle affects the whole page. Prefix class names to avoid conflicts. | .acme-banner { padding: 8px; } |