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 Example

before

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');
})();