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 Salesforce 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.
Beta
As a beta feature, Styling Hooks is a preview. It isn't part of the "Services" under your master subscription agreement with Salesforce. Use this feature at your sole discretion, and make your purchase decisions only on the basis of generally available products and features. Salesforce doesn't guarantee the general availability of this feature within any particular time frame or at all, and we may discontinue it at any time.
This feature is for evaluation purposes only, not for production use. It's offered as-is and isn't supported, and Salesforce has no liability for any harm or damage in connection with its use. All restrictions, Salesforce reservation of rights, obligations concerning the Services, and terms for related Non-Salesforce Applications and Content apply equally to your use of this feature. You can provide feedback and suggestions for styling hooks by filling out our feedback form.
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 the brand button and the brand button using Styling hooks.
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.
For the Winter '21 release, 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(--sds-c-badge-color-background, #ECEBEA);
border-radius: var(--sds-c-badge-radius-border, 15rem);
color: var(--sds-c-badge-color-text, #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, --sds-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
--sds
Declaring a custom property requires that the name begins with double hyphens (--
). sds
is a namespace reserved for Salesforce’s design system.
-c
This identifier indicates that the custom property is a component-level customization. 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 and 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 lwc.dev.
Even if you’re not working in LWC, this section provides helpful guidance 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 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.
Example A
In our CSS, we’ll add custom properties to the :host
pseudo-class that correspond to the custom properties in lightning-badge
. This customizes the background color of the badge:
:host {
--sds-c-badge-color-background: #FF906E;
}
Example B
For our next example, lets change another custom property to achieve a different look:
:host {
--sds-c-badge-color-background: #0C9DDA;
--sds-c-badge-color-text: #FFFFFF;
}
Example C
In our last example, we’ll add one more CSS custom property for an even more distinct feel:
:host {
--sds-c-badge-color-background: #BB00FF;
--sds-c-badge-color-text: #F4F7F9;
--sds-c-badge-radius-border: 4px;
}
By declaring our own CSS custom properties within our custom component’s :host
, we can 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 of our CSS custom properties adhere to the following convention:
COMPONENT_ELEMENT_CATEGORY_PROPERTY_ATTRIBUTE_STATE
Component
— [required] Name of the componentElement
— [optional] Name of the element of the componentCategory
— [required] Indicates the category of the custom property.Property
— [optional] Semantic UI property being described.Attribute
— [optional] Semantic characteristic of a property.State
— [optional] If necessary, the state of a custom property when used in the context of interaction design. E.g. hover, focus, selected
Usage Combinations and Examples
Naming conventions are prescribed in the previously listed order but can be used in multiple combinations with one another:
button-color-background
accordion-heading-font-size
button-sizing-width-small
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.
--sds-c-[component]-spacing-inline-start
--sds-c-[component]-spacing-inline-end
--sds-c-[component]-spacing-block-start
--sds-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)
--sds-c-[component]-color-text
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
--sds-c-[component]-[element]-color-text
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
:root {
--sds-c-badge-color-background: blue;
}
.top-level-element-available {
--sds-c-badge-color-background: 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 {
--sds-c-badge-color-background: 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 {
--sds-c-badge-color-background: 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 {
--sds-c-badge-color-background: blue;
}
:host my-custom-element {
--sds-c-badge-color-background: blue;
}
:host my-custom-element another-custom-element {
--sds-c-badge-color-background: blue; // Inaccessible
}
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 {
--sds-c-badge-color-background: #0C9DDA;
--sds-c-badge-color-text: #FFFFFF;
}
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 {
--sds-c-badge-color-background: #0C9DDA;
--sds-c-badge-color-text: #FFFFFF;
}
.section-codey {
--sds-c-badge-color-background: #BB00FF;
--sds-c-badge-color-text: #F4F7F9;
}
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 {
--sds-c-badge-color-background: #0C9DDA;
--sds-c-badge-color-text: #FFFFFF;
}
.section-codey {
--sds-c-badge-color-background: #BB00FF;
--sds-c-badge-color-text: #F4F7F9;
}
.special {
--sds-c-badge-color-background: #FF538A;
--sds-c-badge-color-text: #111111;
}
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-color-text
- 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: #EEEEEE;
--example-c-fancy-greeting-color-text: #111111;
}
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
And our selector example:
.section-astro {
--example-c-fancy-greeting-color-background: #00E1CB;
--example-c-fancy-greeting-color-text: #111111;
}
.section-codey {
--example-c-fancy-greeting-color-background: #BB00FF;
--example-c-fancy-greeting-color-text: #F4F7F9;
}
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: #00E1CB;
--example-c-fancy-greeting-color-text: #111111;
}
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 our custom properties to its :host
:
:host {
--sds-c-badge-color-background: #0c9dda;
--sds-c-badge-color-text: #FFFFFF;
}
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?
For Winter ‘21, component-level customizations (e.g. --sds-c-*
) will be the only custom properties that will be available.
Global styling capabilities that allow theming are in the works but not within the scope of Winter ‘21. When global styling is introduced, it will be an additive feature that will not break any of your existing styling hooks usage.
What Assignments are Available for Blueprint X?
Styling hooks are being gradually rolled out during the beta phase.
How do I Submit Feedback?
You can provide feedback and suggestions for styling hooks by filling out our feedback form.
Glossary
Terms
Acronyms