Vue.js 44 🟢 Teleporting DOM Nodes with
A modal dialog has a layout problem. It needs to appear centered on the screen, above everything else, with a backdrop that covers the entire page. If the modal is rendered inside a deeply nested component, its parent’s CSS can interfere: an overflow: hidden, a transform, a z-index stacking context, or a position: relative ancestor. The modal’s markup is logically part of the component that opened it, but physically it needs to live somewhere else in the DOM. <Teleport> is the Vue 3 built-in that moves a component’s DOM output to a different location in the document while preserving the logical component hierarchy. The component tree is unchanged; only the rendered DOM is relocated.
Key point: <Teleport> moves DOM nodes, not component logic. Props, events, reactivity, and lifecycle hooks all behave as if the content were rendered in place. What changes is where the browser inserts the nodes in the document.
Why Teleport exists
The stacking-context problem. CSS stacking contexts are created by positioned elements with a z-index, by transform, by filter, and by several other properties. A modal rendered inside such an ancestor cannot escape its stacking context, no matter how high its z-index. It appears behind elements that are outside the ancestor. Teleporting the modal to body removes it from the ancestor’s stacking context and lets it sit above everything.
The overflow problem. An ancestor with overflow: hidden clips its children. A dropdown rendered inside such an ancestor is cut off at the ancestor’s edge. Teleporting it to body or to a dedicated container avoids the clipping.
The layout problem. An ancestor with a fixed height, a grid, or a flex context can constrain the size or position of a child. A tooltip or a popover rendered inside a table cell inherits the cell’s dimensions and cannot position itself freely. Teleporting it out of the cell gives it the full viewport to work with.
The accessibility problem. A modal should trap focus and be announced as a dialog by screen readers. Placing it at the top of the body is the conventional structure for a dialog, and assistive technologies expect it. Teleporting to a top-level container aligns the DOM with the accessibility expectations.
The logical-location problem. The component that opens the modal owns the modal’s state. It should not have to move its template to the top of the app just to get the right DOM position. Teleport lets the component keep its logical structure — the modal is a child in the component tree — while the DOM ends up elsewhere.
The SSR problem. With server-side rendering, teleported content must be hydrated correctly. Vue tracks teleported nodes through hydration, so the client knows which server-rendered DOM belongs to the teleported component. The to target must exist on the server as well as the client, or hydration will fail.
a. The Teleport component
<Teleport> has a required to prop and a disabled prop. The default slot contains the content to teleport. The content is rendered in the target location when to resolves to an element in the document.
The minimal usage
<script setup>
import { ref } from 'vue';
const open = ref(false);
</script>
<template>
<button @click="open = true">Open modal</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>Modal content</p>
<button @click="open = false">Close</button>
</div>
</Teleport>
</template>
The modal markup is rendered as a direct child of <body> in the DOM. In the component tree, it is still a child of the component that contains the <Teleport>. The v-if is on the inner element, so the teleport itself is always present but the modal only renders when open is true.
The to prop
The to prop accepts a CSS selector string or an actual DOM element. The most common values are "body" and a dedicated container like "#modal-root".
<Teleport to="#modal-root">
<div class="modal">...</div>
</Teleport>
If the target does not exist when the teleport mounts, Vue logs a warning and renders the content in place. The target must exist before the teleport renders.
The dedicated container
A dedicated container in index.html gives the teleport a stable target that is not the entire body.
<body>
<div id="app"></div>
<div id="modal-root"></div>
<div id="tooltip-root"></div>
</body>
Two containers separate modals from tooltips, so their z-index layers and styling can be managed independently.
The disabled prop
The disabled prop turns the teleport off. The content is rendered in place instead of in the target.
<Teleport to="body" :disabled="isMobile">
<div class="modal">...</div>
</Teleport>
On mobile, the modal renders inline; on desktop, it teleports to the body. The prop is reactive, so the behavior can change at runtime.
The multiple teleports to the same target
Multiple <Teleport> components can target the same location. Vue appends the content in the order the teleports render.
<Teleport to="#modal-root">
<div>First</div>
</Teleport>
<Teleport to="#modal-root">
<div>Second</div>
</Teleport>
The target receives both, in the order they appear in the template.
The Teleport and Transition
<Teleport> composes with <Transition>. The transition wraps the teleported content, so the enter and leave animations apply to the modal.
<Teleport to="body">
<Transition name="fade">
<div v-if="open" class="modal">...</div>
</Transition>
</Teleport>
The transition is inside the teleport, so the animated element is the teleported content. The v-if is inside the transition, which is what triggers the animation.
b. Common patterns
Teleport is used in a handful of recurring patterns. Each one addresses a specific layout or stacking problem.
The modal dialog
The modal is the canonical use case. It is rendered at the top level, with a backdrop, and traps focus.
<script setup>
import { ref, watch } from 'vue';
const props = defineProps({ open: Boolean });
const emit = defineEmits(['close']);
watch(() => props.open, (isOpen) => {
document.body.style.overflow = isOpen ? 'hidden' : '';
});
</script>
<template>
<Teleport to="body">
<Transition name="modal">
<div v-if="props.open" class="modal-backdrop" @click.self="emit('close')">
<div class="modal-content" role="dialog" aria-modal="true">
<slot />
</div>
</div>
</Transition>
</Teleport>
</template>
The backdrop covers the viewport. The click on the backdrop closes the modal. The content is announced as a dialog by assistive technologies.
The tooltip
A tooltip is positioned relative to the element it describes. Teleporting it to body avoids clipping by ancestors and lets the tooltip use fixed positioning.
<script setup>
import { ref, computed } from 'vue';
const trigger = ref(null);
const visible = ref(false);
const position = ref({ top: 0, left: 0 });
function show() {
const rect = trigger.value.getBoundingClientRect();
position.value = { top: rect.bottom + 8, left: rect.left };
visible.value = true;
}
</script>
<template>
<span ref="trigger" @mouseenter="show" @mouseleave="visible = false">
<slot name="trigger" />
</span>
<Teleport to="body">
<div
v-if="visible"
class="tooltip"
:style="{ top: position.top + 'px', left: position.left + 'px' }"
>
<slot />
</div>
</Teleport>
</template>
The tooltip’s position is computed from the trigger’s bounding rectangle. The teleport lets the tooltip use fixed positioning without interference from ancestors.
The dropdown menu
A dropdown rendered inside a table or a scrollable container is clipped. Teleporting it to body lets it overflow freely.
<template>
<div class="dropdown">
<button @click="open = !open">Menu</button>
<Teleport to="body">
<ul v-if="open" class="dropdown-menu" :style="position">
<li v-for="item in items" :key="item.id">{{ item.label }}</li>
</ul>
</Teleport>
</div>
</template>
The dropdown’s position is computed from the trigger. The menu is not clipped by the table cell.
The notification system
Notifications appear at a fixed corner of the screen, independent of the component that triggered them. A global notification container at the top of the body is the target.
<Teleport to="#notification-root">
<TransitionGroup name="notification">
<div v-for="n in notifications" :key="n.id" class="notification">
{{ n.message }}
</div>
</TransitionGroup>
</Teleport>
The notification component teleports to a dedicated container. The container is positioned with position: fixed and a high z-index.
The nested modal
A modal that opens another modal teleports both to the same container. The second modal renders after the first, so it appears on top.
<Teleport to="#modal-root">
<div class="modal">...</div>
</Teleport>
The z-index is managed by the order of the teleports. The dedicated container can use CSS to layer the modals correctly.
The mobile fallback
On mobile, a dropdown may be better rendered inline. The disabled prop switches the behavior based on a media query.
<Teleport to="body" :disabled="isMobile">
<div class="dropdown">...</div>
</Teleport>
The isMobile flag is computed from window.matchMedia or a reactive viewport observer.
c. Teleport and the component tree
Teleport changes the DOM, not the component tree. This has consequences for refs, events, provide/inject, and SSR.
The component hierarchy
The teleported content is still a child of the component that contains the <Teleport>. Its lifecycle hooks fire in the same order. Its props come from the same parent. Its events bubble to the same handler.
<Teleport to="body">
<ChildComponent @click="handleClick" />
</Teleport>
The handleClick fires when the child is clicked, even though the child’s DOM is in body. The event bubbles through the Vue component tree, not the DOM tree.
The refs
A ref on a teleported element resolves to the DOM element in the target location.
<script setup>
import { ref } from 'vue';
const modalEl = ref(null);
</script>
<template>
<Teleport to="body">
<div ref="modalEl">...</div>
</Teleport>
</template>
The modalEl.value is the actual DOM node, wherever it was teleported.
The provide and inject
provide and inject work across the teleport. The teleported content inherits the provides from its logical ancestors, not its DOM ancestors.
<script setup>
provide('theme', 'dark');
</script>
<template>
<Teleport to="body">
<Child /> <!-- injects 'theme' = 'dark' -->
</Teleport>
</template>
The child injects the value from the logical ancestor, even though the DOM ancestor is body.
The event bubbling
Events emitted by the teleported component propagate through the Vue component tree, not the DOM tree. A listener on the parent receives the event normally.
<Teleport to="body">
<button @click="$emit('close')">Close</button>
</Teleport>
The parent’s @close listener fires when the button is clicked. The DOM position does not affect the event propagation.
The CSS scope
Scoped styles apply to teleported content. The scope attribute is added to the elements regardless of where they end up in the DOM.
<style scoped>
.modal { position: fixed; }
</style>
The .modal class matches only the teleported modal, because the scope attribute is present on the element. Styles from the parent component leak into the modal only through the cascade, not through the scope.
The SSR considerations
During server-side rendering, the teleported content is rendered into the target location in the initial HTML. The client hydrates it in place. If the target element does not exist on the server, hydration fails.
<!-- Server-rendered HTML -->
<body>
<div id="app">
<!-- component content -->
</div>
<div id="modal-root">
<div class="modal">...</div> <!-- teleported during SSR -->
</div>
</body>
The target must be present in the initial HTML. A target created dynamically on the client will not work with SSR.
The Teleport in devtools
Vue Devtools shows the teleported content under its logical parent, not the target. This is because the component tree is unchanged. The DOM inspector shows the content under the target.
Complete Example Session
<!-- ============================================
PART 1: BASIC TELEPORT
============================================ -->
<script setup>
import { ref } from 'vue';
const open = ref(false);
</script>
<template>
<button @click="open = true">Open</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>Modal content</p>
<button @click="open = false">Close</button>
</div>
</Teleport>
</template>
<!-- ============================================
PART 2: DEDICATED CONTAINER
============================================ -->
<!-- index.html -->
<body>
<div id="app"></div>
<div id="modal-root"></div>
</body>
<!-- Modal.vue -->
<template>
<Teleport to="#modal-root">
<div class="modal">...</div>
</Teleport>
</template>
<!-- ============================================
PART 3: TRANSITION WITH TELEPORT
============================================ -->
<template>
<Teleport to="body">
<Transition name="fade">
<div v-if="open" class="modal-backdrop">
<div class="modal-content"><slot /></div>
</div>
</Transition>
</Teleport>
</template>
<style scoped>
.fade-enter-active, .fade-leave-active { transition: opacity 0.2s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
</style>
<!-- ============================================
PART 4: MODAL COMPONENT
============================================ -->
<script setup>
import { watch } from 'vue';
const props = defineProps({ open: Boolean });
const emit = defineEmits(['close']);
watch(() => props.open, (isOpen) => {
document.body.style.overflow = isOpen ? 'hidden' : '';
});
</script>
<template>
<Teleport to="body">
<Transition name="modal">
<div v-if="props.open" class="modal-backdrop" @click.self="emit('close')">
<div class="modal-content" role="dialog" aria-modal="true">
<slot />
</div>
</div>
</Transition>
</Teleport>
</template>
<!-- ============================================
PART 5: TOOLTIP COMPONENT
============================================ -->
<script setup>
import { ref } from 'vue';
const trigger = ref(null);
const visible = ref(false);
const position = ref({ top: 0, left: 0 });
function show() {
const rect = trigger.value.getBoundingClientRect();
position.value = { top: rect.bottom + 8, left: rect.left };
visible.value = true;
}
</script>
<template>
<span ref="trigger" @mouseenter="show" @mouseleave="visible = false">
<slot name="trigger" />
</span>
<Teleport to="body">
<div
v-if="visible"
class="tooltip"
:style="{ top: position.top + 'px', left: position.left + 'px' }"
>
<slot />
</div>
</Teleport>
</template>
<!-- ============================================
PART 6: DROPDOWN COMPONENT
============================================ -->
<script setup>
import { ref } from 'vue';
const open = ref(false);
const trigger = ref(null);
const position = ref({ top: 0, left: 0 });
function toggle() {
if (!open.value) {
const rect = trigger.value.getBoundingClientRect();
position.value = { top: rect.bottom, left: rect.left };
}
open.value = !open.value;
}
</script>
<template>
<div>
<button ref="trigger" @click="toggle">Menu</button>
<Teleport to="body">
<ul
v-if="open"
class="dropdown-menu"
:style="{ top: position.top + 'px', left: position.left + 'px' }"
>
<slot />
</ul>
</Teleport>
</div>
</template>
<!-- ============================================
PART 7: NOTIFICATION SYSTEM
============================================ -->
<!-- index.html -->
<div id="notification-root"></div>
<!-- NotificationContainer.vue -->
<script setup>
import { useNotifications } from '@/composables/useNotifications';
const { notifications } = useNotifications();
</script>
<template>
<Teleport to="#notification-root">
<TransitionGroup name="notification">
<div
v-for="n in notifications"
:key="n.id"
class="notification"
>
{{ n.message }}
</div>
</TransitionGroup>
</Teleport>
</template>
<!-- ============================================
PART 8: DISABLED TELEPORT
============================================ -->
<script setup>
import { computed } from 'vue';
const isMobile = computed(() =>
window.matchMedia('(max-width: 768px)').matches
);
</script>
<template>
<Teleport to="body" :disabled="isMobile">
<div class="dropdown">...</div>
</Teleport>
</template>
<!-- ============================================
PART 9: REFS AND EVENTS ACROSS TELEPORT
============================================ -->
<script setup>
import { ref } from 'vue';
const modalEl = ref(null);
const emit = defineEmits(['close']);
</script>
<template>
<Teleport to="body">
<div ref="modalEl" class="modal">
<button @click="emit('close')">Close</button>
</div>
</Teleport>
</template>
<!-- The parent's @close listener fires when the button is clicked.
The modalEl ref points to the actual DOM element in body. -->
<!-- ============================================
PART 10: SSR COMPATIBILITY
============================================ -->
<!-- index.html (server-rendered) -->
<body>
<div id="app"><!-- server-rendered app --></div>
<div id="modal-root"><!-- server-rendered modals --></div>
</body>
<!-- The target must exist in the initial HTML.
A dynamically created target breaks hydration. -->
The ten parts showed basic teleport, a dedicated container, transition integration, the modal component, tooltip, dropdown, notification system, disabled teleport, refs and events, and SSR considerations.
Quick Reference
Teleport Props
| Prop | Type | Purpose |
|---|---|---|
to | String or Element | The target location |
disabled | Boolean | Render in place instead |
Common Targets
| Target | Use Case |
|---|---|
body | Modals, tooltips, dropdowns |
#modal-root | Dedicated modal container |
#tooltip-root | Dedicated tooltip container |
#notification-root | Notification system |
Teleport Behavior
| Aspect | Behavior |
|---|---|
| Component tree | Unchanged |
| DOM position | Moved to target |
| Refs | Point to the DOM node in the target |
| Events | Bubble through the component tree |
| Provide/inject | Follow the component tree |
| Scoped styles | Apply to the teleported content |
| Lifecycle | Fires in the same order |
Teleport and Other Components
| Component | Composition |
|---|---|
<Transition> | Wrap the teleported content |
<TransitionGroup> | For lists of teleported items |
<Suspense> | Teleport inside async components |
<KeepAlive> | Teleport preserves the cached state |
Best Practices
✅ Do This:
<!-- Use a dedicated container. -->
<Teleport to="#modal-root"> <!-- ✅ -->
<!-- Put the v-if inside the teleport. -->
<Teleport to="body"><div v-if="open">...</div></Teleport> <!-- ✅ -->
<!-- Wrap with Transition for enter/leave. -->
<Teleport to="body"><Transition name="fade"><div v-if="open" /></Transition></Teleport> <!-- ✅ -->
<!-- Hide body scroll when a modal is open. -->
document.body.style.overflow = 'hidden'; <!-- ✅ -->
<!-- Use the disabled prop for responsive behavior. -->
<Teleport to="body" :disabled="isMobile"> <!-- ✅ -->
<!-- Ensure the target exists in SSR. -->
<div id="modal-root"></div> <!-- ✅ -->
❌ Don’t Do This:
<!-- Don't teleport to a non-existent target. -->
<Teleport to="#does-not-exist"> <!-- ❌ Warning, renders in place -->
<!-- Don't put the v-if on the Teleport itself. -->
<Teleport v-if="open" to="body"> <!-- ❌ Teleport remounts -->
<!-- Don't expect DOM event bubbling to work. -->
<!-- Events bubble through the component tree, not the DOM. --> <!-- ❌ -->
<!-- Don't create the target dynamically on the client. -->
document.createElement('div'); // ❌ Breaks SSR hydration
<!-- Don't use Teleport for layout-only concerns. -->
<!-- CSS can handle many cases without moving the DOM. --> <!-- ❌ -->
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Target not found | Element does not exist at mount | Ensure the target is in the initial HTML |
| Modal remounts | v-if on the Teleport itself | Put v-if on the inner element |
| Transition does not fire | Transition outside the teleport | Move the transition inside |
| SSR hydration mismatch | Target created on the client | Render the target server-side |
| Event not received | Listener on the DOM parent | Listen through the component tree |
| Refs are null | Ref on the Teleport, not the element | Ref the inner element |
| Styles do not apply | Styles not scoped to the teleported element | Use the same component’s scoped styles |
Real-World Examples
1. Basic Modal
<Teleport to="body"><div v-if="open" class="modal">...</div></Teleport>
2. Dedicated Container
<Teleport to="#modal-root">...</Teleport>
3. Transition
<Teleport to="body"><Transition name="fade"><div v-if="open" /></Transition></Teleport>
4. Tooltip
<Teleport to="body"><div class="tooltip" :style="pos" /></Teleport>
5. Dropdown
<Teleport to="body"><ul v-if="open" class="dropdown" /></Teleport>
6. Notification
<Teleport to="#notification-root"><TransitionGroup>...</TransitionGroup></Teleport>
7. Disabled on Mobile
<Teleport to="body" :disabled="isMobile">...</Teleport>
8. Body Scroll Lock
watch(() => props.open, (v) => { document.body.style.overflow = v ? 'hidden' : ''; })
9. Ref to Teleported Element
<Teleport to="body"><div ref="modalEl">...</div></Teleport>
10. Nested Modals
<!-- Both teleport to #modal-root; the second appears on top. -->
Visual
Teleport: DOM Position vs Component Tree
┌────────────────────────────────────────────────────────────┐
│ COMPONENT TREE DOM TREE │
│ │
│ App <body> │
│ │ ├── <div id="app"> │
│ ├── Header │ ├── header │
│ ├── Content │ ├── content │
│ │ └── Modal ──────┐ │ │ └── button │
│ └── Footer │ │ └── footer │
│ │ │ │
│ │ └── <div id="modal-root">│
│ │ └── modal │
│ │ ▲ │
│ └────────────────────────┘ │
│ │
│ Modal is a child of Content in the component tree. │
│ Modal is a child of #modal-root in the DOM tree. │
│ Props, events, refs, and lifecycle follow the component │
│ tree. Only the rendered DOM moves. │
└────────────────────────────────────────────────────────────┘
The Stacking Context Problem
┌────────────────────────────────────────────────────────────┐
│ STACKING CONTEXT │
│ │
│ WITHOUT TELEPORT │
│ ┌──────────────────────────────────────────────────┐ │
│ │ <div class="container" style="transform: ..."> │ │
│ │ <div class="card"> │ │
│ │ <div class="modal" style="z-index: 9999"> │ │
│ │ Modal appears behind other elements │ │
│ │ because the ancestor creates a stacking │ │
│ │ context. │ │
│ │ </div> │ │
│ │ </div> │ │
│ │ </div> │ │
│ │ <div class="other" style="z-index: 1"> │ │
│ │ This element is outside the context │ │
│ │ and appears above the modal. │ │
│ │ </div> │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ WITH TELEPORT │
│ ┌──────────────────────────────────────────────────┐ │
│ │ <body> │ │
│ │ <div class="container">...</div> │ │
│ │ <div class="other">...</div> │ │
│ │ <div class="modal"> │ │
│ │ The modal is a direct child of body. │ │
│ │ No ancestor stacking context. │ │
│ │ z-index works as expected. │ │
│ │ </div> │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
The Modal Structure
┌────────────────────────────────────────────────────────────┐
│ MODAL WITH TELEPORT │
│ │
│ <Teleport to="body"> │
│ <Transition name="modal"> │
│ <div v-if="open" class="modal-backdrop"> │
│ <div class="modal-content" role="dialog" │
│ aria-modal="true"> │
│ <slot /> │
│ </div> │
│ </div> │
│ </Transition> │
│ </Teleport> │
│ │
│ RENDERED IN BODY: │
│ ┌──────────────────────────────────────────────────┐ │
│ │ <div class="modal-backdrop"> │ │
│ │ ← covers the entire viewport │ │
│ │ ← @click.self closes │ │
│ │ │ │
│ │ <div class="modal-content"> │ │
│ │ ← centered on the viewport │ │
│ │ ← role="dialog" │ │
│ │ ← aria-modal="true" │ │
│ │ ← focus trap here │ │
│ │ </div> │ │
│ │ </div> │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
Teleport and the Component Tree
┌────────────────────────────────────────────────────────────┐
│ WHAT FOLLOWS THE COMPONENT TREE │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PROPS Follow the component tree │ │
│ │ EVENTS Bubble through component tree │ │
│ │ REFS Point to the DOM element │ │
│ │ PROVIDE/INJECT Follow the component tree │ │
│ │ LIFECYCLE Fires in the same order │ │
│ │ SCOPED STYLES Apply to the teleported node │ │
│ │ DEVTOOLS Shows under the logical parent │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ DOM POSITION Only this changes │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ The component tree is the source of truth. │
│ Teleport only relocates the rendered nodes. │
└────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
<Teleport> | Built-in component that moves DOM nodes |
to prop | CSS selector or DOM element for the target |
disabled prop | Renders in place instead |
| Default slot | The content to teleport |
| Component tree | Unchanged by teleporting |
| Refs | Point to the DOM element in the target |
| Events | Bubble through the component tree |
| Provide/inject | Follow the component tree |
| SSR | Target must exist in the initial HTML |
| Common targets | body, #modal-root, #notification-root |
Key takeaways:
<Teleport>moves DOM nodes, not component logic. The component tree is unchanged. Props, events, refs, lifecycle, and provide/inject all behave as if the content were rendered in place. Only the browser’s DOM position changes.- The
toprop specifies the target. A CSS selector like"body"or"#modal-root", or a DOM element reference. The target must exist when the teleport mounts. - Put the
v-ifinside the teleport. The teleport itself should always be present. The conditional rendering belongs on the inner element, so the teleport does not remount. - Transitions go inside the teleport. The
<Transition>wraps the teleported content, so the enter and leave animations apply correctly. - A dedicated container is cleaner than
body. A<div id="modal-root">at the top of the document gives the teleport a stable target and keeps modal content separate from the app. - The
disabledprop switches behavior. On mobile, rendering inline may be preferable. The prop is reactive, so the behavior can change at runtime. - Events bubble through the component tree, not the DOM. A listener on the logical parent receives the event, even though the DOM node is elsewhere.
- SSR requires the target to exist server-side. The target must be in the initial HTML. A target created dynamically on the client breaks hydration.
- The component tree remains the source of truth. Devtools shows teleported content under its logical parent. The DOM inspector shows it under the target. Both are correct views of the same component.
Remember: <Teleport> solves the problem of rendering content in a different DOM location while keeping its logical component context. It is the tool for modals, tooltips, dropdowns, and notifications — components whose markup needs to live outside their parent’s DOM subtree but whose logic belongs inside it. The to prop selects the target, the disabled prop turns the behavior off, and the component tree remains unchanged. Props, events, refs, provide/inject, and lifecycle all follow the component tree. Only the DOM position moves. The result is a component that keeps its logical structure and its state management, while the browser renders its content where the layout needs it.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!