Adding Dismissibility to Popup Content

When you’re creating content like dropdown menus, then you will need to worry about 1.4.13.1 Content on Hover or Focus. This knowledge base article sets forth some coding strategies to make this easier.

Contents

A Working Example

To avoid showing an example on this page that conflicts with the page’s existing style sheets and scripting, here is a link to a working example. This will load a separate HTML page that includes all of the needed code. This page appears as shown in the following iframe, which includes a button that, when hovered over, displays a dropdown menu of three options.

Unfortunately, when the three options appear, the menu obscures the text in the paragraph that comes after the button. This example was created using almost entirely CSS, as shown in the following code,

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
  background-color: darkblue;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown-content a:hover {background-color: #ddd;}

.dropdown:hover .dropdown-content {display: block;}

.dropdown:hover .dropbtn {background-color: darkblue;}
    
</style>
</head>
<body>

<h2>Dropdown Example</h2>
<p></p>

<div class="dropdown">
  <button class="dropbtn">Hover Over Me</button>
  <div class="dropdown-content" id="content">
    <a href="#">Option 1</a>
    <a href="#">Option 2</a>
    <a href="#">Option 3</a>
  </div>
</div>
<p>Here is some text that comes after the button. It gets obscured by the dropdown.</p>    


</body>
</html>

In this example, the class dropdown-content holds the contents of the dropdown menu and is hidden by default. Then, the :hover selector shows the dropdown menu when the user hovers over it. The problem, however, is that the menu obscures the other text on the page. In this case, 1.4.13.1 Content on Hover or Focus requires that there be a way to dismiss the menu without moving the mouse.

Adding Dismissibility

The best way to make this dismissible, the best strategy is to add an event listener to detect when the user presses the “Escape” key. We can do this by simply adding the following few lines of JavaScript

<script>
    document.addEventListener("keydown", dismiss);
    function dismiss() {
        if(event.key == "Escape"){
            document.getElementById("content").style.display = "none";
        }
    }
</script> 

This code simply sets the display property to none for the dropdown menu. In this example, we took a “brute force” approach and tied it to an id attribute. A more graceful approach would have been to use getElementsByClassName and iterate through the returned array, setting each one to a display value of none. Here is a link to the new working example, which includes these code changes.

Making the Button Clickable

One problem with this last code example is that, in some browsers, the menu won’t appear on hover after it has been dismissed once using the escape key. To get around this problem, we can also add a function to detect when the button is pressed– and then toggling the display property. For instance, in yet another iteration of this example, we could add the argument onclick=showHide() to our button and then define showHide() as shown in our modified script section

<script>
    document.addEventListener("keydown", dismiss);
    function dismiss() {
        if(event.key == "Escape"){
            document.getElementById("content").style.display = "none";
        }
    }
    function showHide() {
        var x = document.getElementById("content");
        if (x.style.display == "none"){
            x.style.display = "block";
        } else {
            x.style.display = "none";
        }
    }
</script> 

Here is a link to this third working example and is demonstrated in the iframe below. Unfortunately, the example below loses the dismissibility offered by the “escape” key (it’s an iFrame limitation– it works fine in the linked example), but it does demonstrate the second means of dismissibility by clicking on the menu item itself.