Teleport in Vue 3

What is Teleport in Vue 3 and how to use it .

Teleport in Vue 3

What is Teleport?

Principe of Teleport

Teleport is a component that appeared in Vue 3.

This component allows displaying its content to slot elsewhere in the DOM. To do that the component has props “to”. This prop uses a CSS selector to know where to display the content of the Teleport.

With Teleport, it’s possible to interact on the DOM external of your component scope while using an ordinary component easily manipulated.

Teleport has another prop “disabled”. This prop allows disabling the teleport of the content and adding the content to the DOM normally.

example of Teleport behavior

Before Vue3, there existed another library: PortalVue. This library has the same concept and many developers from Vue community loved it and used it. Then the Vue Team was natively implemented on Vu3 with a new name: Teleport.

PortalVue still exists and has other features that don’t exist in Teleport.

Simple example

For a better understanding, here is a simple example. I

In a Vue 3 application, I create a simple component. In this component, I add a <div> with the text:

<template>
 <div>
   First Paragraph
 </div>
</template>

And in the <div> I add the Teleport component:

<template>
 <div>
   First Paragraph
   <Teleport to="#test"> Second Paragraph</Teleport>
 </div>
</template>

In my Teleport, I add text in the slot and a CSS tag in props. This CSS tag targets an element HTML with the test in id.

After that in the App.vue I add ExampleTeleport component:

<template>
 <div>
   Text in App.vue
   <ExampleTeleport></ExampleTeleport>
 </div>
</template>

This is the result for now:

Result without using Teleport

And if I want to add <div> with the id:

<template>
 <div id="test"></div>
 <div>
   Text in App.vue
   <ExampleTeleport></ExampleTeleport>
 </div>
</template>

The content in Teleport is shown before the first paragraph:

Result using Teleport

And if you want to show the second paragraph after the first text is possible and very simple! Teleport has another prop: disabled. This prop disabled the teleport feature. For example, if I add disabled props on my component

<Teleport disabled to="#test"> Second Paragraph</Teleport>

Now the second paragraph is after the first paragraph.

Result using Teleport with disabled equal true
⚠️ In my example I add the target of my Teleport in my App.vue but the target must be available in the DOM when the Teleport is mounted. In this example and the next example, it’s the case. If possible, a good practice is to add the target outside of your Vue application. For example, you can add the target in your index.html.
In the Vue3 roadmap, a safe mode is planned to correct this problem. you can see more detail here. ⚠️

Why use Teleport?

After discovering how to use the Teleport component, we will now see why to use this component and what its advantages are with a few examples.

Reason 1: Manage the DOM outside of a component scope

The first reason and that you need to manage the DOM outside of your component scope. With Teleport is possible to manage the props, data, method, etc. in your component and display the content elsewhere in the DOM.

It’s very useful to avoid many problems with CSS in particular with position, z-index, overflow, display, etc., or to don’t have a problem with the HTML semantics.

Example: Modal component

A good example of that is if you want to create a modal component. With this component, you can have many problems with CSS because we use position or overflow attributes and with the HTML semantics.

Let’s build a simple modal component:

<script setup lang="ts">
const props = defineProps<{open: boolean}>();
</script>

<template>
  <div v-if="open" class="modal">
    <slot></slot>
  </div>
</template>

Now if I add my Modal on the button:

<button>
  I'm a button !
  <Modal :open="true">
    <p>Waw ! It's an awesome modal !</p>
  </Modal>
</button>

We have two problems:

  • The semantic HTML it’s not good and if I click on the modal, I click on the button
  • The style of the button can have an impact on my modal

If I use Teleport I can resolve all problems with that.

The first step is to add a target element (on my index.html for example):

<div id="content-modal"></div>

After that, I can add Teleport to my Modal component:

<template>
 <Teleport to="#content-modal">
   <div v-if="open" class="modal">
     <slot></slot>
   </div>
 </Teleport>
</template>

So we have that on the result (I add style for my button and my modal):

Example of modal with Teleport

If you try, you can see, we don’t have a problem with the HTML semantics.

Reason 2: Write a more readable code

The second reason to use a Teleport component is to have a readable code. Indeed, in some cases, Teleport allows simplifying the code.

Example: Alert component

Imagines an application where you want to display an alert message at the top of your page. The alerts can be created everywhere in your code (in the case of a form-sending error for example).

For that, you need to transport your data from one component to another component by using the store (Vuex, Pina, etc.) for example.

But with Teleport, you can have another solution. I created a simple alert component:

<template>
 <div class="alert">
   <slot></slot>
 </div>
</template>
<style scoped>
.alert {
 border-radius: 5px;
 color: white;
 background: #00bfff;
 padding: 10px;
}
</style>

And I add the teleport component:

template>
 <Teleport to="#content-alert">
   <div class="alert">
     <slot></slot>
   </div>
 </Teleport>
</template>

Now, if I add an alert to my project my alert is shown before the content:

 <div id="content-alert"></div>
 <div>
   I'm the content on the website
   <Alert>I'm an alert message !</Alert>
 </div>

The result is:

Result of alert with Teleport

If I had not used the teleport feature then I needed to transport my data with a store for example and my code would have been more complicated.

In the case, you add a new alert, the second will insert in the DOM after the first:

<div id="content-alert"></div>
 <div>
   I'm the content on the website
   <Alert>I'm an alert message !</Alert>
   <Alert>I'm a second alert message !</Alert>
 </div>
Result with two alert

Teleport is a very cool feature (opinionated)

As you can see Teleport is a very cool feature! He use easier our life with the management of the DOM outside our scope component.

It’s not the only component created with Vue3. With this version, we have some components with cool features to create our web applications. 😄

However, you need to do good use of this feature! By controlling the DOM outside to scope of your component if you abuse to use Teleport you can have side effects and it will come to hard to debug.

Moreover, this component has inconvenient because if we target an element inside on your Vue application and this element isn’t mounted, the Teleport doesn’t work. This problem is supposed to be solved this year. You can see more details on the roadmap video.