Create Custom Modal Using React & Tailwind CSS

Create Custom Modal Using React & Tailwind CSS

Post by: Niraj Dhungana

Posted on: Jan 14 2022

#react# tailwind# modal

You if are familiar with react-native then we have a built-in Modal component. We can use it like this.

1
2
3
4
5
6
7
8
// works only in react native
import {Modal} from 'react-native'
const MyModal= ({ visible }) => {
    return (
    <Modal visible={visible}>
        ...
    </Modal>
)}

Here we need to import the Modal component and we can pass the state like visible to show and hide the Modal. Now in this post we will see how we can create that same kind of modal inside React using Tailwind CSS.

Demo React Tailwind Modal

1
2
3
4
5
6
7
8
9
// our fianl project
import {CustomModal} from './components'
const App= () => {
... 
    return (
      <CustomModal visible={showModal}>
          {/* your content */}
      </CustomModal>
)}

Things we are covering.

  • Initializing the project.
  • Creating a button to open a modal.
  • Creating a modal itself.
  • Handling the state to show and hide the modal.

Let’s start coding.

Initializing the project.

First you have to create a project using React and Tailwind CSS. And I hope you already have those thighs setup. If not then you can follow this doc to create projects with react and tailwind css.

Creating a button to open a modal.

Now I hope you have initialized your project. Now let's create a button using which we can open and close a modal.

1
2
3
4
5
6
7
8
9
export default function App() {
  return (
    <div className="w-screen h-screen flex items-center justify-center">
        <button className="py-2 px-5 bg-blue-500 text-white">
          Open Modal
        </button>
    </div>
  );
}

This is the code that I am using to create this button. Here I have this div with flex and justify-center and item-center also you can see we have this width and height full of screen and that is because I want to make this button at the center of this container.

Now you should see something like this.

Modal openner

Creating a modal itself.

Now we have our button it is time to create the model itself. I am going to create this model with fixed height and width which is going to appear at the top of any component.

For that inside Tailwind CSS there is this very interesting class called inset-0. So let's see how we can use it.

1
2
3
4
5
6
7
8
9
10

export default function CustomModal({children}) {
  return (
    <div
      className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 backdrop-blur-sm"
    >
      {children}
    </div>
  );
}

Inside this custom modal component first of all I am accepting these children as the prop of this component. Now let me explain the meaning of these classes.

First two or three classes are self-explanatory but here what we are doing first we are making its position: fixed; and giving this class called inset-0. Which means it will now cover the entire screen because it is fixed so it will appear at the top of any component.

And these flex properties will render children at the center of this CustomModal component. Then we have this class called bg-black for background, bg-opacity-50 to give background an opacity of 50 and finally we have backdrop-blur-sm to give our React Modal a blurry effect.

React Modal with 50% opacity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
import CustomModal from "./components/CustomModal";

export default function App() {
  return (
    <>
      <div className="...">
        <button className="...">
          Open Modal
        </button>
      </div>
      <CustomModal>
        {/* here you can add your other components (JSX)*/}
      </CustomModal>
    </>
  );
}

Now you should see something like this. If you render this modal inside the App component like above. Also you can use any of your components.

Handling the state to show and hide the modal.

Now we have our modal ready, let's handle the state so that we can show and hide this modal according to our need.

1
2
3
4
5
6
7
8
9
export default function CustomModal({ children, visible }) {
  if (!visible) return null;

  return (
    <div className="use above classes">
      {children}
    </div>
  );
}

Here we are accepting another prop called visible which will be a boolean value. And if this value is false we are rendering null which means nothing.

Now we have the prop called visible which we can use to show and hide our Modal. We can manage this state inside the component where we are rendering the Modal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { useState } from "react";
import CustomModal from "./components/CustomModal";

export default function App() {
  const [showModal, setShowModal] = useState(false);
  return (
    <>
      <div className="...">
        <button className="..."
         onClick={() => setShowModal(false)}
         >
          Open Modal
        </button>
      </div>
      <CustomModal visible={showModal}>
        {/* here you can add your other components (JSX)*/}
      </CustomModal>
    </>
  );
}

Like here I can use this showModal state inside the App component because I am rendering the Modal inside App.js. And if you notice (line-10) I am using that onClick listenner to change the state or open the Modal component.

Now let’s see how we can close the modal for that. This time I will start with the App component. Here I am going to pass a prop to our CustomModal called onClose. Which will change the state of showModal to false. See code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
export default function App() {
  const [showModal, setShowModal] = useState(false);
  return (
    <>
      <div className="...">
        ...
      </div>
      <CustomModal
        onClose={() => setShowModal(false)}
        visible={showModal}
        >
        {/* here you can add your other components (JSX)*/}
      </CustomModal>
    </>
  );
}

Now we will get that onClose prop inside our CustomModal and use it to hide the modal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default function CustomModal({ children, visible, onClose }) {
  if (!visible) return null;

  const handleOnBackDropClick = (e) => {
    if (e.target.id === "backdrop") onClose && onClose();
  };

  return (
    <div
      id="backdrop"
      onClick={handleOnBackDropClick}
      className="..."
    >
      {children}
    </div>
  );
}

Here we are first destructuring the prop (onClose) then calling it inside the handleBackdropClick method if the clicked element has the ID called backdrop. Because if you don’t check the ID our modal will close anywhere we click. This is called event bubbling.

Also you can create a separate close button to close the Modal.

And don’t forget to add that id=’backdrop’ inside the main container (line number 10).

Now if you render something inside the Modal like I am rendering this fake newsletter component. You will see something like this.

Final Result React Tailwind Modal

Final Code