preface

Recently, when I looked at the source code of micro front-end framework and Qiankun, I found that Qiankun used shadowDom to achieve CSS style isolation. So out of curiosity, to explore a part of this knowledge.

What is shadowDom?

ShadowDom is an element that starts with # when you debug your code:

Does your video TAB have shadowDom? Search for chrome debug configuration and open the Show User Agent Shadow Dom option

In the code, we just wrote a video tag or an input tag, but in the page, we found that we actually rendered a lot of elements that we didn’t write, such as the pause button under the video tag, the progress bar, etc. This is all shadow Dom that the browser has added to it. The actual DOM tree for the video tag looks like this:

Here are some Shadow DOM specific terms to know:

  • Shadow host: A regular DOM node to which the Shadow DOM is attached.
  • Shadow Tree: Shadow DOM Internal DOM tree.
  • Shadow boundary: The place where the Shadow DOM ends and where the regular DOM begins.
  • Shadow root: indicates the root node of Shadow tree.

What are the characteristics?

  • You can manipulate the Shadow DOM in the same way you manipulate the regular DOM, such as adding child nodes, setting properties, and adding your own styles to the node
  • Elements inside the Shadow DOM never affect elements outside it (except :focus-within), which facilitates encapsulation.

What’s the use?

  • Good encapsulation, for a common component, we, as a developer, don’t need to care about the internal implementation or principle of many elements, such as we use the video element in the page, actually to pause, play, such as scroll logic does not need to do too much concern, so we hope that the code as simple as possible, then, as now, Instead of having to write a bunch of elements to implement the pause button itself, you just need a video TAB

How does it work?

  • Create shadowDom with attachShadow:
let shadow = element.attachShadow({mode: 'open'});
let shadow = element.attachShadow({mode: 'closed'});
Copy the code
    • Open/closed indicates that Shadow DOM can be obtained through JavaScript methods on the page

Have a try?

  • In the example, there are two divs with haha classnames, one in normal DOM and one in shadowDom.
  • You can see that the haha styles under the two style tags do not affect each other
<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
  <style>
    .haha {
      background-color: pink;
    }
  </style>
</head>
<body>
  <div class="wrapper">
    <div class="inner"></div>
    <div class="haha">Ha ha ha ha</div>
  </div>
</body>
<script>
  const inner = document.querySelector('.inner');
  const innerShadow = inner.attachShadow({mode: 'open'});

  const div = document.createElement('div');
  div.innerHTML = "haha";
  div.className = 'haha'

  const style = document.createElement('style');
  style.textContent = ` .haha { color: #ff0000; } `;
  
  innerShadow.appendChild(style)
  innerShadow.appendChild(div)
</script>
</html>
Copy the code

Effect: