Skip to the solution
MediumFrontend10 min read

What is Teleport in Vue 3?

477 views

The problem

Question presented to candidate: "Our modal is rendered deep inside a card that has overflow: hidden and its own z-index, so the modal gets clipped. A teammate suggested <Teleport>. Explain what Teleport does, what stays the same for the component, and what can go wrong."

What a strong answer should cover:

  • <Teleport to="body"> moves the rendered DOM of its content to another place in the document, while the content stays in the same component tree.
  • Props, emits, reactive state, provide/inject and event handlers keep working, because those follow the component tree, not the DOM.
  • The to target is a CSS selector or element that must exist when the Teleport mounts; disabled renders the content in place instead (for example on mobile).
  • defer (Vue 3.5+) resolves the target after the current render, so it can point at an element rendered later by the same app.
  • Typical uses: modals, toasts, tooltips and dropdowns that must escape overflow, z-index stacking contexts or transformed ancestors.
  • In SSR, teleported HTML is returned separately in the render context and must be injected into the page by the server.

Clarifying questions expected:

  • "Is the target outside the Vue app, such as a #modals div in index.html, or rendered by the app?"
  • "Is this app server-rendered?"

Code / implementation expected: Yes β€” a modal teleported to body, ideally with disabled or defer shown.

  • teleport

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

10 min read Β· 10 sections

Read the code

VueModal teleported to body, with disabled, inject and a deferred target
<script setup>
import { ref, provide, inject, defineComponent, h } from "vue";

// A child that reads an injected value: provide/inject follows the component tree, not the DOM.
const ThemeLabel = defineComponent({
  setup() {
    const theme = inject("theme");
    return () => h("small", ` (theme: ${theme})`);
  },
});

provide("theme", "dark");
const open = ref(false);
const inline = ref(false); // when true, Teleport is disabled and renders in place
</script>

<template>
  <div class="card">
    <button class="open" @click="open = true">Open dialog</button>
    <label><input type="checkbox" class="inline" v-model="inline" /> render inline</label>

    <!-- Rendered into <body>, but still part of this component -->
    <Teleport to="body" :disabled="inline">
      <div v-if="open" class="modal" role="dialog">
        <p>Hello from the modal<ThemeLabel /></p>
        <button class="close" @click="open = false">Close</button>
      </div>
    </Teleport>

    <!-- defer (3.5+): the target is resolved after this render, so it can be rendered later in the template -->
    <Teleport defer to="#late-target"><span class="note">deferred note</span></Teleport>
  </div>
  <aside id="late-target"></aside>
</template>
Teleport during SSR: teleported HTML is returned in the render context
import { createSSRApp, h, Teleport } from "vue";
import { renderToString } from "@vue/server-renderer";
const app = createSSRApp({ render: () => h("main", [h("p", "page"), h(Teleport, { to: "body" }, h("div", { class: "modal" }, "modal"))]) });
const ctx = {};
const html = await renderToString(app, ctx);
console.log("html     :", html);
console.log("teleports:", ctx.teleports);

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 52 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextMedium

How do Vue components communicate?

Continue