Shadow DOM & Events in JavaScript

Shadow DOM & Events in JavaScript

Shadow DOM & Events in JavaScript

The Shadow DOM is a way to encapsulate styles and functionality inside a web component, preventing conflicts with the main page. However, handling events in a Shadow DOM works a bit differently than in the regular DOM.

1️⃣ What is Shadow DOM?

Shadow DOM allows you to create a self-contained component with its own isolated styles and markup.

// Create a shadow root let host = document.querySelector("#shadow-host"); let shadow = host.attachShadow({ mode: "open" }); // Add some content inside Shadow DOM shadow.innerHTML = `<style> p { color: red; } </style> <p>Hello from Shadow DOM</p>`;

✅ The paragraph inside the Shadow DOM won’t be affected by global styles.

2️⃣ Events in Shadow DOM

Events can pass through the Shadow DOM but have special behavior.

Example: Event Inside Shadow DOM

let host = document.querySelector("#shadow-host"); let shadow = host.attachShadow({ mode: "open" }); // Add a button inside Shadow DOM let button = document.createElement("button"); button.textContent = "Click Me"; shadow.appendChild(button); // Add event listener button.addEventListener("click", () => { console.log("Button inside Shadow DOM clicked!"); });

✅ Events work normally inside the Shadow DOM.

3️⃣ Event Retargeting

When an event happens inside the Shadow DOM, the event.target behavior differs.

Example: Retargeting

document.addEventListener("click", (event) => { console.log("Clicked element:", event.target); });

🔹 If you click inside the Shadow DOM, it event.target will not expose inner elements; instead, it will return the shadow host.

4️⃣ Event Bubbling & Shadow DOM

By default, events bubble up to the main document except for some native events.

let shadow = document.querySelector("#shadow-host").attachShadow({ mode: "open" }); let div = document.createElement("div"); div.textContent = "Click me!"; shadow.appendChild(div); div.addEventListener("click", (event) => { console.log("Inside Shadow DOM:", event.target); }); document.addEventListener("click", (event) => { console.log("Outside Shadow DOM:", event.target); });

✅ The outside event listener can still catch clicks inside the shadow, but event.target is retargeted.

5️⃣ Dispatching Custom Events from Shadow DOM

If you want an event inside the Shadow DOM to be visible in the main document, use Custom Events.

let host = document.querySelector("#shadow-host"); let shadow = host.attachShadow({ mode: "open" }); let button = document.createElement("button"); button.textContent = "Send Event"; shadow.appendChild(button); button.addEventListener("click", () => { let customEvent = new CustomEvent("shadow-event", { bubbles: true, // Allows event to bubble composed: true, // Allows event to escape Shadow DOM detail: { message: "Hello from Shadow DOM" } }); host.dispatchEvent(customEvent); }); // Listen outside the Shadow DOM document.addEventListener("shadow-event", (event) => { console.log("Received from Shadow DOM:", event.detail.message); });

✅ The composed: true property allows the event to escape the Shadow DOM and reach the main document.

6️⃣ Preventing Events from Escaping

Some events, like focus, do not escape the Shadow DOM unless manually dispatched.

input.addEventListener("focus", (event) => { event.stopPropagation(); // Prevent focus from bubbling up });

🔹 Summary

✔ Shadow DOM keeps styles & elements isolated.
✔ Events inside the Shadow DOM do not expose internal elements.
✔ Use CustomEvent with composed: true to allow events to escape.
✔ Some events, like focus, do not bubble by default.

🚀 Need a hands-on demo? Let me know!

Soeng Souy

Soeng Souy

Website that learns and reads, PHP, Framework Laravel, How to and download Admin template sample source code free.

Post a Comment

CAN FEEDBACK
close