Creating modal is easy with html dialog element

Simple guide to create modals with native html dialog element (react examples)

Sep 27, 2022 - 3 min read

Basic dialog

Let's create a simple dialog and call show method to open the dialog.

App.jsx
import {useRef} from 'react'

export default function App() {
  const dialogRef = useRef(null)

  function openDialog() {
    dialogRef.current.show()
  }

  return (
    <div>
      <dialog ref={dialogRef}>
        <p>Hello Dialog!</p>
        <form method='dialog'>
          <button>Close</button>
        </form>
      </dialog>

      <button onClick={openDialog}>Open dialog</button>
    </div>
  )
}
Preview of opening dialog element

As it is simply a dialog, it does not have any backdrop and it is not centered. To make it a modal, we just need to use the showModal method.

Change the openDialog function and call showModal.

App.jsx
function openDialog() {
  dialogRef.current.showModal()
}
Modal example

Now it is centered and has a light dark backdrop.

Styling dialog element

Let's add some styles and opening animation to make the modal look nice.

styles.css
dialog {
  width: 200px;
  border: 2px solid lightblue;
  border-radius: 5px;
  padding: 1rem 2rem;
  text-align: initial;
}

dialog[open] {
  animation: show-dialog 0.2s ease normal;
}

dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
}

@keyframes show-dialog {
  from {
    transform: scale(0.9);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}
Modal with styles applied

Closing modal

We can use the close method to close the modal. Also note that, because the dialog has a form element which has method attribute set to dialog. So, clicking any button inside the form will also close the modal.

Let’s add a close icon inside the dialog.

App.jsx
import React, { useRef, useEffect } from 'react';

function closeCallback() {
  console.log('Dialog closed');
}

export default function App() {
  const dialogRef = useRef(null);

  function openDialog() {
    dialogRef.current.showModal();
  }

  function closeModal() {
    dialogRef.current.close();
  }

  useEffect(() => {
    const currentRef = dialogRef.current;
    currentRef.addEventListener('close', closeCallback);

    return () => currentRef.removeEventListener('close', closeCallback);
  }, []);

  return (
    <div>
      <dialog ref={dialogRef}>
        <p>Hello Dialog!</p>
        <form method="dialog">
          <button>Close</button>
        </form>
        <p className="close-icon" onClick={closeModal}>
          &#10799;
        </p>
      </dialog>

      <button onClick={openDialog}>Open dialog</button>
    </div>
  );
}
styles.css
.close-icon {
  position: absolute;
  inset: -15px 10px auto auto;
  font-size: large;
  cursor: pointer;
}
Modal close example

We have also added a close event handler, this can be used to notify any other component that the dialog has closed.

That's all.

You can learn more about dialog element and how to support older browsers at MDN.