patternjavascriptvueTip
Vue 3 Teleport renders content outside the component DOM tree
Viewed 0 times
Vue 3.0+
teleportportalmodalz-indexoverflow hiddenbody append
Error Messages
Problem
Modals, tooltips, and dropdowns rendered inside a deeply nested component are clipped by overflow:hidden or have incorrect z-index stacking because they are trapped inside the parent DOM hierarchy.
Solution
Use <Teleport> to render content directly to another part of the DOM:
<!-- In a deeply nested component -->
<template>
<button @click="open = true">Open Modal</button>
<Teleport to="body">
<div v-if="open" class="modal-overlay" @click.self="open = false">
<div class="modal">
<h2>Modal Title</h2>
<p>Content here</p>
<button @click="open = false">Close</button>
</div>
</div>
</Teleport>
</template>
<script setup>
import { ref } from 'vue';
const open = ref(false);
</script>
<!-- Teleport to a custom target -->
<Teleport to="#notification-container">
<Toast v-if="showToast" :message="toastMsg" />
</Teleport>
<!-- Disable teleport conditionally -->
<Teleport to="body" :disabled="isMobile">
<Drawer />
</Teleport>
<!-- In a deeply nested component -->
<template>
<button @click="open = true">Open Modal</button>
<Teleport to="body">
<div v-if="open" class="modal-overlay" @click.self="open = false">
<div class="modal">
<h2>Modal Title</h2>
<p>Content here</p>
<button @click="open = false">Close</button>
</div>
</div>
</Teleport>
</template>
<script setup>
import { ref } from 'vue';
const open = ref(false);
</script>
<!-- Teleport to a custom target -->
<Teleport to="#notification-container">
<Toast v-if="showToast" :message="toastMsg" />
</Teleport>
<!-- Disable teleport conditionally -->
<Teleport to="body" :disabled="isMobile">
<Drawer />
</Teleport>
Why
Teleport moves the DOM nodes to the target while keeping the component's logical parent in Vue's component tree. The component still has access to the parent's reactive state, props, and inject. Only the rendered HTML is relocated.
Gotchas
- The teleport target must exist in the DOM when Teleport mounts — body is always safe
- Multiple Teleports to the same target are appended in order
- Teleported components still belong to their Vue parent for lifecycle and state
- Teleport does not work with SSR by default — use :disabled="true" during SSR or useSSRContext
Code Snippets
Teleported toast notification with transition
<Teleport to="body">
<Transition name="fade">
<div v-if="visible" class="toast">{{ message }}</div>
</Transition>
</Teleport>Context
When rendering modals, toasts, or tooltips that escape CSS stacking context
Revisions (0)
No revisions yet.