#Modals
Modals are CSS-powered prompts designed for any site.
A modal
comprises of these classes:
modal
- the darkened translucent background around modal-content
. Think of this as the modal container.modal-content
- the main dialog itself.modal-header
- header or title bar of the dialog.modal-body
- main contents of the dialog.modal-footer
- bottom portion of dialog.There is quite a lot of flexibility when it comes to building your modal dialog. Typically, the modal-header
consists of some title and a close button, the modal-body
has whatever content you want, and the modal-footer
consists of buttons to act on a prompt.
There are 2 ways to interact with the modal: JavaScript or plain CSS.
This is the most straight forward approach for interacting with the modal
. We can define a simple function to toggle the .modal--visible
class on the modal
to hide and show it.
<script>
function toggleModal() {
// Toggle modal visibility
const modal = document.querySelector('#example-modal');
modal.classList.toggle("modal--visible");
}
</script>
<!-- Button to open/close modal -->
<button onclick="toggleModal()">Open Modal</button>
<div class="modal modal--visible" id="example-modal"><a onclick="toggleModal" class="modal-overlay close-btn" aria-label="Close"></a>
<div class="modal-content" role="document">
<div class="modal-header u-flex u-justify-space-between">
<div class="modal-title">Modal Dialog</div>
<div onclick="toggleModal()"
aria-label="Close"><span class="icon" style="cursor: pointer;"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" class="u-inline-block fa-times w-2 h-4 fa-wrapper" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg></span></div>
</div>
<div class="modal-body">
<!-- Some code here -->
</div>
<div class="modal-footer u-text-right"><a onclick="toggleModal()"
class="u-inline-block mr-1"><button class="btn--sm">Cancel</button></a><a onclick="toggleModal()"
class="u-inline-block"><button class="btn-primary btn--sm">Share</button></a></div>
</div>
</div>
This section covers interacting with the modal via CSS and navigation events. This approach relies more on implicit behaviors that exist within the browser rather than specifying how the logic works yourself like with the JavaScript approach
Opening a Modal
To open a modal, a link must be used with the href
set to be the id
of the modal. For example, if I create a modal
with id
test-modal
, then the href
of the link to open the modal
should be set to #test-modal
.
<div class="modal" id="test-modal">
<!-- Modal stuff -->
</div>
<a href="#test-modal">Open Modal</a>
Close Button Creation/Behavior
The close button can be created using the btn-close
class, but the examples shown here, we will be using a FontAwesome glyph wrapped with a link.
<div class="modal" id="test-modal">
<div class="modal-header u-flex u-justify-space-between">
<a href="#anchor-to-background" aria-label="Close">
<span class="icon">
<i class="fa-wrapper fa fa-times"></i>
</span>
</a>
</div>
</div>
Notice that the close link must be wrapped by an anchor tag containing an href
to some HTML element. The value you put in this href
will alter the close behavior of the modal dialog.
Return to Specific Div
<a href="#TAG-OUTSIDE" class="modal-overlay close-btn" aria-label="Close"></a>
Return to Top
<a href="#" class="modal-overlay close-btn" aria-label="Close"></a>
Keep Scroll Position
<a href="#NON-EXISTENT-DIV" class="modal-overlay close-btn" aria-label="Close"></a>
Below is an example of a basic modal dialog.
<div class="modal modal-animated--zoom-in" id="basic-modal">
<a href="#searchModalDialog" class="modal-overlay close-btn" aria-label="Close"></a>
<div class="modal-content" role="document">
<div class="modal-header u-flex u-justify-space-between"><a href="#components" aria-label="Close"><span class="icon"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" class="u-inline-block fa-times fa-w-11 fa-wrapper" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg></span></a>
<div class="modal-title">Invite</div>
</div>
<div class="modal-body">
<div class="r">
<h3 class="font-alt font-light u-text-center">Invite people to project</h3></div>
<div class="space"></div>
<div class="input-control">
<input type="text" class="input-contains-icon" placeholder="Search for team members"><span class="icon"></div>
<div class="divider"></div>
<div class="my-1">
<div class="tile tile--center py-1 px-2 my-1" style="box-shadow: rgba(0, 0, 0, 0.06) 0px 3px 6px, rgba(0, 0, 0, 0.03) 0px 3px 6px;">
<div class="tile__icon">
<figure class="avatar text-white bg-teal-400" data-text="Jn"></figure>
</div>
<div class="tile__container">
<p class="tile__title m-0">John Newman</p>
<p class="tile__subtitle m-0">jnewman@gmail.com</p>
</div>
<div class="tile__buttons">
<button class="btn-success btn--sm uppercase"><span class="icon"></span></button>
</div>
</div>
<div class="tile tile--center py-1 px-2 my-1" style="box-shadow: rgba(0, 0, 0, 0.06) 0px 3px 6px, rgba(0, 0, 0, 0.03) 0px 3px 6px;">
<div class="tile__icon">
<figure class="avatar text-white bg-teal-500" data-text="Fw"></figure>
</div>
<div class="tile__container">
<p class="tile__title m-0">Franklin Watson</p>
<p class="tile__subtitle m-0">fwatsonm@gmail.com</p>
</div>
<div class="tile__buttons">
<button class="btn-success btn--sm uppercase"><span class="icon"></span></button>
</div>
</div>
<div class="tile tile--center py-1 px-2 my-1" style="box-shadow: rgba(0, 0, 0, 0.06) 0px 3px 6px, rgba(0, 0, 0, 0.03) 0px 3px 6px;">
<div class="tile__icon">
<figure class="avatar text-white bg-teal-600" data-text="Cr"></figure>
</div>
<div class="tile__container">
<p class="tile__title m-0">Cornelia Roberts</p>
<p class="tile__subtitle m-0">croberts@outlook.com</p>
</div>
<div class="tile__buttons">
<button class="btn-danger btn--sm uppercase"><span class="icon"></span></button>
</div>
</div>
<div class="tile tile--center py-1 px-2 my-1" style="box-shadow: rgba(0, 0, 0, 0.06) 0px 3px 6px, rgba(0, 0, 0, 0.03) 0px 3px 6px;">
<div class="tile__icon">
<figure class="avatar text-white bg-teal-700" data-text="Da"></figure>
</div>
<div class="tile__container">
<p class="tile__title m-0">Dominic Alvarado</p>
<p class="tile__subtitle m-0">dalvarado@yahoo.com</p>
</div>
<div class="tile__buttons">
<button class="btn-success btn--sm uppercase"><span class="icon"></span></button>
</div>
</div>
<div class="tile tile--center py-1 px-2 my-1" style="box-shadow: rgba(0, 0, 0, 0.06) 0px 3px 6px, rgba(0, 0, 0, 0.03) 0px 3px 6px;">
<div class="tile__icon">
<figure class="avatar text-white bg-teal-800" data-text="Sl"></figure>
</div>
<div class="tile__container">
<p class="tile__title m-0">Stanley Lim</p>
<p class="tile__subtitle m-0">slim@stanleylim.me</p>
</div>
<div class="tile__buttons">
<button class="btn-success btn--sm uppercase"><span class="icon"></span></button>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="form-section u-text-right">
<a className="mr-1" href="#components">
<button class="btn btn--sm u-inline-block">Cancel</button>
</a>
<a href="#components">
<button class="btn-info btn--sm u-inline-block">Confirm</button>
</a>
</div>
</div>
</div>
</div>
Modals come in 3 sizes: modal-small
, normal, and modal-large
. Append these classes to modal
to set the size. Note that these width constraints apply to .modal-content
and not .modal
as .modal-content
is the dialog itself.
<!-- Small modal -->
<div class="modal modal-small">
<div class="modal-content">
<!-- Stuff -->
</div>
</div>
<!-- Normal modal -->
<div class="modal">
<div class="modal-content">
<!-- Stuff -->
</div>
</div>
<!-- Small modal -->
<div class="modal modal-large">
<div class="modal-content">
<!-- Stuff -->
</div>
</div>
Modals have 3 animations: modal-animated--dropdown
, modal-animated--zoom-in
, and modal-animated--zoom-out
. Append these classes to modal
to set the animation mode.
<!-- Drop down modal -->
<div class="modal modal-animated--dropdown">
<div class="modal-content">
<!-- Stuff -->
</div>
</div>
<!-- Zoom in modal -->
<div class="modal modal-animated--zoom-in">
<div class="modal-content">
<!-- Stuff -->
</div>
</div>
<!-- Zoom out modal -->
<div class="modal modal-animated--zoom-out">
<div class="modal-content">
<!-- Stuff -->
</div>
</div>
To be complaint with WAI-ARIA Best Practices, you can easily include this snippet of JavaScript to close all dialogs when hitting the escape key.
document.addEventListener('keyup', function(e) {
if(e.key === "Escape") {
const modals = document.querySelectorAll('.modal-overlay');
for (const modal of modals) {
modal.click();
}
}
});