0% found this document useful (0 votes)
264 views

Building A Modal With Vue - Js and Tailwind CSS - Laravel News

The document describes how to build a modal component in Vue.js using Tailwind CSS. It includes steps to create the component, add styling, use slots for content, and add functionality like closing the modal via clicks or a close button. Transitions are also added to smoothly fade the modal in and out.

Uploaded by

sinchijackal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
264 views

Building A Modal With Vue - Js and Tailwind CSS - Laravel News

The document describes how to build a modal component in Vue.js using Tailwind CSS. It includes steps to create the component, add styling, use slots for content, and add functionality like closing the modal via clicks or a close button. Transitions are also added to smoothly fade the modal in and out.

Uploaded by

sinchijackal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Laravel News

Building a modal with Vue.js and


Tailwind CSS

M AY 3 1 , 2 0 1 9 / J A S O N B E G G S

Modal windows are a popular UI component and are useful for


many di erent scenarios. You might use one for alerting a user,
showing a form, or even popping up a login form. The uses are
limitless.

In this tutorial, we’ll walk through how to build a reusable card


modal using Vue.js and Tailwind CSS. The component will use
Vue.js slots, so you can change the contents of the modal
wherever it is used while retaining the open/close functionality
and the wrapper design.

We’ll be starting with a brand-new Laravel 5.8 project. The only


additional setup we need to perform is setting up Tailwind, but
I won’t be going into detail on how to setup Vue and Tailwind in
thisLaravel News
tutorial.

Getting started with the modal

To begin, let’s create a CardModal Vue component and register


it in the resources/js/app.js file.

// resources/assets/js/components/CardModal.vue
<template>
<div>
The modal will go here.
</div>
</template>

<script>
export default {
//
}
</script>

// resources/js/app.js
Vue.component('card-modal', require('./components/CardModal.vue').defa

const app = new Vue({


el: '#app',
});

To start using the component, we need to update the


resources/views/welcome.blade.php view to the following.
Note the .relative class on the body tag.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1

Laravel News
<title>{{ config('app.name', 'Laravel') }}</title>

<script src="{{ asset('js/app.js') }}" defer></script>


<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body class="relative font-sans p-8">
<div id="app">
<h1 class="font-bold text-2xl text-gray-900">Example Project</
<p class="mb-6">This is just a example text for my tutorial.</

<card-modal></card-modal>
</div>
</body>
</html>

Making the modal appear

Right now, the text inside the modal will always show. Let’s
start by making the component accept a prop to show or hide
the contents.

Update the component to accept a showing prop and add a v-


if directive to the div in the template to show/hide the
contents when the showing prop changes.

<template>
<div v-if="showing">
The modal will go here.
</div>
</template>

<script>
export default {
props: {
showing: {
required: true,
type: Boolean
}
}
}
</script>
Laravel News
We’ll also need to add a data property to our Vue instance so we
can show or hide the modal from outside the CardModal
component. We’ll default the property to false so the modal
will be hidden when the page loads.

const app = new Vue({


el: '#app',
data: {
exampleModalShowing: false,
},
});

Then, we need to pass the exampleModalShowing prop to the


CardModal in our welcome view. We’ll also need a button to
show the modal.

<div id="app">
<h1 class="font-bold text-2xl text-gray-900 ">Example Project</h1>
<p class="mb-6">This is just a example text for my tutorial.</p>

<button
class="bg-blue-600 text-white px-4 py-2 text-sm uppercase tracki
@click="exampleModalShowing = true"
>
Show Modal
</button>
<card-modal :showing="exampleModalShowing"></card-modal>
</div>

Styling the modal

Next, let’s add some styling to the modal. We’ll need a card
surrounding the contents and a semi-transparent background
around the card. The background will also need to be position
fixed so it can take up the full screen without moving any of the
other contents on the page. Let’s start by adding the
Laravel News
background and centering the contents. For the transparent
background, we will need to add a semi-75 color to our
Tailwind configuration.

<template>
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cen
>
The modal will go here.
</div>
</template>

To add the semi-75 color so the bg-semi-75 class works, we


will extend the colors configuration in our tailwind.config.js
file.

module.exports = {
theme: {
extend: {
colors: {
'bg-semi-75': 'rgba(0, 0, 0, 0.75)'
}
}
}
};

Now, we need to set a max width, background color, shadow,


rounded edges, and padding for the card. We’ll add a div to
wrap the content inside the modal and add these classes to it.

<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cente
>
<div class="w-full max-w-2xl bg-white shadow-lg rounded-lg p-8">
Laravel News
The modal will go here.
</div>
</div>

Using slots for the content

Now that we have the basic styling finished, let’s update the
component to use a slot so the content of the modal can be
configured where the component is used instead of inside the
component. This will make the component much more
reusable.

First, we need to replace the content inside the component with


a <slot>. If you’re not familiar with Vue.js slots, essentially,
they allow you to pass html into a component and it will be
rendered wherever you specify the <slot> tags.

<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cente
>
<div class="w-full max-w-2xl bg-white shadow-lg rounded-lg p-8">
<slot />
</div>
</div>

Second, in the welcome view, we just place the html we want to


show inside the modal between the <card-modal> and </card-
modal> tags.

<card-modal :showing="exampleModalShowing">
<h2>Example modal</h2>
<p>This is example text passed through to the modal via a slot.</p
</card-modal>
Laravel News

Closing the modal

The component is getting close to finished, but we have one


little problem. We haven’t made a way to close the modal yet.
I’d like to add a few di erent ways to close the modal. First,
we’ll add a simple close x at the top right of the card. We need
to add a button to the template that calls a close method
inside the component. Be sure to add the .relative class to
the card div.

<template>
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cen
>
<div class="relative w-full max-w-2xl bg-white shadow-lg rounded-l
<button
aria-label="close"
class="absolute top-0 right-0 text-xl text-gray-500 my-2 mx-4"
@click.prevent="close"
>
×
</button>
<slot />
</div>
</div>
</template>

<script>
export default {
props: {
showing: {
required: true,
type: Boolean
}
},
methods: {
close() {
this.$emit('close');
}
}
};
</script>
Laravel News

You’ll see that the close method emits a close event. We’ll
need to listen for the event outside the component and update
the exampleModalShowing property to false. In the welcome
view, we can listen for the event by adding a @close listener on
the <card-modal> tag.

<card-modal :showing="exampleModalShowing" @close="exampleModalShowing


<h2 class="text-xl font-bold text-gray-900">Example modal</h2>
<p>This is example text passed through to the modal via a slot.</p
</card-modal>

To close the modal from outside the component, we can add a


button that sets exampleModalShowing to false as well.

<card-modal :showing="exampleModalShowing" @close="exampleModalShowing


<h2 class="text-xl font-bold text-gray-900">Example modal</h2>
<p class="mb-6">This is example text passed through to the modal v
<button
class="bg-blue-600 text-white px-4 py-2 text-sm uppercase tracki
@click="exampleModalShowing = false"
>
Close
</button>
</card-modal>

Now when we click the “Show Modal” button, the modal should
appear. When we click the close button or the x inside the
modal, the modal should disappear.
I’d also like the modal to close when the background behind
theLaravel
card isNews
clicked. Using Vue.js, it’s pretty easy to add that
functionality. We can just add @click.self="close" to the
background div and Vue will handle the rest. The .self
modifier will make it so the listener is only triggered when the
background itself is clicked. Without that modifier, the modal
would close whenever anything inside the card is clicked as
well, which is not what we want.

<template>
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cen
@click.self="close"
>
<div class="relative w-full max-w-2xl bg-white shadow-lg rounded-l
<button
aria-label="close"
class="absolute top-0 right-0 text-xl text-gray-500 my-2 mx-4"
@click.prevent="close"
>
×
</button>
<slot />
</div>
</div>
</template>

Adding a transition

To make the component feel smoother, let’s wrap the


component in a transition so the modal fades in. Once again,
Vue makes this pretty easy with <Transition> components. We
just need to wrap the background div in a <Transition> tag
and add a few CSS classes to the bottom of the component.

<template>
<Transition name="fade">
<div
v-if="showing"
Laravel News
class="fixed inset-0 w-full h-screen flex items-center justify-c
@click.self="close"
>
<div class="relative w-full max-w-2xl bg-white shadow-lg rounded
<button
aria-label="close"
class="absolute top-0 right-0 text-xl text-gray-500 my-2 mx-
@click.prevent="close"
>
×
</button>
<slot />
</div>
</div>
</Transition>
</template>

// script...

<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: all 0.4s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>

Fixing scroll issues

Overall, the component is working pretty well. We can


open/close the modal, it fades in nicely, and is really reusable. If
you add the component to a page with a lot of content though,
you might notice one issue. While the modal is open, if you try
to scroll the page, the background is allowed to scroll. This is
usually not desirable, so I’ll show you how to fix that issue. We
can add a Vue watcher to the showing prop. When the showing
prop is set to true, we need to add overflow: hidden to the
body element of our page. When it is set to false, we need to
remove that style. We can use the .overflow-hidden class
Laravel News
provided by Tailwind.

<script>
export default {
props: {
showing: {
required: true,
type: Boolean
}
},
watch: {
showing(value) {
if (value) {
return document.querySelector('body').classList.add('overflow-
}

document.querySelector('body').classList.remove('overflow-hidden
}
},
methods: {
close() {
this.$emit('close');
}
}
};
</script>

Conclusion

Now that our component is complete, you’re free to use it as


you wish, in multiple places with di erent content in each
place. It’s a really useful component for showing small forms,
getting user confirmations, and other use cases. I’d love to hear
how you end up using the component!

This component is based on some principles taught in Adam


Wathan’s “Advanced Vue Component Design” course and
simplified/modified for my needs. If you’re interested in
learning more about this subject and other advanced Vue.js
practices, I would highly recommend checking out his course!
Filed in: News / tailwind / Vue.js
Laravel News

Tired of managing servers? Check out the Serverless Laravel course

L A R AV E L N E W S PA R T N E R S
Laravel News

Students and Teachers, save up to 60% on Adobe Creative Cloud.

ADS VIA CARBON

Laravel Jobs

Backend So ware Engineer (PHP Developer)


Austin TX, Bonita Springs FL
Certified eSupport Corp
Laravel News
Skilled Full Stack Laravel Developer (fulltime)
Remote
Qbixx | Webservices

So ware Developer
Remote
Blueprint Title Company

Senior PHP Developer


London or Newcastle, UK (currently remote)
The Labour Party

Backend PHP Developer


Hamburg, Germany
ABOUT YOU GmbH

Newsletter

Join 31,000+ others and never miss out on new tips, tutorials, and more.

EMAIL ADDRESS SUBSCRIBE

Laravel SNS Events Package


Laravel SNS Events is a package that allows you to listen to Amazon
Simple Notification Service (SNS) webhooks via La…

Subscription billing with Laravel Cashier for Mollie


Laravel Cashier for Mollie is a first-party Cashier package—created and
maintained by Sander van Hoo —which provides…

LINKS NEWSLETTER ADVERTISE ARCHIVE JOBS


YO U R ACCO U NT C O N TA C T

Laravel News
NEWS TUTO RI ALS PAC K AG E S BOOKS INTERVIEWS

TRAINING RESOURCES A P P L I C AT I O N S

© 2 0 1 2 - 2 0 2 0 L A R AV E L N E W S — B Y E R I C L . B A R N E S - A D I V I S I O N O F D O T D E V I N C .

D E S I G N & F R O N T- E N D C O D E B Y

You might also like