JAVASCRIPT

Using Teleport for Global Overlays

Effectively use Vue 3's `<Teleport>` component to render content, such as modals, tooltips, or notifications, into a different part of the DOM tree, avoiding z-index and overflow issues.

// GlobalModal.vue
<template>
  <teleport to="body">
    <div v-if="isVisible" class="global-modal-overlay">
      <div class="global-modal-content">
        <h3>{{ title }}</h3>
        <p>{{ message }}</p>
        <button @click="closeModal">Close</button>
      </div>
    </div>
  </teleport>
</template>

<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue';

const props = defineProps({
  title: String,
  message: String,
  modelValue: Boolean, // To control visibility with v-model
});

const emit = defineEmits(['update:modelValue']);

const isVisible = ref(props.modelValue);

watch(() => props.modelValue, (newValue) => {
  isVisible.value = newValue;
  toggleBodyScroll(newValue);
});

watch(isVisible, (newValue) => {
  emit('update:modelValue', newValue);
  toggleBodyScroll(newValue);
});

const closeModal = () => {
  isVisible.value = false;
};

const toggleBodyScroll = (show) => {
  if (show) {
    document.body.classList.add('no-scroll');
  } else {
    document.body.classList.remove('no-scroll');
  }
};

onMounted(() => {
    toggleBodyScroll(isVisible.value);
});

onUnmounted(() => {
    document.body.classList.remove('no-scroll'); // Ensure cleanup
});
</script>

<style scoped>
.global-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999; /* Ensure it's on top */
}
.global-modal-content {
  background: white;
  padding: 30px;
  border-radius: 8px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
  max-width: 500px;
  text-align: center;
}
button {
  padding: 10px 20px;
  background-color: #28a745;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  margin-top: 20px;
}
button:hover {
  background-color: #218838;
}

/* Global style for no-scroll */
body.no-scroll {
    overflow: hidden;
}
</style>

/*
// Usage in a parent component (App.vue):
<template>
  <div id="app">
    <h1>App Content</h1>
    <p>Some content behind the modal...</p>
    <button @click="showModal = true">Open Teleported Modal</button>

    <GlobalModal
      v-model="showModal"
      title="Important Notice"
      message="This modal content is rendered in the body using Teleport, but controlled from here."
    />
  </div>
</template>

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

const showModal = ref(false);
</script>
*/
How it works: The `<Teleport>` component in Vue 3 allows you to render a portion of your component's template into a different DOM node that exists outside the current component's hierarchy. This snippet demonstrates its use for a global modal. By setting `to='body'`, the modal content is moved directly under the `<body>` tag, effectively preventing common styling issues like `z-index` conflicts or `overflow: hidden` restrictions from parent elements. The modal's visibility is managed via `v-model`, showcasing how logic remains within the component while its rendering location is abstracted.

Need help integrating this into your project?

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

Hire DigitalCodeLabs