# Shadow DOM

Shadow DOM is a standard that encapsulates the internal document object model (DOM) structure of a web component. Encapsulating the DOM gives developers the ability to share a component and protect the component from being manipulated by arbitrary HTML, CSS, and JavaScript. The internal DOM structure is called the shadow tree. The shadow tree affects how you work with CSS, events, and the DOM.

Since not all browsers support Shadow DOM, LWC uses a [synthetic shadow](/docs/platform/lwc/guide/create-dom-synthetic.md) polyfill for Lightning Experience and Experience Cloud. A polyfill is code that allows a feature to work in a web browser.

::video{src="https://youtube.com/embed/K5i9zMzVlzM" title="Explaining the Shadow DOM" type="youtube"}

:::note
If you use LWC outside of Lightning Experience or Experience Cloud, such as in Lightning Out (beta), LWC renders in native shadow. See [Compile-time Differences on the Salesforce Platform](/docs/platform/lwc/guide/get-started-oss.md).
:::

## Shadow Tree

To understand the [shadow tree](https://dom.spec.whatwg.org/#shadow-trees), let’s look at some markup. This markup contains two Lightning web components: `c-todo-app` and `c-todo-item`. The `#shadow-root` [document fragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) defines the boundary between the DOM and the shadow tree. Elements below the shadow root are in the shadow tree.

```html
<c-todo-app>
  #shadow-root
  <div>
    <p>Your To Do List</p>
  </div>
  <c-todo-item>
    #shadow-root
    <div>
      <p>Go to the store</p>
    </div>
  </c-todo-item>
</c-todo-app>
```

Let’s look at how to work with the shadow tree in each of these areas.

- CSS

  - : CSS styles defined in a parent component don’t leak into a child. In our example, a `p` style defined in the `todoApp.css` stylesheet doesn’t style the `p` element in the `c-todo-item` component, because the styles don’t reach into the shadow tree. See [CSS](/docs/platform/lwc/guide/create-components-css-intro.md).

- Events

  - : To prevent exposing a component’s internal details, if an event bubbles up and crosses the shadow boundary, some property values change to match the scope of the listener. See [Event Retargeting](/docs/platform/lwc/guide/events-handling.md#event-retargeting).

- Access Elements

  - : Elements in a shadow tree aren’t accessible via traditional DOM querying methods. Code can’t use `document` or `document.body` to access the shadow tree of a Lightning web component. For example, code can’t call `document.querySelector()` to select nodes in a Lightning web component’s shadow tree. To access its own shadow tree, a Lightning web component calls `this.template.querySelector()`. See [Access Elements the Component Owns](/docs/platform/lwc/guide/create-components-dom-work.md).

- Access Slots

  - : A slot is a placeholder for markup that a parent component passes into a component’s body. DOM elements that are passed to a component via slots aren’t owned by the component and aren’t in the component’s shadow tree. To access DOM elements passed via slots, call `this.querySelector()`. The component doesn't own these elements, so you don’t use `template`. See [Pass Markup into Slots](/docs/platform/lwc/guide/create-components-slots.md).

- Test Components

  - : See [DOM Inspection Tests Are Subject to Change](/docs/platform/lwc/guide/testing-dom-api.md).

:::tip
Watch Salesforce Developer Evangelist Alba Rivas [explain the Shadow DOM](https://www.youtube.com/watch?v=K5i9zMzVlzM\&list=PLgIMQe2PKPSJdFGHjGpjd1FbCsOqq5H8t\&index=5).
:::

## DOM APIs

Don’t use these DOM APIs to reach into a component’s shadow tree in orgs that use Lightning Locker. If you’re using a third-party JavaScript library that uses these DOM APIs to reach into a component’s shadow tree, work with the library author to file and fix issues.

- `Document.prototype.getElementById`
- `Document.prototype.querySelector`
- `Document.prototype.querySelectorAll`
- `Document.prototype.getElementsByClassName`
- `Document.prototype.getElementsByTagName`
- `Document.prototype.getElementsByTagNameNS`
- `Document.prototype.getElementsByName`
- `document.body.querySelector`
- `document.body.querySelectorAll`
- `document.body.getElementsByClassName`
- `document.body.getElementsByTagName`
- `document.body.getElementsByTagNameNS`

Lightning Locker prevents you from breaking shadow DOM encapsulation between Lightning web components by blocking these APIs. However, in Aura components version 39.0 and earlier, Lightning Locker is disabled at the component level, so an Aura component could have code that fails.

These APIs aren’t restricted by [Lightning Web Security (LWS)](/docs/platform/lightning-components-security/guide/lws-intro.md). LWS prevents you from breaking shadow DOM encapsulation by enforcing a value of `closed` on the ShadowRoot's `mode` property for all components.

:::important
The Shadow DOM polyfill includes a patch to the `MutationObserver` interface. If you use `MutationObserver` to watch changes in a DOM tree, disconnect it or you will create a memory leak. Note that a component can observe mutations only in its own template. It can't observe mutations within the shadow tree of other custom elements.
:::

## Convert Components from Synthetic to Native Shadow DOM

To easily convert components from synthetic DOM to native shadow DOM, use the lwc-codemod tool. The tool adds the `static shadowSupportMode` property to a synthetic DOM component.

For more information, see the [lwc-codemod documentation](https://github.com/salesforce/lwc-codemod).
