jQuery simple and accessible modal window, using ARIA

Find/fork me on Github

Other accessible plugins

This jQuery plugin will add a shiny and accessible modal window, using ARIA.

Last updates

30rd of November, 2020: as kindly spotted and fixed by @jpyrat, event propagation was stopped on js-modal-close listener, and this was not necessary, so it has been removed.

1st of September, 2019: as kindly spotted by @twikito, the focus trap had a bug with some input type="hidden", it is fixed.

21st of March, 2018: added a class on modal container div role="document" class="<your-prefix-class>-modal__wrapper"), for enabling styling this wrapper (if needed).

23rd of December, 2017: added option class="js-modal-close" (put it on any element in the modal content) to trigger a click on close button.

First simple example

<button class="js-modal"
 data-modal-prefix-class="simple"
 data-modal-text="Hello world!"
 data-modal-title="Title"
 data-modal-close-text="Close"
 data-modal-close-title="Close this window">
  Show me a modal window
</button>

Second simple example

<button class="js-modal"
 data-modal-prefix-class="simple-animated"
 data-modal-content-id="modal_id_2nd_example"
 data-modal-title="Title for your modal"
 data-modal-close-text="Close it"
 data-modal-close-title="Close it, really">
  Show me another modal
</button>
<div id="modal_id_2nd_example" class="hidden">Woot, you can take the content of a hidden <code>div</code>, and it is animated.</div>

Some informations about this script

How it works

Basically, when you activate one, the scripts wraps all the page into a div id="js-modal-page", adds the noscroll class on the body element (to remove scroll with CSS if needed), then inserts a dialog element at the end of your page, puts the focus into it and traps focus in the modal window. When you exit it, the focus is given back to the element that opened it.

For mouse users, they can click outside the modal window to close it.

If you never activate a modal window, it won’t be anywhere in the code.

Options and attributes

If you need to close it, add class="js-modal-close" on an element in the modal content, it will trigger a click on close button.

How to style it

Here is the minimal set of styles needed to make it work (without data-modal-prefix-class attribute):

/* needed for old browsers */
dialog {
  display: block;
}
/* removes scroll when modal is opened */
.no-scroll {
  overflow: hidden;
}
/* overlay covers everything */
.modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  z-index: 666;
}
/* modal */
.modal {
  position: fixed;
  left: 25%;
  right: auto;
  top: 15%;
  width: 50%;
  background: #fff;
  z-index: 667;
}

Here are the styles used for this page, I’ve used data-modal-prefix-class="simple" to prefix elements, so each element will start with .simple-:

/* needed for old browsers */
dialog {
  display: block;
}
/* removes scroll when modal is opened */
.no-scroll {
  overflow: hidden;
}
/* overlay covers everything */
.simple-modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background: #fff;
  opacity: .8;
  z-index: 666; /* satan inside */
  cursor: pointer;
}
/* modal */
.simple-modal {
  position: fixed;
  left: 15%;
  top: 5%;
  width: 70%;
  max-height: 98vh;
  right: auto;
  border: 2px solid #000; 
  background: #fff;
  z-index: 667;
  padding: 2em;
  overflow: auto;
}
.simple-modal-close {
  float: right;
  background: #933;
  border-radius: 1em;
  color: #fff;
  padding: .25em;
  text-decoration: none;
  line-height: 1.2;
  text-align: center;
}
.simple-modal-close:focus,
.simple-modal-close:hover,
.simple-modal-close:active {
  background: #882525;
}
.simple-modal-overlay[data-background-click="disabled"] {
  cursor: auto;
}

/* it can be easily adapted in media-queries for tablets/mobile */

/* for this example: tablets */
@media (max-width: 55.625em) {

  .simple-modal {
    left: 5%;
    top: 5%;
    bottom: 5%;
    width: 90%;
  }
  
}

/* for this example: mobile */
@media (max-width: 44.375em) {

  .simple-modal {
    left: 1%;
    top: 1%;
    max-width: 98%;
    bottom: 1%;
  }

}


/* another modal styling example */
/* tooltip modal for it’s easy button */
.simple-left-modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background: rgba(0, 0, 0, .8);
  opacity: .8;
  z-index: 666;
  cursor: pointer;
}

.simple-left-modal {
  left: auto;
  right: 0;
  top: 0;
  bottom: 0;
  height: 100%;
  z-index: 667;
  position: fixed;
  width: 40em;
  max-width: 100%;
  padding: 1em;
  font-size: 1em;
  border: 0;
  overflow: auto;
  background-color: #fff ;
  background-image:
      -webkit-linear-gradient(
        top,
        #882525 3em,
        #f7f7f7 3em
      );  background-image:
      linear-gradient(
        to bottom,
        #882525 3em,
        #f7f7f7 3em
      );
  background-attachment: local;
}
.simple-left-modal-close {
  position: absolute;
  top: .25em;
  right: 0;
  background: transparent;
  color: #fff;
}

Other previous updates

18th of August, 2017: fixed an issue on VoiceOver/Mac, as kindly reported by @mdparker26, and with great help of @goetsu, @johan_ramon and @romaingervois.

8th of June, 2017: added attribute data-modal-focus-id, as kindly suggested by @jpyrat.

7th of June, 2017: added attribute aria-haspopup, as kindly suggested by @johan_ramon.

15th of May, 2017: fixed a missing text on overlay, as kindly suggested by @juliemoynat.

10th of April, 2017: linted and re-indented code properly.

23th of March, 2017: added aria-modal="true" to dialog element, as kindly suggested by @johan_ramon.

21th of March, 2017: fixed a selector bug that could cause problems with jQuery 2.x and 3.x (1.x versions were not affected).

19th of March, 2017: added attribute data-modal-close-img" to set up an image in close button.
Added another example of styling modal on “it’s easy” button below.

6th of March, 2017: added attribute type="button" to button, to avoid problems in SharePoint.

2nd of November, 2016: added attribute open to dialog, as suggested by @samrichca.

21st of October, 2016: Fixed a bug in variable declarations: thanks @pepemiyashiro.

18th of April, 2016: added a class that wraps the text of the close button.

17th of April, 2016: When using data-modal-content-id, if there was an id in this content, it was duplicated (which can create issues). It is fixed (bug reported thanks to @goetsu).

21st of March, 2016: this plugin is available on Bower (thanks to @Zubrik).
It can be installed using bower install jquery-accessible-modal-window-aria.

12th of February, 2016: Fixed an issue when focus is outside the page with an opened modal (thanks to @goetsu).
Added an example with animation.

18th of January, 2016: this plugin is available on NPMjs.com. (see other previous updates)

17th of December, 2015: fixed some CSS issues on mobile (seems to be ok for iPhone/Android/Window Phone), added the possibility to remove scroll on the body tag.

20th of July, 2015: fixed a Chrome bug in the sample, thanks to @CindyLuko.

30th of June, 2015: added two new attributes, data-modal-prefix-class will prefix the modal CSS element classnames (basically, you can now have separated modal styles), and data-modal-background-click="disabled" will disable the possibility to click outside the modal window to close it (not activated by default).

26th of May, 2015: fixed a style bug under Chrome, thanks to @herve_Mirguet.

19th of April, 2015: a small bug in the keyboard navigation in the modal, and some performance/refactoring work has been made, thanks to @whatevertechno.