We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
2022 / 07 / 31
2022 / 09 / 18
A basic modal component with Vue 3 and Tailwind CSS
Let's write a reusable modal with Vue and Tailwind CSS.
Let’s go for a simple base modal implementation that provides a
backdrop and a centered <div>
where we can put any content
we need.
Example usage in BaseModalExample.vue
:
<script setup lang="ts">
import { ref } from 'vue'
import BaseModal from '@/components/modals/BaseModal.vue'
const showModal = ref(false)
</script>
<template>
<button
type="button"
class="bg-indigo-200 px-3 py-1 font-medium"
@click="showModal = true"
>
Show modal
</button>
<BaseModal :show="showModal">
<div class="p-4">
<div class="text-lg">Hello Modal World!</div>
<div class="py-2 text-sm">Click to close:</div>
<button
type="button"
class="bg-indigo-200 px-3 py-1 font-medium"
@click="showModal = false"
>
Hide modal
</button>
</div>
</BaseModal>
</template>
Let’s see how to implement the BaseModal.vue
component, shall we? :monocle:
Prerequisites
For this, you’ll need a Vue 3 + TypeScript (+ Tailwind CSS) project.
You can set up one following the instructions here:
Build a Vue 3 + TypeScript dev environment with Vite
Where modals go
It’s recommended that we display our modals in a div at the bottom of our main HTML file to avoid other elements accidentally rendering on top of them.
Add a new #modals element to your index.html
:
<body>
<div id="app" class="relative z-10"></div>
<!-- >> This one is new! << -->
<div id="modals" class="relative z-20"></div>
<script type="module" src="/src/main.ts"></script>
</body>
We also add a z-index value and position: relative to the
#app and #modals layers.
Now our modals will show on top of everything else thanks to stacking contexts.
Base modal
Let’s add a src/components/modals/BaseModal.vue
:
<script setup lang="ts">
defineProps<{
show: boolean
}>()
</script>
<template>
<!-- Render inside our `<div id="modals"></div>` in index.html -->
<Teleport to="#modals">
<!-- Show / hide the modal -->
<div v-if="show" class="">
<!-- The backdrop -->
<div class="fixed inset-0 bg-gray-900 opacity-40"></div>
<!-- Where the actual content goes -->
<div class="fixed inset-0 flex items-center justify-center">
<div class="bg-white text-black">
<slot></slot>
</div>
</div>
</div>
</Teleport>
</template>
This example provides some basic styling.
Feel free to add props or slots to configure the different aspects
of a modal — backdrop color, opacity, content background color,
content text color, etc.
That’s it! :tada: