Salesforce is preparing Lightning base components to adopt native shadow DOM, which will enhance the components’ performance and better align them to Web Components standards. As part of this preparation phase, we have changed the internal DOM structure of some of our components. We just started, and we’ll continue modifying components’ internals in subsequent releases. In this post, we’ll discuss what will change and how you can prepare for it.
What is native shadow DOM?
Shadow DOM is a web standard that encapsulates a web component’s internal document object model (DOM) structure. This gives us the ability to provide you with robust and secure components by protecting them from being manipulated by arbitrary HTML, CSS, and JavaScript.
Currently, Salesforce maintains a synthetic shadow polyfill for legacy browsers, such as older versions of Microsoft Edge, but now that all major browsers support native shadow DOM, we are preparing our components to do the same.
With the introduction of native shadow DOM, we’ll enhance component encapsulation, making them more consistent and secure, as well as provide a more predictable way to style them. This will solve a myriad of backward compatibility issues and align Lightning web components with web standards.
However, it may bring about an adaptation phase as we make the switch.
The internal implementation of base components is changing
We’ve been working on preparing our base components to adopt native shadow DOM. Specific scenarios in which base components encapsulation were broken required us to create a new container element within the shadow boundary. To help illustrate this, let’s walk through an example base component called lightning-foo
. Before, the component looked like this:
From Summer ’23, it will look like this:
The inner mechanics of base components weren’t designed to be directly accessed and treated as a dependable API for use. Instead, our pre-packaged components were meant to be used just as they are, using the official public APIs we’ve openly shared. However, we know some customers are using components internals in undocumented ways. If you’re accessing the inner elements of a base component for customization and testing purposes, be mindful of these changes.
How can you fix your custom code and tests?
When manually testing your applications, you may detect a previously working custom component that does not look as expected. Due to these changes, your end-to-end automated tests may also fail. In both cases, it may mean that your custom code or test code is relying on the internals of a base component that has changed. Let’s explore these two problems in more depth:
A component doesn’t look as expected:
- Problem: Attempting to style the custom element or classes within a base component may lead to unforeseen results.
- Solution: The switch from synthetic shadow to fully encapsulated components with native shadow DOM may change your CSS strategy. When migrating your styling customizations to native shadow, follow these steps:
- Check for the availability of a styling hook. They offer a superb method for tailoring a component without delving into the complexities of underlying CSS or shadow DOM.
- Ensure the value you’re applying to the styling hook is tied to your design system instead of a fixed, predefined value. Avoid using a hardcoded value.
An end-to-end test fail:
- Problem: Any implementation that uses CSS combinators will fail. For example,
lightning-foo > p
will not match our updated markup. - Solution: Combinators make CSS fragile and should be avoided unless used for a good reason. Most often, combinators can be removed without any regression. If a specific element is desired, other targeting methods that don’t rely on the never-changing markup can be used. That is, avoid explicitly targeting HTML elements whenever possible. Use other available selectors, like classes that allow your CSS usage to be abstracted, modular, and separated from the HTML element. If your tests rely on CSS combinators, we recommend you adopt UI Test Automation Model (UTAM) to avoid future breaking changes as the page objects stay up to date with all component changes.
Conclusion
In summary, we are making significant advancements by preparing the Lightning base components to adopt native shadow DOM, which will ensure better performance and alignment with Web Components standards while also enhancing the security and reliability of the components. By encapsulating the internal DOM structure, we are striving to provide a more robust and predictable experience for developers and users alike.
While these changes may introduce some initial challenges, they are necessary steps toward a more standardized and future-proof system. We remain committed to informing and supporting developers throughout this transition.
In preparation for these changes, we recommend adopting styling hooks and targeting methods like classes to ensure that CSS usage remains modular and adaptable. Furthermore, we strongly recommend adopting UTAM as your end-to-end testing solution.
Stay tuned for further updates and changes as Salesforce continues to optimize and enhance the Lightning component framework. By embracing these upcoming improvements, developers can expect a more seamless and efficient development experience while building powerful applications on the Salesforce Platform.
Further Resources
- For supported end-to-end tests, use the UI Test Automation Model (UTAM) and UTAM Page Objects, which stay up to date with changes in component structure
- For supported Selenium-based tests, see Working With Shadow DOM Elements Using Webdriver
- For supported CSS styling, see CSS in the Lightning Web Components Developer Guide
About the authors
Maeve Tuntivate is a Senior Manager on the Product Management team at Salesforce.
Jesse Brack is a Lead UX Engineer on the Design Systems Engineering team at Salesforce.