DEV Community

Cover image for Dialogs vs. Modals: Is there a difference?
Tim Smith
Tim Smith

Posted on

Dialogs vs. Modals: Is there a difference?

You may hear developers talking about dialogs and modals on websites as being similar things. Are they really the same though? The answer is: sort of. Modals are a type of dialog, but not all dialogs are modals. They do have similar appearances and functionality, but with a key difference. In this blog post, I'll explore modals and dialogs and explain the difference while showing you how they can be used natively in the browser.

Please note: I will be using the term "dialog" to represent a non-modal dialog and the term "modal" to represent a modal dialog. This is to describe the behavior of each rather than the HTML element to build them.

Dialogs and modals?

While both dialogs and modals can appear similar, there are different reasons for using each. First we'll discuss what they are and how they're used and then we'll discuss how they're different.

How are dialogs and modals similar?

Dialogs and modals can serve similar purposes: to display some data or collect some data outside the flow of the normal document. This could be a form collection, a call-to-action, or something similar that you want to be front-and-center for a user. Typically, people refer to these things as "popups".

Dialogs and modals are designed to draw the user's attention.

I'm sure you've seen them all over the web if you've been using the internet for any amount of time. Typically, people complain about these because they can be disruptive when using a website. Because of this, it's important to use them in this fashion sparingly. One of the two items is more disruptive than the other though...

How are dialogs and modals different?

The way in which dialogs and modals differ has to do with how it allows the user to interact with the document when it's open. What does that mean? Let's talk about each one:

  • A dialog still allows a user to interact with other content on the page while it's open (i.e. click buttons and links visible around the dialog)
  • A modal locks down the page until something is done. This is typically done with a background that covers all other content so the modal must be dealt with. This is the more disruptive of the two options.

Understanding the differences between the two will allow you to make the right choice about which option is best for your situation. As a general rule, you should reach for the dialog unless it's absolutely necessary to prevent the user from interacting with other elements.

The dialog element

In years past, building dialogs and modals consisted of nesting divs inside of divs while applying some styles to make it look and behave a certain way using javascript and css. While some of this is still necessary due to it's interactive nature, the dialog has come a long way since then.

One of the big problems around the dialog components of old are a lack of accessibility. They just weren't easy to understand and use with screen readers. There was a role="dialog" attribute which could be applied, but many times accessibility is unfortunately an afterthought.

David Rose, shocked, backs away to avoid my callout.

Despite this, the web has evolved quite a bit in the last several years to make accessibility much more "baked in" through the use of semantic elements. Because of this, we have a dialog element in HTML5 which takes care of a lot of these things for us. In addition to being accessible, the dialog element gives us the ability to use it as both a dialog and a modal, although the way to do this may not be super intuitive.

Dialog element basics

A dialog element is hidden by default and accepts children to be displayed inside the dialog. It also accepts an open attribute which decides whether the dialog should be visible to the user or not. Past that, it's got all the same attributes you would expect on a generic HTML element (class, id, aria-stuff, etc).

How do I use a dialog?

Now that we've discussed what attributes a dialog element can have, we should probably talk about how to actually use the thing. I mentioned that there is an open attribute available on a dialog element. By changing this value, you can show and hide the dialog box. That's great, but how do you actually do that? First, lets create a function which toggles the dialog between open and closed:

const toggleDialog = () => {
  // Get the dialog element
  const dialog = document.getElementById("dialog");
  // Figure out what the 'open' attribute is set to
  const open = dialog.getAttribute("open");
  // Set the dialog's 'open' value accordingly
  if (open) {
    dialog.removeAttribute("open");
  } else {
    dialog.setAttribute("open", "true");
  }
};
Enter fullscreen mode Exit fullscreen mode

When using HTML, the dialog will be shown if the open attribute is present, regardless of what the value is. In the function above, I am looking to see if the dialog has the open attribute set. If so, it removes the attribute but if the open attribute is missing, it adds it with a value of true.

Next, I will create the dialog itself. For now, I will just create a basic dialog element with some content inside:

<dialog id="dialog">I'm a dialog</dialog>
Enter fullscreen mode Exit fullscreen mode

Finally, I want a button the user can click to control the dialog. Clicking the button once will show the dialog and clicking the button a second time will hide the dialog.

<button onclick="toggleDialog()">This button toggles a dialog</button>
Enter fullscreen mode Exit fullscreen mode

Once this is built out, your result should look something like this:

A dialog element without any custom styles

How do I use a modal?

Although my HTML code will be the same for the modal (except for the dialog ID), the function being called will be different for a modal. This is because the browser provides a method which comes built-in to handle the modal's behavior. Unlike the dialog, a modal requires two separate buttons to handle opening and closing the dialog. This is because any buttons outside the dialog will be inaccessible while it is open. Because of this difference, I will create functions for each task:

const openModal = () => {
  // Get the modal element
  const modal = document.getElementById("modal");
  // Call the built-in 'showModal' method to display the modal
  modal.showModal();
};

const closeModal = () => {
  // Get the modal element
  const modal = document.getElementById("modal");
  // Call the built-in 'close' method to close the modal
  modal.close();
};
Enter fullscreen mode Exit fullscreen mode

The button and dialog should look pretty much the same as the previous code except for an additional button to close the modal:

<button onclick="openModal()">This button opens a modal</button>
<!--The dialog element being used as a modal-->
<dialog id="modal">
  <p>I'm a modal</p>
  <!-- A button to be able to close the modal -->
  <button onclick="closeModal()">Close</button>
</dialog>
Enter fullscreen mode Exit fullscreen mode

With this code in place, clicking the button should display something like this:

A modal element without any custom styles

The ::backdrop pseudoselector

You may notice that a key difference between the dialog and modal is a backdrop which covers all of the content behind the modal. This is what makes a modal different because it prevents the user from accessing the page content until the modal is closed. This backdrop doesn't look very interesting though. Lucky for us, there is a pseudoselector that can be used to target and style the backdrop so it better matches your use case. You can use the ::backdrop pseudoselector like this:

dialog::backdrop {
  background: #111111;
}
Enter fullscreen mode Exit fullscreen mode

It's worth noting that the backdrop only appears on modals, so the pseudoselector will not have any impact on the dialogs you're displaying.

Accessibility

I mentioned earlier that accessibility is a big benefit we get from the dialog element in HTML5, but what does that mean? There is a role="dialog" attribute which can be assigned to an element to tell a screen reader that the item is a dialog. In addition, an aria- tag should be added to tell the screen reader whether the element is visible or not.

<div role="dialog" aria-hidden="true">
  <p>This is a dialog</p>
</div>
Enter fullscreen mode Exit fullscreen mode

By using the dialog element, the browser takes care of these things for us! So instead of the code above, we can simply write:

<dialog>
  <p>This is a dialog</p>
</dialog>
Enter fullscreen mode Exit fullscreen mode

While the two attributes may not seem like a big deal, it may not always be something you think of when you create a dialog or modal. Using a dialog element allows us to focus on building cool things instead of getting into the nitty gritty and sometimes guessing on which aria- attributes are appropriate.

Like the dialog element, Max Goof is pretty cool!

Making my dialogs cool

As previously discussed, my dialogs are pretty lame. I think it's time to add some styles. In the spirit of Max Goof, let's build a modal he might have looked at for his favorite singer, Powerline. First, I'll set some CSS variables based on some of the palettes I've seen online:

:root {
  --background: #111;
  --text: #fff;
  --yellow: #d1933f;
  --red: #9b2a4e;
  --purple: #7044a5;
}
Enter fullscreen mode Exit fullscreen mode

Now that I have some colors ready to go, it's time to start styling. Here's some styles I'm using for all the things that aren't the dialogs:

html,
body {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
}

body {
  font-family: sans-serif;
  color: var(--text);
  text-align: center;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
body:before {
  content: "";
  display: block;
  position: absolute;
  inset: 0;
  background-image: url("/bg.jpg");
  background-size: cover;
  background-position: top center;
  z-index: -1;
}
body:after {
  content: "";
  display: block;
  position: absolute;
  inset: 0;
  background: radial-gradient(transparent, black);
  z-index: 0;
  line-height: 1.5rem;
}

main {
  position: relative;
  z-index: 1;
}

a {
  color: var(--text);
  background: var(--red);
  padding: 0.25rem;
  text-decoration: none;
  transition: background 0.3s;
}
a:hover {
  background: linear-gradient(
    to bottom right,
    var(--yellow),
    var(--red),
    var(--purple)
  );
}

button {
  background: var(--yellow);
  font-size: 1.1rem;
  padding: 0.5rem;
  margin: 1rem;
  border: 2px solid var(--red);
  border-radius: 8px;
  cursor: pointer;
}
button:hover {
  box-shadow: 0 0 1rem var(--red);
}

.headline {
  font-size: 1.5rem;
  font-weight: bold;
  text-transform: uppercase;
  color: var(--text);
  text-shadow: 5px 5px 0 var(--red);
}
Enter fullscreen mode Exit fullscreen mode

I would like to style the dialog as well as the backdrop according to the palette I've chosen so it doesn't stick out like a sore thumb. Below are the styles I'll be using for the dialog:

dialog {
  position: fixed;
  background: linear-gradient(
    to bottom right,
    var(--yellow),
    var(--red),
    var(--purple)
  );
  margin: 0 auto;
  text-align: center;
  width: 400px;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 8px;
  border: 1px solid var(--purple);
}
dialog::backdrop {
  background: rgba(74, 62, 89, 0.4);
}
Enter fullscreen mode Exit fullscreen mode

Now my modal looks like this:

The finished modal

You can see the full code for this at https://github.com/iamtimsmith/dialog-vs-modal and you can visit the finished site at https://dialog-vs-modal-nine.vercel.app

Conclusion

Dialogs and modals have become a common part of the web, but it's not always clear which one is appropriate for a given situation. Now you'll know that a dialog is used when the user should still be able to interact with the main page content, while a modal should be used when the dialog should prevent the user from accessing the rest of the page. With this in mind, you can hopefully build better and more accessible user experiences when using a popup.

Have questions? You can find me on Twitter at @iam_timsmith.

Top comments (4)

Collapse
 
bwin profile image
Benjamin Winkler

Hey I don't think you got the terminology quite right.
"Modal" is a qualifier for a dialog (ie a dialog can be modal or non-modal), not a standalone thingy.
IMHO the premise is misleading. "Dialog vs modal" should be "(non-modal) dialog vs modal dialog" IMO.
developer.mozilla.org/en-US/docs/W...

For example you write "Below are the styles I'll be using for the dialog" followed by "Now my modal looks like this".

IMO you should still describe the use cases and differences between non-modal and modal dialogs, but I think you should change the title and be more specific with the terminology to not cause confusion. After all you're trying to teach others here.

Have a nice day!

Collapse
 
iam_timsmith profile image
Tim Smith

@bwin I appreciate your feedback and agree with your point. I have updated the article to reflect the better terminology of modal and non-modal dialogs.

Collapse
 
wraith profile image
Jake Lundberg

great topic choice šŸ˜Š this is something i really think deserves more attention. way to spread the word!

Collapse
 
ilkergonenc profile image
ig

Thanks it's been a mystery for me for a while, it's nice to see someone get in to this topic in depth. šŸ™