Lightning Web Components (LWC) from Salesforce are based on standard Web Components built using HTML and JavaScript. They are lightweight, easy to build, and perform well in modern browsers. When building LWCs, you’ll become familiar with the concept of composition: piecing together simple building-block components within the body of a more complex component.
Regarding composition, LWC leverages the Shadow Document Object Model (DOM) web standard, which encapsulates the internal structure of a Web Component and makes it inaccessible to code and components outside of the component. The alternative to this approach is Light DOM, which Salesforce makes available in beta.
In this post, we’ll explore in detail the concept of Light DOM in Salesforce development. We’ll begin with an overview of the DOM concept, followed by the differences between Shadow DOM and Light DOM. Finally, we’ll look at how this plays out in LWC, along with how to implement Light DOM in LWC.
Taking the definition from MDN, the DOM is “the data representation of the objects that comprise the structure and content of a document on the web.” That means: The DOM provides a way to represent a web page in a tree-like structure as nodes and objects. This makes it easier for developers to manipulate and build out any logic as required.
It’s important to note that the DOM is independent of any programming language. A web application built using any language or framework would typically provide access to the DOM and its components in one way or another.
Perhaps you’ve come across the “Shadow DOM”, which is basically an extension of the DOM that allows hidden DOM trees to be attached as elements in the regular DOM tree. MDN uses this graphic to represent the Shadow DOM:
The intent of the Shadow DOM is to provide encapsulation for an individual component in the DOM, keeping the markup structure, style, and behavior of that component hidden and separate from other code on the page. Developers can share that component as a full DOM tree (“shadow tree”), ensuring that no outside code can manipulate that tree. This helps keep the code well segregated and avoids clashing.
The term “Light DOM” is just another name used for the normal or regular DOM, to distinguish it from the Shadow DOM. The “Shadow Boundary” separates the Light DOM from the Shadow DOM. LWC, just like any Web Component, enforces the Shadow DOM on every component. By using the Light DOM approach, which is currently a feature in beta Service and generally available only for Salesforce Experience Builder sites, components are attached to the host element instead of its shadow tree.
Let’s look at what this means in greater detail.
Because the Shadow DOM web standard is not implemented in all browsers that Salesforce supports, LWC uses a Shadow DOM polyfill named Synthetic Shadow DOM. The following markup shows a sample shadow tree structure:
<c-my-app>
#shadow-root
<div>
<p>My Tasks</p>
</div>
<c-my-item>
#shadow-root
<div>
<p>Item 1</p>
</div>
</c-my-item>
</c-my-app>
Shadow DOM prevents us from extracting DOM elements by using references to document
or document.body
. Instead, an LWC component needs to access the tree by using this.template.querySelector()
.
CSS is also affected by Shadow DOM encapsulation. Style from outside of the component can only affect the top level of the component and cannot affect parent, child, or sibling CSS.
The LWC architecture leverages Lightning Locker Service to enforce DOM access containment.
Components are segregated from one another by using namespaces, and each component can only traverse its DOM and access elements in the same namespace. This is a significant limitation (albeit intentional), making the component inaccessible to programmatic code. This measure prevents script injections and style leaks. Light DOM allows developers to circumvent this security restriction.
To lift DOM access restrictions imposed by the Shadow DOM, Salesforce has introduced the concept of working with Light DOM in LWC. Even though the feature is currently in beta, it’s clearly the way forward for DOM manipulation for LWCs.
The idea is this: Since the LWC resides outside the Shadow DOM, none of the Shadow DOM limitations apply to the component.
Below is a brief comparison of how Shadow DOM and Light DOM impact an LWC.
Feature |
Light DOM |
Shadow DOM |
---|---|---|
Global CSS Theming with a master style sheet |
Full Support |
No Support, CSS is defined at component level and does not cascade. |
Third-Party Tools |
Full Support for DOM traversal |
Limited support as third-party tools can only access their parent component. |
Programmatic DOM Access |
Not limited by namespace |
Limited by namespace |
Portability |
Portable but cause breaking changes |
Portable with secure access |
Highly Customizable UI |
Good fit |
Not a good fit |
Let’s look at a simple example of how Light DOM works with an LWC component. This is a simple template directive for a MyApp LWC that uses the Shadow DOM by default.
<template>
<my-header>
<p>My Tasks</p>
</my-header>
</template>
To enable light DOM, we simply need to set the renderMode
property as follows:
import { LightningElement } from 'lwc';
export default class MyApp extends LightningElement {
static renderMode = 'light';
}
Next, we change our template directive to use Light DOM instead of Shadow DOM:
<template lwc:render-mode='light'>
<my-header>
<p>My Tasks</p>
</my-header>
</template>
Elements can be accessed in Light DOM using the document.querySelector()
method. This is a powerful way for developers to access and manipulate elements as needed.
In Light DOM, we would use this.querySelector
. In Shadow DOM, we would need to use this.template.QuerySelector
.
When it comes to event propagation, Light DOM is a big uplift for developers. Shadow DOM retargets any events which cross the shadow boundary. There is no such event retargeting in Light DOM, and it’s easy for developers to identify the exact UI element that triggered an event instead of getting a reference to the underlying component.
Salesforce has provided a set of guidelines and limitations for developers using Light DOM, which you can find here.
LWC provides a simple and powerful approach to crafting complex web components. Up to this point, while Salesforce has used the Shadow DOM standard in LWC for the purposes of encapsulation and secure access, developers may encounter many scenarios in which the Light DOM approach is fitting and appropriate. With Light DOM now offered in beta, Salesforce developers can now make the choice for themselves based on their use case.