Definition
Shadow DOM là một tính năng cho phép tạo ra các custom element (hay custom component, web component). Nói cách khác, shadow DOM cho phép chúng ta tạo ra một DOM tree độc lập nằm bên trong các element của original DOM tree.
Structure
Với Shadow DOM chúng ta sẽ có thêm shadow host. Shadow host được xem như một element bình thường nhưng nội dung bên trong nó (cả stylesheet) sẽ được đóng gói và độc lập với thế giới bên ngoài. Nói cách khác, CSS và JS ở bên ngoài sẽ không áp dụng được cho nội dung bên trong một shadow host và ngược lại.
Mỗi shadow host sẽ có một shadow root là con trực tiếp. Shadow root và các node con của nó sẽ nằm ở trong shadow tree. Nội dung shadow root sẽ không được trình duyệt render mà thay vào đó trình duyệt chỉ render ra shadow host.

Bên trong một shadow tree có thể có nhiều shadow host cũng như shadow tree khác.
Ví dụ điển hình về shadow DOM là thẻ <video>.
<video controls width="500">
<source src="https://youtu.be/Pt7DYT2BxyE" type="video/webm" />
</video>Khi inspect ở devtool, ta chỉ thấy mỗi thẻ <video> và thẻ <source>. Tuy nhiên, ở video player trên giao diện thì lại có nhiều control khác nhau, chẳng hạn như nút play, nút phóng to màn hình, slider tăng giảm âm lượng, …
Các control này có thể được thêm vào giao diện bởi trình duyệt thông qua shadow DOM. Do vậy, tùy mỗi loại browser hoặc trang web mà giao diện của video player sẽ khác nhau.
Basic Usage
Có thể attach một shadow root vào một element bất kỳ thông qua phương thức Element.attachShadow(). Tham số đầu vào của phương thức là một đối tượng có thuộc tính mode.
const shadowOpen = elementRef.attachShadow({ mode: "open" })
const shadowClosed = elementRef.attachShadow({ mode: "closed" })Giá trị trả về của phương thức Element.attachShadow() sẽ là một shadow root.
Chế độ open sẽ cho phép chúng ta truy cập vào shadow DOM từ bên ngoài bằng JavaScript. Ví dụ, ta có thể truy cập đến thuộc tính shadowRoot của custom element (là một shadow host nào đó) như sau:
const myShadowDom = myCustomElem.shadowRootChế độ closed thì ngược lại, chúng ta sẽ không thể truy cập vào shadow DOM (giá trị của thuộc tính shadowRoot sẽ là null). Đây chính là trường hợp của các shadow host built-in chẳng hạn như thẻ <video>.
Chúng ta có thể attach một shadow root vào một element bên trong constructor của element đó như sau:
const shadow = this.attachShadow({ mode: "open" })Đây chính là tính năng sẽ được áp dụng cho Web Components.
Important
Một shadow DOM khi được attached vào một element nào đó thì có thể sử dụng các DOM APIs như element thông thường.