<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Animated ARIA hamburger menu</title>
<link rel='stylesheet prefetch' href='css/kxqoaa.css'>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Animated <abbr title="Accessible Rich Internet Applications">ARIA</abbr> hamburger menu to meet <abbr title="Web Content Accessibility Guidelines">WCAG</abbr> 2 level AA</h1>
<p>I needed a non-linear show-hide peekaboo to meet WCAG 2 level AA.<br> This one ticks the boxes, and a reusable asset to boot.</p>
<p>JavaScript is used to toggle ARIA states and control tab position while CSS attribute selectors control animation.<p>
<p>
<a id="hamburger" href="#navigation" class="menu">
<svg class="menu_svg" viewbox="0 0 48 48">
<title>Menu</title>
<rect x="15.5" y="16.5" width="20" height="3"/>
<rect x="15.5" y="23.5" width="20" height="3"/>
<rect x="15.5" y="30.5" width="20" height="3"/>
</svg>
</a>
</p>
<p>A <a href="#">Fake Site Search</a> between the Menu link and the navigation block.<br>Arrgh, the things you have to deal with…</p>
<nav id="navigation" class="navigation">
<h2 class=navigation_title>Main navigation:</h2>
<ul class=navigation_list>
<li><a href="#">Tesco.com</a></li>
<li><a href="#">Groceries</a></li>
<li><a href="#">Tesco direct</a></li>
<li><a href="#">F&F clothing</a></li>
<li><a href="#">Clubcard</a></li>
<li><a href="#">Tesco Bank</a></li>
<li><a href="#">Wine by the case</a></li>
<li><a href="#">Tesco Mobile</a></li>
</ul>
</nav>
<p><a href="#">Fake link after navigation block</a> to test keyboard <kbd>Tab</kbd> order.</p>
<p>Strongly influenced by the work of Heydon Pickering</p>
<script src="js/index.js"></script>
</body>
</html>
/*Downloaded from https://www.codeseek.co/2kool2/animated-aria-hamburger-menu-kXVKKb */
/* Simple animated Peekaboo show-hide */
/* Generic styling (not required) */
.menu {
display:block;
width: 40px;
height: 40px;
border: 0 solid;
background-color:#ddd;
}
.menu_svg {
pointer-events: none;
}
.menu[aria-expanded="true"] {
background-color: #1A1A1A;
fill: #fff;
}
/* The heavy lifting is done by 3 statements */
.navigation {
position: relative;
margin: 0;
padding: 0;
transform: translate3d(0,0,0);
backface-visibility: hidden;
/* opacity has to finish before height to allow JS time to find first link */
transition: visibility 0s ease-out, opacity .3s linear, max-height .5s ease-out;
opacity: 0;
visibility: hidden;
max-height: 0;
overflow: hidden;
}
.navigation[aria-hidden="true"] {
transition-delay: .6s, 0s, 0s;
}
.navigation[aria-hidden="false"] {
transition-delay: 0s, 0s, 0s;
opacity: 1;
visibility: visible;
max-height: 12em;
}
/* More generic styling */
.navigation_title {
margin: 0;
padding: 0;
position: absolute;
left: -200em;
}
.navigation_list {
margin: 0;
padding: 0 2em;
}
.navigation_list li {
width: 50%;
float: left;
}
/*Downloaded from https://www.codeseek.co/2kool2/animated-aria-hamburger-menu-kXVKKb */
function peekaboo(w, d, linkBtnId) {
// Peekaboo - show-hide toggle
// Toggle a section using ARIA
"use strict";
var openLabel = "Open and skip to navigation bypassing site search";
var closeLabel = "Close and hide navigation";
var _getRegionObj = function (linkObj) {
return d.getElementById(linkObj.hash.replace("#", "")) || !1;
};
var _setAriaStates = function (linkObj, regionObj, isExpanded) {
w.requestAnimationFrame(function () {
linkObj.setAttribute("aria-expanded", isExpanded);
regionObj.setAttribute("aria-hidden", !isExpanded);
linkObj.setAttribute("aria-label", isExpanded ? closeLabel : openLabel);
});
};
var _toggleAriaStates = function (e) {
e.preventDefault();
var linkObj = e.target;
var expanded = linkObj.getAttribute("aria-expanded") || !1;
if (expanded) { // string "false" is boolean true here
var regionObj = _getRegionObj(linkObj);
if (regionObj) {
// convert to boolean
expanded = expanded === "true";
_setAriaStates(linkObj, regionObj, !expanded);
if (expanded) {
linkObj.focus();
} else {
// Small delay required for focusable object to reappear in DOM
// (transitionend event would have CSS dependencies)
setTimeout(function() {
(regionObj.querySelector("a") || regionObj).focus();
}, 100);
}
}
}
};
var _addAriaAttributes = function (linkObj) {
var regionObj = _getRegionObj(linkObj);
if (regionObj) {
linkObj.setAttribute("aria-controls", regionObj.id);
regionObj.setAttribute("aria-controlledby", linkObj.id);
_setAriaStates(linkObj, regionObj, false);
}
return regionObj;
};
var initialise = function () {
var anchor = d.getElementById(linkBtnId);
if (anchor && _addAriaAttributes(anchor)) {
anchor.addEventListener("click", _toggleAriaStates, !1);
}
};
return initialise();
}
peekaboo(window, document, "hamburger");