class attribute or dynamically setting CSS custom properties (variables).
Building responsive, user-friendly Lightning interfaces often requires visual cues like alert states, interactive toggles, or dynamic status badges. In this tutorial, you will learn standard, platform-compliant patterns for handling dynamic styling in LWC without violating Shadow DOM encapsulation.
Prerequisites
- A Salesforce Developer Edition, Sandbox, or Scratch Org.
- Salesforce CLI (
sf) configured in your workspace. - Familiarity with standard LWC reactivity and JavaScript getters.
Step 1: Set Up the Component Structure
sf lightning generate component -n dynamicStylingDemo -d force-app/main/default/lwc --type lwc
Step 2: Define Component Styles in CSS
In LWC, standard component styles placed in dynamicStylingDemo.css are automatically scoped to the component's Shadow DOM. There is no need to manually import the CSS file inside your JavaScript code.
:host {
display: block;
}
/* Base button wrapper styling */
.action-box {
padding: 1rem;
border-radius: 8px;
transition: all 0.3s ease-in-out;
}
/* Dynamic theme states */
.theme-default {
background-color: #f3f3f3;
border: 1px solid #d8dde6;
color: #181818;
}
.theme-active {
background-color: #e2efda;
border: 1px solid #a9d18e;
color: #375623;
}
.theme-alert {
background-color: #fce4e4;
border: 1px solid #e06666;
color: #7a1414;
}
import styles from './component.css' or using static static styles = [styles] in standard on-platform LWC. The Salesforce build compiler automatically links your same-named CSS file (<componentName>.css) to your template at build time.
Step 3: Implement Reactive Styling Logic in JavaScript
Open dynamicStylingDemo.js. Use tracked state properties and clean JavaScript getters to calculate and return CSS class strings dynamically:
import { LightningElement } from 'lwc';
export default class DynamicStylingDemo extends LightningElement {
currentStatus = 'default'; // 'default', 'active', 'alert'
// Getter computing dynamic class string based on state
get boxClass() {
let dynamicClass = 'action-box ';
if (this.currentStatus === 'active') {
dynamicClass += 'theme-active';
} else if (this.currentStatus === 'alert') {
dynamicClass += 'theme-alert';
} else {
dynamicClass += 'theme-default';
}
return dynamicClass;
}
get statusLabel() {
return this.currentStatus.toUpperCase();
}
setNormal() {
this.currentStatus = 'default';
}
setActive() {
this.currentStatus = 'active';
}
setAlert() {
this.currentStatus = 'alert';
}
}
Step 4: Build the HTML Template
In dynamicStylingDemo.html, bind the container's class attribute directly to your reactive {boxClass} getter:
<template>
<lightning-card title="Dynamic Styling in LWC" icon-name="utility:brush">
<div class="slds-p-around_medium">
<!-- Dynamic Container -->
<div class={boxClass}>
<h3 class="slds-text-heading_small slds-m-bottom_x-small">
Current Component State: <strong>{statusLabel}</strong>
</h3>
<p>The background, border, and font colors update automatically as state changes.</p>
</div>
<!-- Interactive Controls -->
<div class="slds-m-top_medium slds-button-group" role="group">
<lightning-button label="Default" onclick={setNormal}></lightning-button>
<lightning-button variant="success" label="Active State" onclick={setActive}></lightning-button>
<lightning-button variant="destructive" label="Alert State" onclick={setAlert}></lightning-button>
</div>
</div>
</lightning-card>
</template>
- Class Getters: Preferred method for toggling predefined CSS classes based on component data state.
- CSS Custom Properties: Use
style="--custom-color: {dynamicColor}"when colors or pixel values must be calculated arbitrarily from runtime data. - Shadow DOM Boundary: Scoped CSS rules within an LWC will not leak into or affect parent or sibling components on the page.
Step 5: Expose and Deploy the Component
Update dynamicStylingDemo.js-meta.xml to expose the component to Lightning App Builder:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>60.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
# Deploy the component bundle
sf project deploy start
# Open target org in browser
sf org open
- In Salesforce Setup, navigate to Lightning App Builder.
- Drop
dynamicStylingDemoonto any test page layout, save, and activate. - Click the action buttons to see instant, reactive CSS theme switching in real time.
class attribute provides a clean, reactive, and maintainable approach to dynamic styling that adheres directly to Salesforce Shadow DOM standards.