Good day! In this short article, I will tell you about Shadow dom (shadow dom) in javascript. So let’s go!

As you know, working with html elements in javascript is done through working with the DOM. DOM is an architecture of elements (tags) built in the browser from html code. To view this architecture, just go to any element inspector. For example, in google chrome, in order to call the inspector, you must press the hot keys ctrl + shift + i and as a result you will see the dom tree of the web page. This DOM is open and can inherit all styles, scripts connected to this page.

In modern browsers, in addition to the open dom tree, the so-called shadow dom (hidden dom tree) is also supported. Shadom dom is an isolated architecture of elements from the main dom (open tree dom). Some complex web page elements such as video, audio, input[range] etc. are made up of individual components built using shadow dom.

Consider the video tag as an example.

If we go to the code inspector and look at this tag, we will see exactly the same structure that we described in the html code. We will not see any additional components, because initially the shadow tree is hidden. To view it, go to the inspector (using the example of the google chrome browser), in the upper right menu of the debug panel next to the cross, click on the icon with three dots and select the settings item. Next, in the Elements column, activate the ‘Show user agent shadow DOM’ checkbox. After we return to the inspector and look at the video tag. As you can see it is not empty now. If we expand it, we will see the line ‘#shadow-root (user-agent)’ which contains many different elements. Congratulations! You have reached the hidden dom tree of the web page, or rather the video tag. Now you know that the html5 video player consists of many different components (tags). Note that the dom of the video tag is generated by the browser and we cannot access its hidden elements for manipulation. However, nothing prevents us from creating our own hidden components for the elements, which we will continue to do.

So the introduction is over, let’s move on to the code.

Text title

Ending Text

A simple layout has been created here to which styles and scripts have been applied. The div element with class shadow will be the root element of our hidden dom tree (shadow). Moreover, it is desirable that the root element does not contain anything, since when a shadow dom is created in it, all its contents will no longer be displayed. This should be remembered!

vardiv = document.querySelector(‘.shadow’);
var shadow = div.attachShadow({mode: ‘open’});

With this code, we create a shadow dom (shadow dom) inside the ‘.shadow’ element. If we go to the code inspector and expand this element, we will see #shadow-root (open).mode

{mode: ‘open’} — means that we can access the shadow dom tree through the element using the shadowRoot property example:

console.log(div.shadowRoot);

Here the link to the dom tree of the ‘.shadow’ element will be returned to the console, in fact, this is what is returned to the ‘shadow’ variable.

If you put {mode: ‘closed’} then the ‘shadowRoot’ property will return null.

We have created a shadow dom tree, now we can fill it with data (html code, styles, scripts).

vardiv = document.querySelector(‘.shadow’);
var p = document.createElement(‘p’);
p.innerText = ‘Inner Text’;
var shadow = div.attachShadow({mode: ‘open’});
shadow appendChild(p);

In this example, we’ve created a ‘p’ tag with the text ‘Mid Text’ and added it to the hidden dom tree. Please note that working with shadow dom is no different from working with a regular dom tree. However, as you may have noticed, external styles and scripts were not applied to the ‘p’ tag in the shadow dom. This means that the shadow tree context is completely isolated from the regular DOM.

Let’s expand the example:

vardiv = document.querySelector(‘.shadow’);
var p = document.createElement(‘p’);
p.innerText = ‘Inner Text’;
var shadow = div.attachShadow({mode: ‘open’});

shadow.innerHTML = `

`;
varscript = document.createElement(‘script’);
script.innerHTML = `
shadow.querySelector(‘p’).addEventListener(‘click’, function(){
this.style.fontSize = ’20px’;
});
`;
shadow appendChild(p);
shadow.appendChild(script);

Here in the shadow dom styles and script have been added to the ‘p’ tag. Please note that in the script itself, we are accessing the ‘p’ tag not through document(document.querySelector(‘p’)), but the variable shadow(shadow.querySelector(‘p’)) which is a reference to the shadow dom root element.

var shadow = div.attachShadow({mode: ‘open’});

This is done because shadow dom elements are not contained in regular dom