← Back to all snippets
JAVASCRIPT

Vue 3 Teleport for Creating Modals or Overlays

Leverage Vue 3's built-in Teleport component to render content into a different part of the DOM, making it ideal for creating accessible modals, tooltips, or overlays.

// public/index.html (Ensure you have a target element for Teleport)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 3 Teleport Demo</title>
  </head>
  <body>
    <div id="app"></div>
    <div id="modals-container"></div> <!-- This is our Teleport target -->
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

// components/MyModal.vue
<template>
  <teleport to="#modals-container">
    <div v-if="show" class="modal-backdrop" @click.self="closeModal">
      <div class="modal-content">
        <h2>{{ title }}</h2>
        <p><slot>Default modal content goes here.</slot></p>
        <button @click="closeModal">Close</button>
      </div>
    </div>
  </teleport>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  show: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: 'Modal Title'
  }
});

const emit = defineEmits(['close']);

const closeModal = () => {
  emit('close');
};
</script>

<style scoped>
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  width: 90%;
  max-width: 500px;
}
</style>

// App.vue (Parent component using the modal)
<template>
  <div>
    <h1>Welcome to the Teleport Demo</h1>
    <button @click="openModal">Open Modal</button>

    <MyModal :show="isModalOpen" title="Important Message" @close="closeModal">
      <p>This content is rendered by the modal.</p>
      <p>Even though it's placed inside App.vue, Teleport moves it to `body > #modals-container`.</p>
    </MyModal>

    <p>Some other content in the main app.</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import MyModal from './components/MyModal.vue';

const isModalOpen = ref(false);

const openModal = () => {
  isModalOpen.value = true;
};

const closeModal = () => {
  isModalOpen.value = false;
};
</script>
How it works: This snippet demonstrates Vue 3's `Teleport` feature, which allows you to render a component's content into a different DOM node, even if that node is outside the component's normal DOM hierarchy. This is particularly useful for creating modals, tooltips, or notifications that need to appear above all other content, avoiding CSS stacking context issues. The `MyModal` component uses `<teleport to="#modals-container">` to move its content to a specific `div` element defined in `public/index.html`.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs