One of the most practical new features in Vue 3 is the <Teleport> component. It solves a classic UI problem: how to render a component logically inside a parent (for data/events) but visually somewhere else in the DOM (for z-index/overflow issues).
The Problem: Modals and z-index
Imagine a default modal component nested deep within your application tree. If a parent element has overflow: hidden or a low z-index, your modal might get clipped or appear behind other content. Traditionally, we hacked this by moving modals to the root of the app, but that made passing data difficult.
The Solution: Teleport
<template>
<div class="user-card">
<h2>{{ user.name }}</h2>
<button @click="showModal = true">Edit User</button>
<Teleport to="body">
<div v-if="showModal" class="modal-overlay">
<div class="modal-content">
<h3>Edit {{ user.name }}</h3>
<form @submit.prevent="save">...</form>
<button @click="showModal = false">Close</button>
</div>
</div>
</Teleport>
</div>
</template>
How It Works
Even though the DOM elements are rendered in <body>, the Vue component hierarchy remains intact. The modal is still a child of UserCard. This means:
- Data flows (props) work normally.
- Event bubbling works! Events from the modal will bubble up to
UserCard, not justbody. - Lifecycle hooks are tied to the
UserCardparent.
Use Cases
- Modals/Dialogs: Ensure they overlay everything.
- Tooltips/Popovers: Avoid clipping by parent containers.
- Toast Notifications: Stack notifications in a fixed container.
References
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.