Offscreen Content
Content that is invisible or obscured to a user using a mouse, but still accessible to a keyboard or screen reader user.
The Problem
Users navigating with a keyboard or screen reader will lose their place when offscreen content is focused, potentially also able to interact with page content they shouldn't be.
The Solution
Making the element(s) invisible using CSS display: none
or visibility: hidden
. If the element(s) are supposed to be offscreen or obscured but unusable then aria-hidden
can be used.
Related Articles
Live Examples
Before illustrates the problem, After illustrates the solution. Click the header to see it larger in a modal.
Please note that this Before example contains inaccessible code, use this link to skip to the After Live Examplebefore
after
Code Comparison
Code diff between the before and after examples above to show the changes necessary. To copy the final source click on the 'after' path link before the diff.
source
Comparing /examples/focus/offscreen-content/before/index.html to /examples/focus/offscreen-content/after/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Accessibility Solutions - Focus - Offscreen Content</title>
<link rel="stylesheet" href="../../../presentation.css" />
<link rel="stylesheet" href="offscreen-content.css" />
</head>
<body>
<header>
<nav class="header-nav">
<button class="header-nav__open" type="button">Menu</button>
<ul id="menu">
<li>
<button class="header-nav__close" type="button">Close</button>
</li>
<li><a href="#">Lorem</a></li>
<li><a href="#">Architecto</a></li>
<li><a href="#">Quas</a></li>
<li><a href="#">Nobis</a></li>
<li><a href="#">Eligendi</a></li>
<li><a href="#">Quaerat</a></li>
</ul>
</nav>
</header>
<main id="main" tabindex="-1">
<h1>Sample Page</h1>
<p>Header nav on Desktop, Slideout nav on mobile!</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laboriosam
accusantium debitis voluptates voluptatem soluta pariatur possimus
fugiat natus dignissimos! Atque beatae laudantium ducimus quasi esse
eveniet neque sed nihil similique.
</p>
<p>
Doloremque repellendus perspiciatis iusto enim illum laboriosam deserunt
eius aliquam numquam atque, neque velit. Accusamus dolore dicta sunt
voluptas vitae, animi sint, autem nam ducimus incidunt necessitatibus
dolorem quaerat! Id?
</p>
<p>
Vel explicabo error sed dolorem <a href="#">repellendus</a>, cum veniam
harum architecto dolorum officiis sunt nostrum rem similique laboriosam
quo aliquam, facere pariatur. Maiores voluptatum itaque, quia at placeat
corporis rem possimus!
</p>
<p>
Alias magni quod sit, cupiditate, consequatur minus necessitatibus id
molestiae deleniti ipsam optio molestias quibusdam nihil quis.
Voluptates sit minima perspiciatis recusandae fugit laboriosam ducimus
quidem quo, cupiditate sequi. Ad?
</p>
<p>
Iusto eos <a href="#">exercitationem</a>, nemo dolor saepe sunt vel
quasi corrupti quae consequuntur dolorem nobis facere sit explicabo in
esse repellat deleniti, ex quaerat! Perspiciatis assumenda porro rem
dolore perferendis pariatur.
</p>
</main>
<script src="offscreen-content.js"></script>
</body>
</html>
styles
Comparing /examples/focus/offscreen-content/before/offscreen-content.css to /examples/focus/offscreen-content/after/offscreen-content.css
.header-nav #menu {
background: white;
bottom: 0;
box-shadow: 0 0 12px 1px #00000075;
height: calc(100% - 40px);
left: 0;
list-style: none;
margin: 0;
min-width: 220px;
opacity: 0;
overflow: auto;
padding: 20px;
position: absolute;
transform: translateX(-100%);
transition: all 0.3s ease;
visibility: hidden;
z-index: 100;
}
.header-nav #menu li {
padding: 20px;
}
.header-nav #menu.nav-opened {
opacity: 1;
transform: translateX(0);
visibility: visible;
}
.header-nav__close,
.header-nav__open {
padding: 0 20px;
}
javascript
Comparing /examples/focus/offscreen-content/before/offscreen-content.js to /examples/focus/offscreen-content/after/offscreen-content.js
(function () {
'use strict';
function SlideOutMenu(id) {
this.el = document.querySelector(id);
this.closeButton = document.getElementsByClassName('header-nav__close')[0];
this.openButton = document.getElementsByClassName('header-nav__open')[0];
this.closeButton.addEventListener('click', this.menuToggle.bind(this));
this.openButton.addEventListener('click', this.menuToggle.bind(this));
}
SlideOutMenu.prototype.menuToggle = function (e) {
e.preventDefault();
this.el.classList.toggle('nav-opened');
};
const menu = new SlideOutMenu('#menu');
})();