Skip to main content

Project 04 · Beginner

Modal Box

A settings card with a button that opens a box on top of the page. You'll build it three ways: a popover with no JavaScript, a modal you put together yourself, and the browser's own <dialog>, which does most of that work for you.

  • 5 HTML ideas
  • 6 CSS ideas
  • 7 JavaScript ideas
  • 3 ways to build it

Why build it

Once you can open a box over the page, move focus into it, and lock everything behind it, you can build cookie banners, "Are you sure?" delete confirmations, sign-in prompts, and image lightboxes that keyboard and screen reader users can use and close. You'll also know what the dialog element does for you, and when to reach for it.

Skills you'll earn

  • Show and hide a box over the page with the popover attribute
  • Stop people clicking or tabbing to the page behind a modal, with inert
  • Move focus into a modal when it opens, and back where it was when it closes
  • Use the dialog element, and find out which button someone used to close it

01

Try it

Play with it first, then read the code that makes it work.

3 ways to build it

The popover attribute shows and hides a box with no JavaScript at all. It can't act on a choice, so this one just shows a message.

Result0px
New tab (opens in a new tab)
Download
<!doctype html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Modal Box</title>
		<link rel="stylesheet" href="style.css" />
	</head>
	<body>
		<main class="settings">
			<h1 class="settings-title">Settings</h1>
			<p class="status">Notifications are off.</p>
			<!-- popovertarget opens the element with that id, with no JavaScript. -->
			<button type="button" class="button button-primary" popovertarget="about">
				What are notifications?
			</button>
		</main>

		<!-- popover keeps this hidden until a button opens it, then puts it on top. -->
		<div
			class="modal"
			id="about"
			popover
			role="dialog"
			aria-labelledby="about-title"
		>
			<h2 class="modal-title" id="about-title">About notifications</h2>
			<p class="modal-text">
				Notifications tell you when something new is out. Press Escape or click
				outside this box to close it.
			</p>
			<div class="modal-actions">
				<!-- popovertargetaction="hide" makes this button only ever close it. -->
				<button
					type="button"
					class="button button-primary"
					popovertarget="about"
					popovertargetaction="hide"
				>
					Got it
				</button>
			</div>
		</div>
	</body>
</html>

02

How it works

The ideas behind it, one at a time, each next to the code that does it.

3 ways to build it

The popover attribute shows and hides a box with no JavaScript at all. It can't act on a choice, so this one just shows a message.

HTMLthe structure

  1. 01

    Hide a box with the popover attribute

    The popover attribute turns an element into a popover: the browser keeps it hidden until something opens it, then shows it on top of everything else on the page. It also closes it for you when someone presses Escape or clicks outside it. Here it holds the short message about notifications, with no JavaScript at all.

    		<!-- popover keeps this hidden until a button opens it, then puts it on top. -->
    		<div
    			class="modal"
    			id="about"
    			popover
    			role="dialog"
    			aria-labelledby="about-title"
    		>
  2. 02

    Open and close it with popovertarget

    A button needs to know which popover it controls. popovertarget points it at one by its id, here about, and each click opens or closes that popover. Adding popovertargetaction="hide" changes what the button does, so the Got it button only ever closes the popover.

    			<!-- popovertarget opens the element with that id, with no JavaScript. -->
    			<button type="button" class="button button-primary" popovertarget="about">
    				What are notifications?
    			</button>
    		</main>
    
    		<!-- popover keeps this hidden until a button opens it, then puts it on top. -->
    		<div
    			class="modal"
    			id="about"
    			popover
    			role="dialog"
    			aria-labelledby="about-title"
    		>
    			<h2 class="modal-title" id="about-title">About notifications</h2>
    			<p class="modal-text">
    				Notifications tell you when something new is out. Press Escape or click
    				outside this box to close it.
    			</p>
    			<div class="modal-actions">
    				<!-- popovertargetaction="hide" makes this button only ever close it. -->
    				<button
    					type="button"
    					class="button button-primary"
    					popovertarget="about"
    					popovertargetaction="hide"
    				>
    					Got it
    				</button>

CSSthe look

  1. 03

    Know what a popover doesn't do

    ::backdrop is a layer the browser puts behind an open popover, and this CSS uses it to dim the page. But a popover isn't a modal: Tab can still leave it and reach the button behind it. That's fine for a message someone reads and dismisses, not for a question that needs an answer.

    /* An open popover gets a ::backdrop too, but the page behind still works. */
    .modal::backdrop {
    	background: rgb(28 28 34 / 0.6);
    }

03

Wrap up

Track your progress, then go deeper or keep going.

Take it further

Once it works, try these on your own. Each one uses what you've just learned, plus one new idea.

  1. Challenge 01

    Fade and scale the modal in when it opens, and skip it for reduced motion.

  2. Challenge 02

    Ask for confirmation before something can't be undone, like deleting a note.

  3. Challenge 03

    Remember the answer in localStorage, so the modal only asks once.

Articles that go further into ideas from this project.

Finished Modal Box?

Mark it done to track your progress.

You finished Modal Box!

0 of 15 projects done.

Go deeper

The full article explains each idea in more depth, why the code is written this way, and more than fits on this page.

Article coming soon. See the series so far (opens in a new tab)