auditmysitev2.0.2

Cross-origin iframe: review manually

frames/cross-origin

WCAG success criterion
4.1.2 (level A)
Outcome class
Manual. A tool cannot decide this check. The audit only points a person at it; it is never counted as automatically verified.
Area
Accessibility, Technical Robustness
Default severity
medium
axe-core rule
frame-tested

Why we flag this

Embedded content (maps, videos, consent widgets) may be inaccessible to screen reader users.

Iframe content is unreachable via CDP — automatic rule checking is not possible.

What the rule checks

Scope. Every perceivable <iframe>/<frame> (not hidden, aria-hidden, role none/presentation, display:none, visibility:hidden, or 1px or smaller) in the top document, its open shadow roots included.

Expectation. One UNTESTED note per perceivable frame whose document is cross-origin to the page (Rendering::frame_reachable: the frame's contentDocument cannot be read, measured by accessibility::probes), located at the frame. Same-origin and srcdoc frames, and frames that are not perceivable (hidden, aria-hidden, display:none, at most 1px in either dimension), get no note. A frame inserted by script or inside a shadow root is part of the page and is judged the same way. Never a pass or a violation. A page whose scripts break the probe records the rule as not run (CapabilityMissing).

Why a person has to decide. The rule only flags embedded content from another origin for a human: whether that content meets WCAG is outside the page's own markup and is never concluded automatically.

Source. WCAG 2.2 SC 4.1.2 (and every SC for embedded content); axe-core frame-tested; HTML §7.1 origin

Detection: shared; needs dom, geometry, frames.

Failing example

The check flags this for review. Corpus case content_frames_cross_origin, element iframe#booking. The page may contain further findings for other rules.

content_frames_cross_origin.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Room booking</title>
    <style>
        nav a, .skip-link { display: inline-block; min-width: 44px; min-height: 44px; }
    </style>
</head>
<body>
    <a class="skip-link" href="#main">Skip to main content</a>
    <header>
        <p>City Library</p>
        <nav aria-label="Main"><a href="/" aria-current="page">Home</a> <a href="/catalogue">Catalogue</a> <a href="/visit">Visit</a></nav>
    </header>
    <main id="main">
        <h1>Book a study room</h1>
        <iframe id="booking" title="Room booking" src="{{CROSS_ORIGIN}}/booking" width="400" height="200"></iframe>
        <p>Our location, as a small marker:</p>
        <iframe id="small-map" title="Location map" src="{{CROSS_ORIGIN}}/map" width="2" height="2" style="border: 0"></iframe>
        <p>Visits are counted anonymously.</p>
        <iframe id="pixel" title="Visitor counter" src="{{CROSS_ORIGIN}}/pixel" width="1" height="1" style="border: 0"></iframe>
        <iframe id="collapsed" title="Chat" src="{{CROSS_ORIGIN}}/chat" style="display: none"></iframe>
        <iframe id="silent" title="Analytics" src="{{CROSS_ORIGIN}}/analytics" width="300" height="100" aria-hidden="true" tabindex="-1"></iframe>
        <iframe id="local-help" title="Booking help" width="400" height="120" srcdoc="<!DOCTYPE html><html lang=&quot;en&quot;><head><title>Help</title></head><body><p>Rooms can be booked for up to two hours.</p></body></html>"></iframe>
        <booking-widget></booking-widget>
        <div id="late-frame"></div>
        <script>
            var crossOrigin = '{{CROSS_ORIGIN}}';
            customElements.define('booking-widget', class extends HTMLElement {
                connectedCallback() {
                    this.attachShadow({ mode: 'open' }).innerHTML =
                        '<iframe id="shadow-calendar" title="Room calendar" src="' + crossOrigin + '/calendar" width="300" height="150"></iframe>';
                }
            });
            document.getElementById('late-frame').innerHTML =
                '<iframe id="late-reviews" title="Reviews" src="' + crossOrigin + '/reviews" width="300" height="150"></iframe>';
        </script>
    </main>
    <footer><p>City Library, 1 Market Square</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.