What Causes This Warning?
This warning occurs when <Teleport> cannot find the target DOM element specified in its to prop. The element either doesn’t exist yet, has a typo in the selector, or is being rendered conditionally.
The Problem
<!-- ❌ Target element doesn't exist -->
<template>
<Teleport to="#modal-container">
<div class="modal">Modal content</div>
</Teleport>
</template>
<!-- No element with id="modal-container" in the DOM! -->
The Fix
Ensure Target Element Exists
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
<!-- ✅ Add teleport target -->
<div id="modal-container"></div>
</body>
</html>
<!-- Component.vue -->
<template>
<Teleport to="#modal-container">
<div class="modal">Modal content</div>
</Teleport>
</template>
Use Disabled Prop When Target Not Ready
<script setup>
import { ref, onMounted } from 'vue'
const targetReady = ref(false)
onMounted(() => {
// Check if target exists
targetReady.value = !!document.querySelector('#modal-container')
})
</script>
<template>
<!-- ✅ Disable teleport until target is ready -->
<Teleport to="#modal-container" :disabled="!targetReady">
<div class="modal">Modal content</div>
</Teleport>
</template>
Create Target Dynamically
<script setup>
import { onMounted, onUnmounted } from 'vue'
let container: HTMLElement | null = null
onMounted(() => {
// ✅ Create target element dynamically
container = document.createElement('div')
container.id = 'dynamic-modal-container'
document.body.appendChild(container)
})
onUnmounted(() => {
container?.remove()
})
</script>
<template>
<Teleport to="#dynamic-modal-container">
<div class="modal">Modal content</div>
</Teleport>
</template>
Common Scenarios
SSR/Nuxt Applications
<script setup>
import { ref, onMounted } from 'vue'
// ❌ Target doesn't exist during SSR
const isMounted = ref(false)
onMounted(() => {
isMounted.value = true
})
</script>
<template>
<!-- ✅ Only teleport on client -->
<Teleport v-if="isMounted" to="body">
<div class="modal">Modal content</div>
</Teleport>
</template>
Nuxt with ClientOnly
<template>
<!-- ✅ Use ClientOnly in Nuxt -->
<ClientOnly>
<Teleport to="#modal-container">
<div class="modal">Modal content</div>
</Teleport>
</ClientOnly>
</template>
Multiple Teleport Targets
<!-- index.html -->
<body>
<div id="app"></div>
<div id="modals"></div>
<div id="tooltips"></div>
<div id="notifications"></div>
</body>
<template>
<Teleport to="#modals">
<Modal v-if="showModal" />
</Teleport>
<Teleport to="#tooltips">
<Tooltip v-if="showTooltip" />
</Teleport>
<Teleport to="#notifications">
<Toast v-for="toast in toasts" :key="toast.id" />
</Teleport>
</template>
Teleport to Body
<!-- ✅ body always exists -->
<template>
<Teleport to="body">
<div class="fullscreen-modal">
Content goes here
</div>
</Teleport>
</template>
Conditional Teleport
<script setup>
const props = defineProps<{
appendToBody?: boolean
}>()
</script>
<template>
<!-- ✅ Conditionally teleport -->
<Teleport to="body" :disabled="!appendToBody">
<div class="dropdown-menu">
Menu content
</div>
</Teleport>
</template>
Dynamic Target
<script setup>
import { computed } from 'vue'
const props = defineProps<{
targetId: string
}>()
const teleportTarget = computed(() => `#${props.targetId}`)
</script>
<template>
<Teleport :to="teleportTarget">
<div>Teleported content</div>
</Teleport>
</template>
Valid Target Selectors
<!-- CSS selector -->
<Teleport to="#my-id">
<!-- Class selector -->
<Teleport to=".my-class">
<!-- Data attribute -->
<Teleport to="[data-modal-container]">
<!-- Element tag (first match) -->
<Teleport to="body">
<!-- DOM element reference -->
<Teleport :to="elementRef">
Quick Checklist
- Verify target element exists in the DOM
- Check for typos in the selector
- Add target element to
index.html - Use
:disabledwhen target might not exist - For SSR, ensure client-side only rendering
- Use
bodyas a fallback target that always exists