.agents/skills/vue-best-practices/references/component-teleport.md
Impact: MEDIUM - <Teleport> renders part of a component's template in a different place in the DOM while preserving the Vue component hierarchy. Use it for overlays (modals, toasts, tooltips) or any UI that must escape stacking contexts, overflow, or fixed positioning constraints.
body or a dedicated container outside the app root#modals, #notifications) and control layering with order or z-index:disabled for responsive layouts that should render inline on small screensWhen an ancestor has transform, filter, or perspective, fixed-position overlays can behave like they are locally positioned. Teleport escapes that context.
BAD:
<template>
<div class="animated-container">
<button @click="open = true">
Open
</button>
<!-- Broken: fixed positioning is scoped to the transformed parent -->
<div v-if="open" class="modal">
Modal
</div>
</div>
</template>
<style>
.animated-container {
transform: translateZ(0);
}
.modal {
position: fixed;
inset: 0;
z-index: 9999;
}
</style>
GOOD:
<template>
<div class="animated-container">
<button @click="open = true">
Open
</button>
<Teleport to="body">
<div v-if="open" class="modal">
Modal
</div>
</Teleport>
</div>
</template>
disabledUse :disabled to render inline on mobile and teleport on larger screens:
<script setup>
import { useMediaQuery } from '@vueuse/core'
const isMobile = useMediaQuery('(max-width: 768px)')
</script>
<template>
<Teleport to="body" :disabled="isMobile">
<nav class="sidebar">
Navigation
</nav>
</Teleport>
</template>
Teleport changes DOM position, not the Vue component tree. Props, emits, slots, and provide/inject still work:
<template>
<Teleport to="body">
<ChildPanel :message="message" @close="open = false" />
</Teleport>
</template>
Teleports to the same target append in declaration order:
<template>
<Teleport to="#notifications">
<div>First</div>
</Teleport>
<Teleport to="#notifications">
<div>Second</div>
</Teleport>
</template>
Use a shared container to keep stacking predictable, and apply z-index only when you need explicit layering.