Restricted screen orientation
orientation/root-rotated
- WCAG success criterion
- 1.3.4 (level AA)
- Outcome class
- Automatic. An automated check that can report a confirmed violation.
- Area
- Accessibility, Structure & Semantics
- Default severity
- high
- axe-core rule
css-orientation-lock
Why we flag this
Users with fixed-mount screens (e.g. wheelchair-mounted) cannot read the page.
The computed transform (matrix) or rotate of html or body turns by a quarter turn, measured in the audited viewport.
What the rule checks
Scope. The root elements html and body of the top document, in each audited viewport: every page has them, so there is no page the check does not apply to.
Expectation. Fails when html or body is rotated in the audited viewport (computed transform with a rotation component, or the rotate property; Rendering::box_transform, measured by accessibility::probes), which turns the whole page sideways: in the mobile (portrait) pass this is the classic lock that forces landscape, whether set by an orientation media query or by a script reacting to the orientation. The finding names the rotated element. A full turn (360deg), a translation or no transform is no rotation. Rotations by a multiple of 180deg do not swap the axes and are not reported. A page whose computed style cannot be read records the rule as not run (CapabilityMissing), not as a pass.
Source. WCAG 2.2 SC 1.3.4 Orientation
Detection: shared; needs computed_style.
Failing example
The check reports a violation here. Corpus case visual_orientation_lock, element body. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page rotated into landscape on portrait screens</title>
<style>
body { color: #111111; background: #ffffff; }
/* Classic orientation lock: in portrait (the mobile pass) the whole page
is turned sideways so it can only be read in landscape. */
@media (orientation: portrait) {
body { transform: rotate(90deg); transform-origin: top left; }
}
</style>
</head>
<body>
<header>
<a href="#main" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Skip to main content</a>
<p>Seat map</p>
<nav aria-label="Main"><a href="#main" aria-current="page" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Overview</a></nav>
</header>
<main id="main">
<h1>Choose your seat</h1>
<p>Rows A to F, seats 1 to 30.</p>
</main>
<footer><p>Footer text</p></footer>
</body>
</html>Passing example
The check passes here and reports nothing. Corpus case visual_orientation_hide. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Timetable hidden in portrait behind a rotate hint</title>
<style>
body { color: #111111; background: #ffffff; }
.rotate-hint { display: none; }
@media (orientation: portrait) {
.timetable { display: none; }
.rotate-hint { display: block; }
}
</style>
</head>
<body>
<header>
<a href="#main" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Skip to main content</a>
<p>Regional trains</p>
<nav aria-label="Main"><a href="#main" aria-current="page" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Overview</a></nav>
</header>
<main id="main">
<h1>Timetable</h1>
<p class="rotate-hint">Please turn your device to see the timetable.</p>
<div class="timetable">
<table>
<caption>Departures from Central Station</caption>
<tr><th scope="col">Train</th><th scope="col">Time</th></tr>
<tr><td>RE 1</td><td>08:15</td></tr>
</table>
</div>
</main>
<footer><p>Footer text</p></footer>
</body>
</html>This page is generated from the rule catalogue and the rule contracts; see therule overview for how the outcome classes are derived.