Styling hooks use CSS custom properties which make it easy to customize component styling and express your brand.
Before Getting Started
This documentation assumes you have an understanding of standards-based web technologies and the Salesforces platform. Additionally, we recommend having a solid grasp of these concepts:
These topics include concepts that are core to styling hooks. Understanding these topics beforehand is extremely beneficial when reading our documentation.
General Audience (GA)
As of the 2.17.0 (Spring '22) release, styling hooks is officially designated for General Audience (GA) use! This release adds CSS Custom Property capabilities throughout our supported components, creates a legacy stylesheet for browsers that do not support CSS Custom Properties (e.g., IE11), and updates the namespace of these hooks. Developers can now use all of the existing styling hooks in a fully supported way to customize the look and feel of their Lightning components!
Migrating Namespaces
As mentioned above, we changed the styling hooks namespace as part of the GA effort. From here on out, the official styling hooks namespace for SLDS will be --slds
. The old namespace, --sds
, will continue to function in the short term; however, it is best to migrate if you have existing declarations using the old namespace.
Migration should be a straightforward process, as no other part of the styling hooks syntax has changed. For all of your existing --sds
declarations, migrating them to --slds
will put you on the long-term support path. For the most up-to-date information on available component styling hooks, please visit the Blueprint Overview page and select your desired component.
New in Summer ’24
At Salesforce, we’re continuously improving our user interface architecture and planning for the future. Because, we’re planning to replace --lwc
custom properties with --slds
styling hooks in a future release (safe harbor). In the Summer ’24 release, the --lwc
custom properties still work in Lightning pages and Experience Cloud sites. However, in Lightning pages you are strongly encouraged to replace --lwc
custom properties during the Summer ’24 release with --slds
styling hooks to avoid regressions when they are removed.
What are Styling Hooks?
Styling hooks use CSS custom properties which make it easy to customize component styling and express your brand, especially when working with web components and shadow DOM.
Below is an example of a custom container with a checkbox using styling hooks.
.my-css {
padding-block: 0.5rem;
padding-inline: 1rem;
margin-block: 0.5rem;
background: white;
border: 1px solid #014486;
border-radius: 0.5rem;
}
.my-checkbox {
border-color: #014486;
background: #cfe9fe;
}
.slds-checkbox [type=checkbox]:checked + .slds-checkbox__label .my-checkbox {
background: #fff;
}
If you're working in Lightning Web Components (LWC) and Salesforce Lightning Design System (SLDS), styling hooks will enable customization for your Lightning components in an elegant and supported fashion.
Currently, we are focusing exclusively on component-level customizations. Theming will be available in a future version.
What Does the Code Look Like?
At its heart, styling hooks are constructed using CSS custom properties, (also referred to as CSS variables or cascading variables). Here’s a simple example using our badge blueprint which contains styling hooks.
Badge Label
.slds-badge {
background-color: var(--slds-c-badge-color-background, #ECEBEA);
border-radius: var(--slds-c-badge-radius-border, 15rem);
color: var(--slds-c-badge-text-color, #080707);
}
Lets take the background color property and break down its associated styling hooks implementation, piece by piece.
var(…)
This is a CSS function that enables you to use the stored value of a CSS custom property. It accepts two arguments: a CSS custom property and an optional fallback value. In our example, --slds-c-badge-color-background
is our first argument, the CSS custom property, and #ECEBEA
is our second argument, the fallback value.
Learn more about the var()
function on MDN
--slds
Declaring a custom property requires that the name begins with double hyphens (--
). slds
is a namespace reserved for the Salesforce Lightning Design System.
-c
This identifier indicates that the custom property is a component-level customization within SLDS. It is specific to the component it resides in and does not affect unrelated components.
Curious about themed customizations? See the Theming FAQ
-badge
badge
refers to the name of the component that is being targeted by the custom property. In our example, our component is named badge so we include badge in the name of our custom property.
-color
To provide predictability, we’ve defined several categories that classify our naming conventions. In this instance, -color
identifies the category that this CSS custom property falls under.
For a full list of our categories, see Naming Convention categories
-background
This is the semantic user interface property being customized. This example is referencing the background
property.
#ECEBEA
This is the fallback value if the CSS custom property is not valid. In styling hooks, this value is defined by the design system using a token and is not changeable. It is the sensible default of the design system.
See Naming Conventions for more detailed information regarding our naming conventions.
How Does it Work?
In the following section, we assume you have a working knowledge of Lightning Web Components (LWC). If not, you can find excellent information and documentation about Salesforce’s open-source, enterprise-grade web components foundation at developer.salesforce.com.
Even if you’re not working in LWC, this section provides helpful guidance for working with styling hooks.
Setup
To show a basic example of styling hooks in action, we’ll create a component that contains the badge Lightning web component. For more information around CSS custom properties and base Lightning components, visit the official base components documentation.
myComponent.html
<template>
<lightning-badge label="Badge Label"></lightning-badge>
</template>
myComponent.css
myComponent.js
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {}
We won’t be touching myComponent.js
but it is required to get your component up and running.
We can use the special CSS pseudo-class :host
to declare our CSS custom properties within our custom component myComponent
. The pseudo-class, :host
scopes our styles to the shadow host of the shadow DOM and is one of several useful ways to scope your styles. To dive deeper into the different types of scopes, see the Scoping section.
Styling Hooks ❤️ Tokens
It's best to assign styling hooks using tokens. This makes your CSS simpler and easier to maintain. SLDS Design Tokens provide a convenient set of standardized values.
Learn More
Example A
In our CSS, we’ll add custom properties to the :host
pseudo-class that correspond to the styling hooks in lightning-badge
.
In this example, we'll reference standard SLDS Design Tokens that are only available to internal developers. --lwc-paletteOrange80
will be used to configure the --slds-c-badge-color-background
styling hook. We'll also configure the text color using --slds-c-badge-text-color
to avoid any unexpected accessibility issues.
Components and Variants
Before customizing a component using styling hooks, it's best to first utilize standard variants provided by the component. SLDS offers several classes for use with lightning-badge
that result in standard color variations with specific meanings.
View Variants
Accesssibility Requirement
Change contrasting semantic properties in unison. For example, you should customize both the background and text color styling hooks at the same time. This ensures that the color contrast won't change unexpectedly.
This customizes the background color of the badge.
:host {
--slds-c-badge-color-background: var(--lwc-paletteOrange80); // internal only token
--slds-c-badge-text-color: var(--lwc-paletteNeutral10); // internal only token
}
Example B
For our next example, let's use custom Aura tokens to achieve a different look for our unique brand.
Custom Tokens
When developing Lightning web components use custom Aura tokens to create and manage your own collection of tokens. Custom Aura tokens, created in your org or installed from an unmanaged package, can be shared across all of your web components. In your web component's CSS file, reference the custom token using the --c-
namespace prefix.
Learn More
:host {
--slds-c-badge-color-background: var(--c-example-purple);
--slds-c-badge-text-color: var(--c-example-white);
}
Example C
In our last example, we’ll add one more CSS custom property for an even more distinct feel.
:host {
--slds-c-badge-color-background: var(--c-example-purple);
--slds-c-badge-text-color: var(--c-example-white);
--slds-c-badge-radius-border: var(--c-example-border-radius-small);
}
By declaring our own CSS custom properties within our custom component’s :host
, we can assign values to the styling hooks and change the look and feel of our badge without ever touching the internal CSS of the component or needing to be intimately familiar with how the badge is built under the hood!
Advanced Usage
This section showcased a basic usage of styling hooks. You may run into instances where you want to customize a specific part of an experience component or limit the reach of your custom properties to a certain area of your app.
The Scoping section will provide guidance on these advanced customizations.
Naming Conventions
Styling hooks follows a specific naming convention to promote predictability and consistency. All SLDS styling hooks adhere to the following convention.
--[namespace]-[scope]-[component]-[element]-[category]-[property]-[attribute]-[state]
Identifier | Example | Description | Required |
---|
Namespace | --slds | The namespace of the system that owns the hook. | ✓ |
---|
Scope | -c | The scope defines the reach of the hook. Note: The scope -c is different from the custom Aura token namespace --c . | ✓ |
---|
Component | -button | Name of the component. | ✓ |
---|
Element | -footer | The descendent element of the component. | Optional |
---|
Category | -color | The category of the property that the hook affects. | ✓ |
---|
Property | -background | The semantic UI property being affected. | Optional |
---|
Attribute | -small | The semantic characteristic of a property. | Optional |
---|
State | -hover | The state of a property within the context of interaction design. | Optional |
---|
Usage Combinations and Examples
Naming conventions are prescribed in the previously listed order but can be used in multiple combinations with one another.
--slds-c-button-color-background
--slds-c-accordion-heading-font-size
--slds-c-button-sizing-width-small
--slds-c-button-color-background-hover
Categories
Directional Support
We aim to align with the flow-relative directional keywords found within the CSS logical properties W3C specification.
--slds-c-[component]-spacing-inline-start
--slds-c-[component]-spacing-inline-end
--slds-c-[component]-spacing-block-start
--slds-c-[component]-spacing-block-end
Implicit vs Explicit
There may be times when a single custom property used multiple times throughout a component makes more sense than declaring several unique custom properties to do the same job. When a custom property is used in the former fashion, we define it as implicit and for the latter, explicit.
Each have their use cases and we allow for both implicit and explicit naming conventions with a set of rules delineating the two.
Implicit (component-level)
- Custom property has multiple instances in the component that are expected to share the same value
- Custom property describes the component as a whole, not an individual piece of the component
- Custom property has only a single use case in the component and describes the component (e.g. a container)
--slds-c-[component]-radius-border
Explicit (element-level)
- Custom property is specific to an element and not reusable across other properties, expects a unique value
- Custom property may exists across multiple use cases in a component but do not share a relationship
- Custom property does not describe the component as a whole, it describes a specific piece of the component in isolation
--slds-c-[component]-[element]-color-background
Scoping
Within the context of CSS custom properties, scoping refers to the region in which custom properties are valid and inheritable by any descendant custom properties. Your scope is determined by the selector you decide to use.
Global
Applying custom properties to the global scope causes all applicable custom properties in your document to inherit from your global scope unless you define custom properties lower in the document tree.
:root
is the most common global scope when it comes to custom properties. :root
is a pseudo-class that targets the top-level element of a document. If :root
is not accessible, target the highest available element in your document.
Learn more about :root
on MDN
Lightning Web Components
:root
is not available in Lightning web components. Use :host
as described below.
:root {
--slds-c-badge-color-background: var(--c-example-blue);
}
.top-level-element-available {
--slds-c-badge-color-background: var(--c-example-blue);
}
Element
You can scope your custom properties to a standard HTML element and have all its descendants inherit from it. Keep in mind the cascade, specificity, and inheritance still applies.
h1 {
--slds-c-badge-color-background: var(--c-example-blue);
}
Class
You can scope your custom properties to a CSS class and have all its descendants inherit from it. Keep in mind the cascade, specificity, and inheritance still applies.
.my-class {
--slds-c-badge-color-background: var(--c-example-blue);
}
:host
:host
is a pseudo-class that targets the shadow host of the shadow DOM. Adding your custom properties to :host
ensures your custom properties are scoped to the custom element that contains the shadow DOM. Keep in mind user styles always win over any styles inside :host
.
:host {
--slds-c-badge-color-background: var(--c-example-blue);
}
:host my-custom-element {
--slds-c-badge-color-background: var(--c-example-blue);
}
:host my-custom-element another-custom-element {
--slds-c-badge-color-background: var(--c-example-blue);
}
Examples
There are multiple ways to use styling hooks; how you use styling hooks depends on your project’s needs and constraints. The following examples are potential use cases, not official SLDS guidelines or patterns.
We’ll use the following use case for our examples.
Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
<div class="app slds-grid slds-gutters">
<section className="slds-col slds-size_1-of-1 slds-medium-size_1-of-2 slds-m-bottom_large section section-astro">
<article class="slds-card">
<div class="slds-card__header">
<header>
<h3 class="slds-card__header-title slds-text-heading_large">
Astro
</h3>
</header>
</div>
<div class="slds-card__body slds-card__body_inner">
<p>
Astro is your friendly guide to everything at Salesforce and helps
you become the best at anything you want to do. Warm and
welcoming, they encourage the Salesforce community to achieve
their goals through trying new things, asking questions, and
having fun. Curious and always wanting to learn.
</p>
<div class="slds-badge special">Curious</div>
<div class="slds-badge">Traveler</div>
<div class="slds-badge">Welcoming</div>
</div>
</article>
</section>
<section className="slds-col slds-size_1-of-1 slds-medium-size_1-of-2 slds-m-bottom_large section section-codey">
<article class="slds-card">
<div class="slds-card__header">
<header>
<h3 class="slds-card__header-title slds-text-heading_large">
Codey
</h3>
</header>
</div>
<div class="slds-card__body slds-card__body_inner">
<p>
It’s hard not to notice Codey—he’s the bear tackling projects and
getting his paws dirty, all while having a great time. Codey is a
maker and a builder. Whether it’s coding an app on Salesforce, or
pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed
or dive in to get things done.
</p>
<div class="slds-badge">Builder</div>
<div class="slds-badge">Fearless</div>
<div class="slds-badge">Hugger</div>
</div>
</article>
</section>
</div>
Global
Global scoping is a good option if you want to set a custom property once and have it affect your entire document or app.
Apply your custom properties to .app
. This selector is the container for our application. Your global container may be different. The higher in your DOM tree you place your custom properties, the larger your scope.
.app {
--slds-c-badge-color-background: var(--c-example-blue);
--slds-c-badge-text-color: var(--c-example-white);
}
Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
If you are working on the Salesforce platform, keep in mind access to :root
is disabled. Alternatively, target the parent container of your app.
Selector
If you want to bundle your custom properties with a selector, you place your custom properties in a selector that is applied to your markup. This is typically a class although any valid selector will work.
.section-astro {
--slds-c-badge-color-background: var(--c-example-blue);
--slds-c-badge-text-color: var(--c-example-white);
}
.section-codey {
--slds-c-badge-color-background: var(--c-example-purple);
--slds-c-badge-text-color: var(--c-example-white);
}
Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
A selector doesn’t have to scope to a region. It can be applied to a selector that lives on a single element to limit its scope.
.section-astro {
--slds-c-badge-color-background: var(--c-example-blue);
--slds-c-badge-text-color: var(--c-example-white);
}
.section-codey {
--slds-c-badge-color-background: var(--c-example-purple);
--slds-c-badge-text-color: var(--c-example-white);
}
.special {
--slds-c-badge-color-background: var(--c-example-pink);
--slds-c-badge-text-color: var(--c-example-black);
}
Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
Web Components
We’ll update our example with a simple web component called fancy-greeting
.
…
<div class="slds-card__body slds-card__body_inner">
<fancy-greeting>Hello!</fancy-greeting>
<p>
Astro is your friendly guide to everything at Salesforce and helps
you become the best at anything you want to do. Warm and
welcoming, they encourage the Salesforce community to achieve
their goals through trying new things, asking questions, and
having fun. Curious and always wanting to learn.
</p>
<div class="slds-badge special">Curious</div>
<div class="slds-badge">Traveler</div>
<div class="slds-badge">Welcoming</div>
</div>
…
…
<div class="slds-card__body slds-card__body_inner">
<fancy-greeting>Howdy!</fancy-greeting>
<p>
It’s hard not to notice Codey—he’s the bear tackling projects and
getting his paws dirty, all while having a great time. Codey is a
maker and a builder. Whether it’s coding an app on Salesforce, or
pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed
or dive in to get things done.
</p>
<div class="slds-badge">Builder</div>
<div class="slds-badge">Fearless</div>
<div class="slds-badge">Hugger</div>
</div>
…
Hello!Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
Howdy!It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
A few things to note:
fancy-greeting
exposes two hooks: --example-c-fancy-greeting-color-background
and --example-c-fancy-greeting-text-color
- We’re following our naming conventions with example, placeholder names
- Shadow DOM is enabled (A warning about the shadow DOM)
Custom properties in web components inherit from their scope just like our previous examples. If we revisit our global example, we'll see our web components pick up on our global custom properties.
.app {
--example-c-fancy-greeting-color-background: var(--c-example-gray);
--example-c-fancy-greeting-text-color: var(--c-example-black);
}
Hello!Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
Howdy!It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
As before, scoping to a selector allows us to customize the two sections differently.
.section-astro {
--example-c-fancy-greeting-color-background: var(--c-example-teal);
--example-c-fancy-greeting-text-color: var(--c-example-black);
}
.section-codey {
--example-c-fancy-greeting-color-background: var(--c-example-purple);
--example-c-fancy-greeting-text-color: var(--c-example-white);
}
Hello!Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
Howdy!It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
Targeting the custom elements themselves works as well.
fancy-greeting {
--example-c-fancy-greeting-color-background: var(--c-example-teal);
--example-c-fancy-greeting-text-color: var(--c-example-black);
}
Hello!Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
Howdy!It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
Working with :host
We’ve created a new web component called fancy-container
and updated our example markup.
…
<div class="slds-card__body slds-card__body_inner">
<fancy-greeting>Hello!</fancy-greeting>
<p>
Astro is your friendly guide to everything at Salesforce and helps
you become the best at anything you want to do. Warm and
welcoming, they encourage the Salesforce community to achieve
their goals through trying new things, asking questions, and
having fun. Curious and always wanting to learn.
</p>
<fancy-container>
<div class="slds-badge special">Curious</div>
<div class="slds-badge">Traveler</div>
<div class="slds-badge">Welcoming</div>
</fancy-container>
</div>
…
In fancy-container
‘s CSS, we add SLDS custom properties for badge to its :host
. We then assign values to these styling hooks using our own tokens, referenced using CSS custom properties.
:host {
--slds-c-badge-color-background: var(--c-example-blue, royalblue);
--slds-c-badge-text-color: var(--c-example-white, white);
}
Hello!Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
Howdy!It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
Shadow DOM Disclaimer
The shadow DOM, when enabled, prevents access to the internal DOM of the web component. Attempting to reach into the component from the outside will fail.
fancy-greeting .fancy-text {
text-transform: uppercase;
}
Hello!Astro is your friendly guide to everything at Salesforce and helps you become the best at anything you want to do. Warm and welcoming, they encourage the Salesforce community to achieve their goals through trying new things, asking questions, and having fun. Curious and always wanting to learn.
Curious
Traveler
Welcoming
Howdy!It’s hard not to notice Codey—he’s the bear tackling projects and getting his paws dirty, all while having a great time. Codey is a maker and a builder. Whether it’s coding an app on Salesforce, or pouring lattes as a ‘Bearista’, Codey isn’t afraid to get noticed or dive in to get things done.
Builder
Fearless
Hugger
Our selector fails and the text does not transform to uppercase. Targeting a specific part of a web component that you do not own is not possible. This is by design and promotes component encapsulation.
It is up to the owner of the web component to provide you access. Examples of access is adding ::part
or ::slotted
within the component or turning off the shadow DOM. Unless access is granted, you can only target the parent custom element and have all of its descendants inherit from it.
FAQ
What About Theming Custom Properties?
Currently, component-level customizations (e.g. --slds-c-*
) are the only custom properties that are available.
Global styling capabilities that allow theming are in the works but not within scope. When global styling is introduced, it will be an additive feature that will not break any of your existing styling hooks usage.
What Styling Hooks are Available for Blueprint X?
Styling hooks are being gradually rolled out. You can track which components have styling hooks in the component list page.
Glossary
Terms
Acronyms