Skip to content

Shadow DOM ​

By default, all Jadis components render their templates inside a Shadow DOM. This provides style and markup encapsulation, preventing CSS leakage and ensuring predictable component behavior.

How It Works ​

When a Jadis component is instantiated, the constructor attaches an open shadow root if useShadowDom is true (the default):

typescript
class MyComponent extends Jadis {
  static readonly selector = 'my-component';
  // useShadowDom defaults to true — shadow DOM is used automatically
}

The template returned by templateHtml() and the styles from templateCss() are injected into this shadow root.

Disabling Shadow DOM ​

In some cases, you may want your component to render in the light DOM instead:

typescript
class MyComponent extends Jadis {
  static readonly selector = 'my-component';
  static readonly useShadowDom = false;
}

When useShadowDom is false, the template is appended directly to the component element itself. Then:

  • the styles from templateCss() apply to the whole document, as any global stylesheet;
  • <slot> elements do nothing, as slots only exist in a shadow root;
  • getElement() and refs search the component's own children.

When to Disable Shadow DOM ​

ScenarioReason
Global stylingYour component must inherit styles from a global stylesheet or CSS framework that relies on global selectors.
Third-party integrationLibraries or scripts expect direct access to the DOM tree and don't support shadow boundaries.
Legacy environmentsExisting codebases or tooling may not fully support Shadow DOM.
SEO / testing toolsSome crawlers or testing utilities require light DOM access.

CSS Variables and Shadow DOM ​

CSS custom properties (variables) defined on :root or ancestor elements do traverse shadow boundaries:

css
/* Global stylesheet */
:root {
  --font-family: 'Inter', sans-serif;
  --color-primary: #3b82f6;
}
css
/* Component stylesheet */
:host {
  font-family: var(--font-family);
  color: var(--color-primary);
}

This is the recommended pattern for theming: define variables globally and consume them in component styles.

Accessing Elements Across Shadow Boundaries ​

The getElement() helper supports the >>> combinator to traverse into child shadow roots:

typescript
// Access an element inside a child component's shadow DOM
const innerButton = this.getElement('child-component >>> button');

See getElement() for full details.

See Also ​