Files
agent-skills/skills/vue-best-practices/reference/teleport-scoped-styles-limitation.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

3.8 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
Scoped Styles May Not Apply to Teleported Content MEDIUM Scoped styles can fail to apply to teleported elements due to data attribute limitations gotcha
vue3
teleport
scoped-styles
css

Scoped Styles May Not Apply to Teleported Content

Impact: MEDIUM - When using scoped styles with Teleport, the styles may not apply correctly to teleported elements. This is a known limitation related to how Vue's scoped style attributes work with elements rendered outside the component's DOM tree.

Task Checklist

  • Test scoped styles on teleported content
  • Use :deep() selector or non-scoped styles for teleported content
  • Consider CSS modules as an alternative
  • Keep teleported content styles in a separate non-scoped style block

Problem - Scoped Styles Not Applied:

<template>
  <Teleport to="body">
    <div class="modal">
      <p class="modal-text">This text may not be styled!</p>
    </div>
  </Teleport>
</template>

<style scoped>
/* These styles may NOT apply to teleported content */
.modal {
  background: white;
  padding: 20px;
}

.modal-text {
  color: blue;  /* May not work */
}
</style>

Solution 1 - Use Non-Scoped Styles for Teleported Content:

<template>
  <Teleport to="body">
    <div class="my-modal">
      <p class="my-modal-text">This text will be styled</p>
    </div>
  </Teleport>
</template>

<style scoped>
/* Component-specific styles */
.button { color: blue; }
</style>

<style>
/* Non-scoped styles for teleported content */
/* Use specific class names to avoid conflicts */
.my-modal {
  background: white;
  padding: 20px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.my-modal-text {
  color: blue;
}
</style>

Solution 2 - Use :deep() Selector:

<template>
  <Teleport to="body">
    <div class="modal">
      <p class="modal-text">Styled with :deep()</p>
    </div>
  </Teleport>
</template>

<style scoped>
:deep(.modal) {
  background: white;
  padding: 20px;
}

:deep(.modal-text) {
  color: blue;
}
</style>

Solution 3 - CSS Modules:

<template>
  <Teleport to="body">
    <div :class="$style.modal">
      <p :class="$style.modalText">Styled with CSS modules</p>
    </div>
  </Teleport>
</template>

<style module>
.modal {
  background: white;
  padding: 20px;
}

.modalText {
  color: blue;
}
</style>

Multi-Root Components with Teleport

Using Teleport as one of multiple root nodes causes additional issues:

<template>
  <!-- Multi-root component -->
  <button @click="open = true">Open</button>
  <Teleport to="body">
    <div class="modal">Content</div>
  </Teleport>
</template>

<!-- Warning: class/style attributes may not be inherited -->

Pass classes explicitly to avoid inheritance issues:

<template>
  <button @click="open = true">Open</button>
  <Teleport to="body">
    <div :class="['modal', $attrs.class]" :style="$attrs.style">
      Content
    </div>
  </Teleport>
</template>

Best Practice: Dedicated Modal Styles

Create a dedicated stylesheet for modal/overlay components:

/* modal-styles.css */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  background: white;
  border-radius: 8px;
  padding: 24px;
  max-width: 500px;
  width: 90%;
}
<script setup>
import './modal-styles.css'
</script>

<template>
  <Teleport to="body">
    <div v-if="open" class="modal-overlay">
      <div class="modal-content">
        <slot />
      </div>
    </div>
  </Teleport>
</template>

Reference