<Teleport>: DOM Relocation Outside Component Root & Dynamic Targets
- Last updated
- Prerequisites:
- Vue Template Syntax
- CSS Stacking Contexts & z-index
- vue
- teleport
- dom
- modals
- top-layer
- portal
Read at your depth
The practical view
`<Teleport to="body">` moves its template markup to a different DOM node (like `document.body` or `#modals-container`) while maintaining its reactive component connection. It is the standard solution for modals, tooltips, and notifications to prevent them from being cut off by parent CSS `overflow: hidden` or `z-index` stacking contexts. The `disabled` prop lets you toggle teleportation dynamically.
The same idea in other frameworks
`createPortal(<Modal />, document.body)` from `react-dom`.Angular CDK `Portal` / `Overlay` service.`<Teleport to="body"><Modal /></Teleport>`.Svelte custom action moving element to `document.body`.Legacy vs modern
CSS-Trapped Modal vs Vue <Teleport>
Nested modal markup gets clipped by parent CSS; `<Teleport to="body">` mounts directly into body.
<div class="modal">...</div> // ❌ Trapped inside overflow: hidden container<Teleport to="body"><div v-if="showModal" class="modal">...</div></Teleport> // ✅ NEWInterview gotchas
Context
Interviewers test your knowledge of mounting order and querySelector timing.
The mechanical answer
If the target element does not exist in the DOM when the component mounts, Vue will throw a runtime warning (`[Vue warn]: Failed to locate Teleport target with selector...`) and rendering of the teleported content will fail. The target DOM element must already exist in the HTML *before* the component containing `<Teleport>` is mounted.
Trap
Do not attempt to teleport to a sibling element that renders later in the same template; target elements must already be present in the DOM (e.g. in `index.html` or a previously mounted layout).
Context
Checks cross-framework event architecture comprehension.
The mechanical answer
In Vue 3, **native DOM events bubble through the physical HTML DOM tree**, following the target's new position in the DOM. (This differs from React Portals, where synthetic events bubble through the virtual component tree). However, Vue component custom events (`$emit`) still propagate through the Vue component hierarchy as expected.
Trap
A native `@click` on the parent container in Vue will *not* catch clicks from teleported elements if they were moved outside that container in the physical DOM.