JavaScript - attachShadow() method

revision:


Category : element

The Element.attachShadow() method attaches a shadow DOM tree to the specified element and returns a reference to its ShadowRoot.

The following is a list of elements you can attach a shadow root to:

any autonomous custom element with a valid name
<article>
<aside>
<blockquote>
<body>
<div>
<footer>
h1
h2
h3
h4
h5
h6
<header>
<main>
<nav>
<p>
<section>
<span>

Syntax :

        attachShadow(options)
    

Parameters:

options : an object which contains the following fields:

mode : a string specifying the encapsulation mode for the shadow DOM tree. This can be one of:

open: elements of the shadow root are accessible from JavaScript outside the root, for example using Element.shadowRoot.
closed: denies access to the node(s) of a closed shadow root from JavaScript outside it.

delegatesFocus : optional. A boolean that, when set to true, specifies behavior that mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling. Its default value is false.

slotAssignment : optional. A string specifying the slot assignment mode for the shadow DOM tree. This can be one of:

named : elements are automatically assigned to <slot> elements within this shadow root. Any descendants of the host with a slot attribute which matches the name attribute of a <slot> within this shadow root will be assigned to that slot. Any top-level children of the host with no slot attribute will be assigned to a <slot> with no name attribute (the "default slot") if one is present.

manual : elements are not automatically assigned to <slot> elements. Instead, they must be manually assigned with "HTMLSlotElement.assign()"". Its default value is named.

Examples:

            element.attachShadow({ mode: "open" });
            element.shadowRoot; // Returns a ShadowRoot obj

            element.attachShadow({ mode: "closed" });
            element.shadowRoot; // Returns null
        

Practical examples

example: word counting in a text

Word count rating widget

Sample heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc pulvinar sed justo sed viverra. Aliquam ac scelerisque tellus. Vivamus porttitor nunc vel nibh rutrum hendrerit. Donec viverra vestibulum pretium. Mauris at eros vitae ante pellentesque bibendum. Etiam et blandit purus, nec aliquam libero. Etiam leo felis, pulvinar et diam id, sagittis pulvinar diam. Nunc pellentesque rutrum sapien, sed faucibus urna sodales in. Sed tortor nisl, egestas nec egestas luctus, faucibus vitae purus. Ut elit nunc, pretium eget fermentum id, accumsan et velit. Sed mattis velit diam, a elementum nunc facilisis sit amet.

Pellentesque ornare tellus sit amet massa tincidunt congue. Morbi cursus, tellus vitae pulvinar dictum, dui turpis faucibus ipsum, nec hendrerit augue nisi et enim. Curabitur felis metus, euismod et augue et, luctus dignissim metus. Mauris placerat tellus id efficitur ornare. Cras enim urna, vestibulum vel molestie vitae, mollis vitae eros. Sed lacinia scelerisque diam, a varius urna iaculis ut. Nam lacinia, velit consequat venenatis pellentesque, leo tortor porttitor est, sit amet accumsan ex lectus eget ipsum. Quisque luctus, ex ac fringilla tincidunt, risus mauris sagittis mauris, at iaculis mauris purus eget neque. Donec viverra in ex sed ullamcorper. In ac nisi vel enim accumsan feugiat et sed augue. Donec nisl metus, sollicitudin eu tempus a, scelerisque sed diam.

code:
                    <div>
                        <h4>Word count rating widget</h4>
                        <article contenteditable="">
                            <h5>Sample heading</h5>
                            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc pulvinar sed justo sed viverra. 
                            Aliquam ac scelerisque tellus. Vivamus porttitor nunc vel nibh rutrum hendrerit. Donec viverra 
                            vestibulum pretium. Mauris at eros vitae ante pellentesque bibendum. Etiam et blandit purus, nec 
                            aliquam libero. Etiam leo felis, pulvinar et diam id, sagittis pulvinar diam. Nunc pellentesque 
                            rutrum sapien, sed faucibus urna sodales in. Sed tortor nisl, egestas nec egestas luctus, faucibus vitae
                            purus. Ut elit nunc, pretium eget fermentum id, accumsan et velit. Sed mattis velit diam, a elementum
                            nunc facilisis sit amet.</p>
                            <p>Pellentesque ornare tellus sit amet massa tincidunt congue. Morbi cursus, tellus vitae pulvinar
                            dictum, dui turpis faucibus ipsum, nec hendrerit augue nisi et enim. Curabitur felis metus, euismod 
                            et augue et, luctus dignissim metus. Mauris placerat tellus id efficitur ornare. Cras enim urna, 
                            vestibulum vel molestie vitae, mollis vitae eros. Sed lacinia scelerisque diam, a varius urna iaculis 
                            ut. Nam lacinia, velit consequat venenatis pellentesque, leo tortor porttitor est, sit amet accumsan 
                            ex lectus eget ipsum. Quisque luctus, ex ac fringilla tincidunt, risus mauris sagittis mauris, at 
                            iaculis mauris purus eget neque. Donec viverra in ex sed ullamcorper. In ac nisi vel enim accumsan 
                            feugiat et sed augue. Donec nisl metus, sollicitudin eu tempus a, scelerisque sed diam.</p>
                            <p is="word-count"></p>
                        </article>
            
                    </div>
                    <script>
                        class WordCount extends HTMLParagraphElement {
                            constructor() {
                                // Always call super first in constructor
                                super();
                                // count words in element's parent element
                                const wcParent = this.parentNode;
                                function countWords(node){
                                    const text = node.innerText || node.textContent;
                                    return text.trim().split(/\s+/g).filter(a => a.trim().length > 0).length;
                                }
                                const count = `Words: ${countWords(wcParent)}`;
                                // Create a shadow root
                                const shadow = this.attachShadow({mode: 'open'});
                                // Create text node and add word count to it
                                const text = document.createElement('span');
                                text.textContent = count;
                                // Append it to the shadow root
                                shadow.appendChild(text);
                                // Update count when element content changes
                                setInterval(function() {
                                const count = `Words: ${countWords(wcParent)}`;
                                text.textContent = count;
                                }, 200);
                            }
                        }
                        // Define the new element
                        customElements.define('word-count', WordCount, { extends: 'p' });
                        
                    </script>