Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login

You must be logged to download. Click here to login


MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation


MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Javascript Modal Window: Making Modal Window usable and accessible

In this article we will understand how to work with Javascript Modal Window and we will show how to make modal windows more usable and accessible.

Modal Windows might be a blessing of additional screen real estate, providing a way to deliver contextual information, notifications and other actions relevant to the current screen. On the other hand, modals might feel like a hack that you’ve been forced to commit in order to cram extra content on the screen. These are the extreme ends of the spectrum, and users are caught in the middle. Depending on how a user browses the Internet,modal windows can be downright confusing.

Modals quickly shift visual focus from one part of a website or application to another area of (hopefully related) content. The action is usually not jarring if initiated by the user, but it can be annoying and disorienting if it occurs automatically, as happens with the modal window’s evil cousins, the “nag screen” and the “interstitial.”

However, modals are merely a mild annoyance in the end, right? The user just has to click the “close” button, quickly skim some content or fill out a form to dismiss it.

Well, imagine that you had to navigate the web with a keyboard. Suppose that a modal window appeared on the screen, and you had very little context to know what it is and why it’s obscuring the content you’re trying to browse. Now you’re wondering, “How do I interact with this?” or “How do I get rid of it?” because your keyboard’s focus hasn’t automatically moved to the modal window.

This scenario is more common than it should be. And it’s fairly easy to solve, as long as we make our content accessible to all through sound usability practices.

Better Semantics Lead To Better Usability And Accessibility

Usability and accessibility are lacking in many modal windows. Whether they’re used to provide additional actions or inputs for interaction with the page, to include more information about a particular section of content, or to provide notifications that can be easily dismissed, modals need to be easy for everyone to use.

To achieve this goal, first we must focus on the semantics of the modal’s markup. This might seem like a no-brainer, but the step is not always followed.

Suppose that a popular gaming website has a full-page modal overlay and has implemented a “close” button with the code below:

Listing 1: Implementing close button
<div id="modal_overlay">
  <div id="modal_close" onClick="modalClose()">

Thisdivelement has no semantic meaning behind it. Sighted visitors will know that this is a “close” button because it looks like one. It has a hover state, so there is some visual indication that it can be interacted with.

But this element has no inherit semantic meaning to people who use a keyboard or screen reader.

There’s no default way to enable users to tab to adivwithout adding atabindex attribute to it. However, we would also need to add a:focusstate to visually indicate that it is the active element. That still doesn’t give screen readers enough information for users to discern the element’s meaning. An “X” is the only label here. While we can assume that people who use screen readers would know that the letter “X” means “close,” if it was a multiplication sign (using the HTML entity×) or a cross mark (❌), then some screen readers wouldn’t read it at all. We need a better fallback.

We can circumvent all of these issues simply by writing the correct, semantic markup for a button and by adding an ARIA label for screen readers:

Listing 2: adding aria label
<div id="modal_overlay">
  <button type="button" class="btn-close" id="modal_close" aria-label="close">

By changing thedivto a button, we’ve significantly improved the semantics of our “close” button. We’ve addressed the common expectation that the button can be tabbed to with a keyboard and appear focused, and we’ve provided context by adding the ARIA label for screen readers.

That’s just one example of how to make the markup of our modals more semantic, but we can do a lot more to create a useful and accessible experience.

Making Modals More Usable And Accessible

Semantic markup goes a long way to building a fully usable and accessible modal window, but still more CSS and JavaScript can take the experience to the next level.


Provide a focus state! This obviously isn’t exclusive to modal windows; many elements lack a proper focus state in some form or another beyond the browser’s basic default one (which may or may not have been cleared by your CSS reset). At the very least, pair the focus state with the hover state you’ve already designed:

Listing 3: Providing a focus state
.btn:hover, .btn:focus {
  background: #f00;

However, because focusing and hovering are different types of interaction, giving the focus state its own style makes sense.

Listing 4: styling the focus state
.btn:hover {
  background: #f00;

:focus {
  box-shadow: 0 0 3px rgba(0,0,0,.75);

Really, any item that can be focused should have a focus state. Keep that in mind if you’re extending the browser’s default dotted outline.


When a modal window loads, the element that the user last interacted with should be saved. That way, when the modal window closes and the user returns to where they were, the focus on that element will have been maintained. Think of it like a bookmark. Without it, when the user closes the modal, they would be sent back to the beginning of the document, left to find their place. Add the following to your modal’s opening and closing functions to save and reenable the user’s focus.

Listing 5:Saving last active element

var lastFocus;

function modalShow () {
  lastFocus = document.activeElement;

function modalClose () {
  lastFocus.focus(); // place focus on the saved element

Shifting Focus

When the modal loads, focus should shift from the last active element either to the modal window itself or to the first interactive element in the modal, such as an input element. This will make the modal more usable because sighted visitors won’t have to reach for their mouse to click on the first element, and keyboard users won’t have to tab through a bunch of DOM elements to get there.

Listing 6: Shifting Focus

var modal = document.getElementById('your-modal-id-here');

function modalShow () {
   modal.setAttribute('tabindex', '0');

Making Full Screen

If your modal takes over the full screen, then obscure the contents of the main document for both sighted users and screen reader users. Without this happening, a keyboard user could easily tab their way outside of the modal without realizing it, which could lead to them interacting with the main document before completing whatever the modal window is asking them to do.

Use the following JavaScript to confine the user’s focus to the modal window until it is dismissed:

Listing 7: Confining the user's focus

function focusRestrict ( event ) {
  document.addEventListener('focus', function( event ) {
    if ( modalOpen && !modal.contains( ) ) {
  }, true);

While we want to prevent users from tabbing through the rest of the document while a modal is open, we don’t want to prevent them from accessing the browser’s chrome (after all, sighted users wouldn’t expect to be stuck in the browser’s tab while a modal window is open). The JavaScript above prevents tabbing to the document’s content outside of the modal window, instead bringing the user to the top of the modal.

If we also put the modal at the top of the DOM tree, as the first child ofbody, then hittingShift + Tabwould take the user out of the modal and into the browser’s chrome. If you’re not able to change the modal’s location in the DOM tree, then use the following JavaScript instead:

Listing 8: Javascript code to change the modal’s location

var m = document.getElementById('modal_window'),
    p = document.getElementById('page');

// Remember that <div id="page"> surrounds the whole document,
// so aria-hidden="true" can be applied to it when the modal opens.

function swap () {
  p.parentNode.insertBefore(m, p);


If you can’t move the modal in the DOM tree or reposition it with JavaScript, you still have other options for confining focus to the modal. You could keep track of the first and last focusable elements in the modal window. When the user reaches the last one and hitsTab, you could shift focus back to the top of the modal. (And you would do the opposite forShift + Tab.)

A second option would be to create a list of all focusable nodes in the modal window and, upon the modal firing, allow for tabbing only through those nodes.

A third option would be to find all focusable nodes outside of the modal and settabindex="-1"on them.

The problem with these first and second options is that they render the browser’s chrome inaccessible. If you must take this route, then adding a well-marked “close” button to the modal and supporting theEscapekey are critical; without them, you will effectively trap keyboard users on the website.

The third option allows for tabbing within the modal and the browser’s chrome, but it comes with the performance cost of listing all focusable elements on the page and negating their ability to be focused. The cost might not be much on a small page, but on a page with many links and form elements, it can become quite a chore. Not to mention, when the modal closes, you would need to return all elements to their previous state.

Clearly, we have a lot to consider to enable users to effectively tab within a modal.


Finally, modals should be easy to dismiss. Standardalert()modal dialogs can be closed by hitting theEscapekey, so following suit with our modal would be expected — and a convenience. If your modal has multiple focusable elements, allowing the user to just hitEscapeis much better than forcing them to tab through content to get to the “close” button.

Listing 9: function modalClose

function modalClose ( e ) {
  if ( !e.keyCode || e.keyCode === 27 ) {
    // code to close modal goes here

document.addEventListener('keydown', modalClose);

Moreover, closing a full-screen modal when the overlay is clicked is conventional. The exception is if you don’t want to close the modal until the user has performed an action.

Use the following JavaScript to close the modal when the user clicks on the overlay:

Listing 10: Javascript to close the modal

mOverlay.addEventListener('click', function( e )
  if ( == modal.parentNode)
    modalClose( e );
}, false);

Additional Accessibility Steps

Beyond the usability steps covered above,ARIA roles, states and propertieswill add yet more hooks for assistive technologies. For some of these, nothing more is required than adding the corresponding attribute to your markup; for others, additional JavaScript is required to control an element’s state.


Use the aria-hidden attribute. By toggling the value true and false, the element and any of its children will be either hidden or visible to screen readers. However, as with all ARIA attributes, it carries no default style and, thus, will not be hidden from sighted users. To hide it, add the following CSS:

Listing 11: Hiding aria

.modal-window[aria-hidden=”true”] {
  display: none;

Notice that the selector is pretty specific here. The reason is that we might not want all elements with aria-hidden="true"to be hidden (as with our earlier example of the “X” for the “close” button).


Addrole="dialog"to the element that contains the modal’s content. This tells assistive technologies that the content requires the user’s response or confirmation. Again, couple this with the JavaScript that shifts focus from the last active element in the document to the modal or to the first focusable element in the modal.

However, if the modal is more of an error or alert message that requires the user to input something before proceeding, then use role="alertdialog" instead. Again, set the focus on it automatically with JavaScript, and confine focus to the modal until action is taken.


Use the aria-label or aria-labelledby attribute along with role="dialog". If your modal window has a heading, you can use the aria-labelledby attribute to point to it by referencing the heading’s ID. If your modal doesn’t have a heading for some reason, then you can at least use the aria-label to provide a concise label about the element that screen readers can parse.

What About HTML5’s Dialog Element?

Chrome 37 beta and Firefox Nightly 34.0a1 support the dialog element, which provides extra semantic and accessibility information for modal windows. Once this native dialog element is established, we won’t need to apply role="dialog"to non-dialog elements. For now, even if you’re using a polyfill for the dialog element, also use role="dialog"so that screen readers know how to handle the element.

The exciting thing about this element is not only that it serves the semantic function of a dialog, but that it come with its own methods, which will replace the JavaScript and CSS that we currently need to write.

For instance, to display or dismiss a dialog, we’d write this base of JavaScript:

Listing 12: Javascript code to display or dismiss a dialog

var modal = document.getElementById('myModal'),
  openModal = document.getElementById('btnOpen'),
  closeModal = document.getElementById('btnClose');

// to show our modal
openModal.addEventListener( 'click', function( e ) {;
  // or

// to close our modal
closeModal.addEventListener( 'click', function( e ) {

The show()method launches the dialog, while still allowing users to interact with other elements on the page. The showModal()method launches the dialog and prevents users from interacting with anything but the modal while it’s open.

The dialog element also has the open property, set to true or false, which replaces aria-hidden. And it has its own::backdrop pseudo-element, which enables us to style the modal when it is opened with the showModal()method.

There’s more to learn about the dialog element than what’s mentioned here. It might not be ready for prime time, but once it is, this semantic element will go a long way to helping us develop usable, accessible experiences.

Where To Go From Here?

Whether you use a jQuery plugin or a homegrown solution, step back and evaluate your modal’s overall usability and accessibility. As minor as modals are to the web overall, they are common enough that if we all tried to make them friendlier and more accessible, we’d make the web a better place.

I hope you have understood and liked the article about modal windows. See you next time.

Freelancer Software Developer. Have knowledge in Java, Android, HTML, CSS and Javascript. He has also knowledge in Agile Development

What did you think of this post?
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!

> More info about MrBool Credits
You must be logged to download.

Click here to login