Vue Shadow DOM Integration

4.2.0 · active · verified Sun Apr 19

vue-shadow-dom is a JavaScript library providing robust Shadow DOM support for Vue 3 applications, currently stable at version 4.2.0. It allows developers to leverage the browser's native Shadow DOM capabilities directly within Vue components, enabling strict encapsulation of styles and markup. The library achieves this through the provision of a Vue plugin, a `v-shadow` directive, and dedicated `<shadow-root>` and `<shadow-style>` components. While there isn't a stated fixed release cadence, updates tend to align with major Vue ecosystem changes or feature enhancements. A key differentiator is its direct, declarative API for Shadow DOM usage, avoiding complex manual DOM manipulations, and its comprehensive support for various module environments including ESM, CommonJS, and UMD builds, catering to both bundler-driven and browser-only setups. Notably, versions 2.0 and above are specifically designed for Vue 3, while v1.x targets Vue 2.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates initializing the `vue-shadow-dom` plugin, using the `<shadow-root>` component with custom tag and abstract prop, applying encapsulated styles with `<shadow-style>`, and accessing the native ShadowRoot instance via a ref for direct DOM interaction.

import { createApp, ref, defineComponent } from 'vue';
import shadow, { type ShadowRootExpose } from 'vue-shadow-dom';

const MyShadowComponent = defineComponent({
  template: `
    <div style="border: 1px solid blue; padding: 10px; margin: 20px;">
      <h2>Component Host</h2>
      <p>Content outside the shadow root. Styles here will leak unless encapsulated.</p>
      <shadow-root ref="shadowRef" tag="section" abstract>
        <template #default>
          <shadow-style>
            p { color: green; font-weight: bold; }
            h3 { color: darkred; }
            button { background-color: lightblue; padding: 8px; border: none; cursor: pointer; }
          </shadow-style>
          <h3>Shadow Root Content</h3>
          <p>This paragraph should be green and bold inside the shadow DOM.</p>
          <button @click="logShadowRoot">Log Shadow Root</button>
        </template>
      </shadow-root>
      <p>This paragraph is outside the shadow root.</p>
    </div>
  `,
  setup() {
    const shadowRef = ref<ShadowRootExpose | null>(null);

    const logShadowRoot = () => {
      if (shadowRef.value && shadowRef.value.shadow_root) {
        console.log('Shadow Root Instance:', shadowRef.value.shadow_root);
        // You can interact with the native ShadowRoot object directly
        const pElement = shadowRef.value.shadow_root.querySelector('p');
        if (pElement) {
          console.log('Paragraph inside shadow root:', pElement.textContent);
        }
      } else {
        console.warn('ShadowRoot instance not available yet.');
      }
    };

    return { shadowRef, logShadowRoot };
  },
});

const app = createApp(MyShadowComponent);
app.use(shadow);
app.mount('#app');

// To run this, you would typically have an index.html like:
// <div id="app"></div>

view raw JSON →