Skip to content

Instantly share code, notes, and snippets.

@alastc
Last active December 27, 2015 14:29
Show Gist options
  • Save alastc/7340946 to your computer and use it in GitHub Desktop.
Save alastc/7340946 to your computer and use it in GitHub Desktop.
A test page for accessible pop-overs, with JS &CSS in the head of the HTML file.
<!DOCTYPE html>
<html lang="en">
<head>
<!--
This is an example page, published by @alastc at:
http://alastairc.ac/gists/7340946/PopOvers-Content.html
On Github at:
https://gist.github.com/alastc/7340946
Creative Commons BY-SA 2.0
http://creativecommons.org/licenses/by-sa/2.0/"
-->
<title>Accessible content pop-over example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
body, html, main {margin: 0; padding: 0; font-family: sans-serif;}
main {
display: block;
outline: 0;
padding: 20px;
max-width: 800px;
}
#popover {
display: none;
}
#popover.triggered {
display: block;
position: fixed;
top: 100px;
width: 50%;
height: 300px;
left: 25%;
background: #eee;
padding: 30px;
border: 2px #666 solid;
z-index: 20;
}
.overlayed {
position:relative;
}
.overlayed:before {
content: "";
background-color: rgba(150, 150, 150, 0.7);
position: absolute;
top: 0; left:0; right:0;bottom:0;
outline: 1px rgba(100, 100, 100, 0.8) solid;
z-index: 10;
}
#close {
position: fixed;
top: 95px;
width: 10%;
left: 75%;
display: block;
background: white;
border: 1px #666 solid;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<!-- load local copies if you've no internet access-->
<script>window.jQuery || document.write(unescape('%3Cscript src="../jquery-1.7.2.min.js"%3E%3C/script%3E'));
</script>
<script type="text/JavaScript">
$(document).ready(function(){
// Setup aria-hidden for the pop-over onload
$("#popover").attr("aria-hidden", "true");
// variable to hold the triggering element.
var triggerElement;
// Main function for opening the pop-over. NB: click works for keyboard as well when on a link/button.
$("#trigger").click(function(e) {
// Get the link that triggered it, so we can focus back on it later. Only applies when using keyboard.
triggerElement = $("a:focus");
// Get window width & height
var popHeight = window.innerHeight * 0.7;
var popWidth = window.innerWidth * 0.7;
var popTop = window.innerHeight * 0.15;
var popLeft = window.innerWidth * 0.15;
$("#popover").css({
"width": popWidth + "px",
"height": popHeight + "px",
"top": popTop + "px",
"left": popLeft + "px",
"outline": "0"
});
$("close").css({
"top": popTop - 5 + "px",
"left": popLeft + 5 + "px"
});
// show overlay
$("#popover").addClass("triggered").attr("aria-hidden", "false");
// Hide background
$(".wrap").addClass("overlayed").attr({
"aria-hidden": "true",
"tabindex": "-1"
});
// set keyboard focus into pop over
$("#tofocus").attr("tabindex", "-1").css("outline", "0");
$("#tofocus").focus();
// setup tab-loop so you cannot tab out of the pop-over.
(function(){
// I assume keeping this bit in a function is a good thing for closure? I.e. keeping variables local.
// Also, I have checked, and if there is only one link (i.e. close), focus is just kept on that link until you press enter or esc.
var firstLink = $("#popover a:first").get(0);
var lastLink = $("#popover a:last").get(0);
$(firstLink).keydown(function(e) {
// if you shift-tab on first link, go to last
if(e.shiftKey && e.keyCode == 9) {
e.preventDefault();
$(lastLink).focus();
}
});
$(lastLink).keydown(function(e) {
// if you press tab without shift, loop to first link.
if (!e.shiftKey && e.keyCode == 9) {
e.preventDefault();
$(firstLink).focus();
}
});
})(); // end tabloop anonymous function
// Prevent the screen shifting around when you open the pop-over.
e.preventDefault();
}); // end triggering click
// The main close functions
$("#close").click(function(e) {
// hide overlay
$("#popover").removeClass("triggered").attr({
"aria-hidden": "true",
"tabindex": ""
});
// show background
$(".wrap").removeClass("overlayed").attr({
"aria-hidden": "false"
});
// prevent screen scroll by preventing default link action.
e.preventDefault();
// Focus back onto the link that opened it.
if (triggerElement) {
$(triggerElement).focus();
}
}); // End close button click.
// Setup esc to trigger close.
$(document).keyup(function(e) {
// Detect if the popover is closed, i.e. aria-hidden == true
var isPopupClose = $("#popover").attr("aria-hidden");
// var code = e.keyCode ? e.keyCode : e.which;
// console.log(code);
// If the popover is open
if (isPopupClose == "false" ) {
// If the keypress is esc
if (e.keyCode == 27) {
// trigger the close button
$('#close').click();
}
}
});
// Setup clicking outside of pop-over to trigger close.
$('html').click(function() {
var isPopupClose = $("#popover").attr("aria-hidden");
if (isPopupClose == "false" ) {
$("#close").click();
}
});
// but not inside the pop-over, or from the triggering element.
$('#popover, #trigger').click(function(event){
event.stopPropagation();
});
}); // end document
</script>
</head>
<body>
<div class="wrap" id="top">
<main role="main" id="main" tabindex="-1">
<h1>Pop-overs - content example</h1>
<p>A pop-over (sometimes called a &quot;<a href="http://en.wikipedia.org/wiki/Lightbox_(JavaScript)">lightbox</a>&quot;) is where some content appears over the page. Generally it (should) prevent access to the page until the pop-over is dismissed, or you follow a link, or submit a form. I think there are three types, names vary but for purpose of this example:</p>
<ul>
<li>A &quot;Dialogue&quot;: Where a form or other interactive controls is presented over the content area.</li>
<li>A &quot;lightbox&quot;: an image or video is presented over the content area.</li>
<li>A &quot;Content pop-over&quot;: Where miscelaneous content is presented over the content area.</li>
</ul>
<p>This example deals with the last of these, the content pop-over.</p>
<p>The usual <a href="http://www.456bereastreet.com/archive/200910/lightboxes_and_keyboard_accessibility/">accessibility issue for pop-overs</a> are for keyboard accessibility, as the user ends up tabbing through the background in order to get to the pop-over.</p>
<h2>Content pop-over example</h2>
<p><a href="#" id="trigger">trigger pop-over</a>.</p>
<h2>Accessibility requirements</h2>
<p>A content pop-over element should work with mouse, keyboard and touch-devices at various screen sizes. The basic requirements are that:</p>
<ul>
<li>Mouse control, you should be able to:
<ul>
<li>Click the link to open the pop-over.</li>
<li>Click a 'close' button to dismiss it.</li>
<li>Click outside of the pop-over to dismiss it.</li>
</ul>
</li>
<li>Keyboard control should:
<ul>
<li>Allow tabbing to the link and pressing enter to open it</li>
<li>Move the keyboard focus to the top of the pop-over when it is opened. For screen reader users they will simply read from the top. For (visual) keyboard users pressing tab once should take you to the first focusable element in the pop-over.</li>
<li>Prevent tabbing outside of the pop-over, wrapping around. I.e. tab from the last focusable element moves to the first, and shift-tabbing from the first moves to the last.</li>
<li>Screen reader users should also not be able to 'browse' out of the pop-over. E.g. in Jaws, pressing down arrow at the end does not move out of the pop-over.</li>
<li>Closing the pop-over should put the link back where it was, on the triggering element.</li>
<li>You should be able to press <kbd>esc</kbd> to close the pop-over.</li>
</ul>
</li>
<li>Visual aspects:
<ul>
<li>The pop-over should not extend out of the viewport, or it needs to scroll with the window.</li>
<li>The pop-over should not disappear if you scroll down.</li>
<li>The background should appear blanked-out and inactive.</li>
</ul>
</li>
</ul>
<h2>It's a trick, get an axe!</h2>
<p><strong>Warning:</strong> You might find references to <a href="http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#the-dialog-element">HTML5</a> or <a href="http://www.w3.org/TR/wai-aria/roles#dialog">WAI-ARIA</a> &quot;<code>dialog</code>&quot;, <strong>do not use these for content-based pop-overs</strong>. They prevent screen reader users from reading the content, they are restricted to form-controls because: <q cite="http://www.w3.org/TR/wai-aria/roles#dialog">A dialog is an application window that is designed to interrupt the current processing of an application in order to prompt the user to enter information or require a response</q>. I.e. a form, not content.</p>
</main>
<footer role="contentinfo">
<p>Created by <a href="http://alastairc.ac/">AlastairC</a> in 2013, &copy; <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a></p>
</footer>
</div><!-- end .wrap -->
<div id="popover">
<h2 id="tofocus">Content of pop-over</h2>
<p>Some text, that needs a couple of links as examples, such as <a href="http:///google.com/">Google</a> or <a href="http://www.example.com/">example.com</a>.</p>
<a href="#" id="close">Close</a>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment