DEV Community

Cover image for ShadowDOM: The Underrated Gem Every Web Developer Should Know
Rijul Rajesh
Rijul Rajesh

Posted on

ShadowDOM: The Underrated Gem Every Web Developer Should Know

Understanding ShadowDOM: A Key to Unaltered Web Components

In the world of web development, developers are often tasked with creating components that need to be reusable and independent of the environment they are placed in. This is where Shadow DOM comes into play—a technology that allows developers to encapsulate the internal structure of an element so it remains unaffected by the external styles or scripts around it.

But why is this important? And how has it transformed the user experience for my product LiveAPI? Let’s dive into it!

What is ShadowDOM?

Image description

Shadow DOM is a web standard that provides a way to isolate a piece of the DOM (Document Object Model) within a host element. This isolation means that the internal structure and styling of the shadow tree are kept separate from the rest of the page. In simple terms, it’s like creating a mini-DOM within your DOM that is protected from the outside world.

With Shadow DOM, you can define a component’s HTML, CSS, and JavaScript in a way that ensures it doesn’t clash with other parts of the page. This makes it an essential tool for building reusable, modular, and scalable components.

How ShadowDOM Solved Challenges for LiveAPI

Image description

LiveAPI is a product which I'm developing that helps to build API documentations instantly, by just connecting your Git repositories.

To make the generated documentations interactive, we developed LiveAPI widget which can be embedded. This is where our challenge came in.

In the initial phase we faced a significant challenge when embedding our LiveAPI widget across various websites. Our widget was designed to execute API requests and display the results in a user-friendly way. However, without Shadow DOM, we found that the widget would misbehave in some contexts due to conflicts with other page styles.

Here’s what went wrong:

  • Styles Overriding: The widget’s internal styles would often get overridden by global styles from the host page. This caused the widget to look different depending on where it was embedded, leading to a poor user experience.
  • JavaScript Conflicts: The widget’s JavaScript could also conflict with the host page's scripts, causing unpredictable behavior and making it hard to maintain consistency across platforms.

This is where Shadow DOM came to our rescue. By encapsulating our widget within a shadow tree, we ensured that:

  1. Styles Are Isolated: The widget’s internal CSS is no longer impacted by the host page's external styles, guaranteeing that it looks the same no matter where it’s embedded.
  2. Scripts Don’t Clash: The widget’s JavaScript runs independently, reducing the risk of conflicts with other scripts on the page.

As a result, we were able to create a seamless, consistent experience for our users, regardless of where they placed the widget.

How to Use ShadowDOM: A Simple Guide with Code Examples

Let’s explore how you can use ShadowDOM in your projects.

1. Creating a Shadow DOM

To start using ShadowDOM, you'll need to create a shadow root on an existing element. You can achieve this by calling the attachShadow() method on the element you want to attach the shadow DOM to.

Here's an example of how to create a shadow root for an HTML element:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ShadowDOM Example</title>
</head>
<body>
    <div id="shadow-host">This is the shadow host element.</div>

    <script>
        // Step 1: Select the element you want to attach the shadow root to
        const host = document.getElementById('shadow-host');

        // Step 2: Attach a shadow root to the host element
        const shadowRoot = host.attachShadow({mode: 'open'});  // "open" allows access to the shadow DOM

        // Step 3: Add content to the shadow root
        shadowRoot.innerHTML = `
            <style>
                p {
                    color: blue;
                    font-size: 20px;
                }
            </style>
            <p>This content is inside the shadow DOM!</p>
        `;
    </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

In this example:

  • The attachShadow() method creates a shadow root on the #shadow-host element.
  • The mode: 'open' option means that the shadow DOM is accessible via JavaScript (you can also use mode: 'closed' to make it inaccessible).
  • Inside the shadow root, we define some CSS and HTML that will be encapsulated within the shadow DOM.

2. Accessing the Shadow DOM

If you set the shadow DOM’s mode to open, you can access the shadow tree via JavaScript. Here’s an example of accessing and modifying the shadow DOM:

<script>
    const shadowHost = document.getElementById('shadow-host');
    const shadowRoot = shadowHost.shadowRoot; // Accessing the shadow root

    // Modify the shadow DOM
    const paragraph = shadowRoot.querySelector('p');
    paragraph.textContent = "The shadow DOM content has been updated!";
</script>
Enter fullscreen mode Exit fullscreen mode

In this code:

  • We access the shadow root using shadowHost.shadowRoot.
  • We then modify the content inside the shadow DOM by selecting the <p> element and changing its text.

3. Styling Inside the Shadow DOM

Let's try to style the component inside the ShadowDOM. This will be isolated from the rest of the site.

<script>
    const shadowRoot = host.attachShadow({mode: 'open'});

    shadowRoot.innerHTML = `
        <style>
            p {
                color: red;
                font-weight: bold;
            }
            div {
                background-color: lightgray;
                padding: 10px;
                border-radius: 5px;
            }
        </style>
        <div>
            <p>This paragraph is styled inside the shadow DOM.</p>
        </div>
    `;
</script>
Enter fullscreen mode Exit fullscreen mode

Here, the p and div styles are scoped to the shadow DOM, meaning they won’t affect any elements outside the shadow tree. This ensures that the component behaves as intended, regardless of the styles applied to the rest of the page.

Final Thoughts

In summary, Shadow DOM is a game-changer for building robust, reusable components that need to be independent of their surrounding environment. By integrating this powerful technology, we were able to create the LiveAPI widget that works on any website without issues.

If you are curious about LiveAPI, you can check it out here at hexmos.com/liveapi and try to generate a doc. It's Free to try!

Top comments (0)