Search topics
Iframes with a missing or generic title
A studio's contact page embeds a map with no title and a video whose only title, “Video player”, came with the embed code, so a screen reader announces two frames without saying what either holds.
<iframe src="https://maps.example.com/embed?pb=…"> The problem
Screen reader users can't tell what an embedded map, video or widget holds without going into it to find out.
A pottery studio's "Visit us" page has two embeds. Under "Find us" is a map, pasted in from a map provider's share menu. Under "Take the tour" is a two-minute video, pasted from a video host. A screen reader user who wants directions moves through the page's frames, with the frame key or the screen reader's list of frames, and hears "frame" and then "Video player, frame". Depending on the screen reader, the first may instead read the long address the map loads from. Neither says which one is the map, so they enter each to find out, or give up and look for the address elsewhere.
An iframe puts another document inside the page, and assistive technology announces it as a frame with a name. 4.1.2 needs every user interface component to have a name that can be determined in code, and a frame is one. The map's iframe has no title, so it has no name at all. The video's frame has title="Video player", which the host's embed code supplies on every video it serves. That is a name, but it describes the player, not the video, and WCAG technique H64, which names frames with title, checks that the title "describes the iframe's content". A second video on the page would get the same name, and the two could not be told apart.
Sighted visitors see a map and a video and notice nothing wrong. The failure is only in the names the code gives the two frames.
2 of 10 groups affected
- No vision (affected)
- Low vision (affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (not affected)
- Reach, strength (not affected)
- Cognitive (not affected)
- Seizures (not affected)
- Without vision Screen reader users hear “frame” and “Video player” and can't tell the map from the video, or either from an advert, without going into each one. Many skip frames they can't identify, and miss the directions.
- Limited vision People who use a screen reader with magnification often move by frames rather than pan across the page, and the names give them nothing to tell the frames apart.
axe's frame-title and ANDI flag the map, because its frame has no name. Both accept "Video player", because any non-empty title counts, and axe's frame-title-unique only catches two frames sharing one title. Scanners also check the page as it first loads, so a chat or booking widget that inserts its frame after a cookie choice or a click is often never tested. When asked to fix the warning, an AI assistant tends to write title="iframe", title="Embedded content" or the provider's name, which says nothing about the content, or adds aria-hidden="true" to the frame. That silences the scanner and hides the map from screen readers, while its links stay in the Tab order, announced as nothing. Whether a name says what the frame holds is something a person has to judge.
Try it
Find the map, going only by what a screen reader says about each frame.
Under the page is what a screen reader says as it moves from frame to frame. Choose a line to jump to that frame. Can you tell which one is the map before you choose?
Broken Can you fix this?
Visit us
Find us
4 Mill Lane. Open Tuesday to Sunday, 10:00 to 18:00.
Take the tour
Two minutes around the wheels and kilns.
Moving frame by frame, a screen reader says:
A recreated demo. The broken version is intentionally inaccessible.
The fix
Give each frame a short title that says what is inside it.
- 1Every visible frame gets a title, including frames a script inserts.
- 2Say what the frame holds, not that it is a frame, a player or an embed.
- 3Give each frame its own name, in the language of the page.
<h2>Find us</h2><p>4 Mill Lane. Open Tuesday to Sunday, 10:00 to 18:00.</p><iframe src="https://maps.example.com/embed?pb=!1m18!1m12…" width="600" height="320" style="border:0" loading="lazy"></iframe> <h2>Take the tour</h2><iframe src="https://video.example.com/embed/x7Kq2" width="560" height="315" title="Video player" allowfullscreen></iframe><h2>Find us</h2><p>4 Mill Lane. Open Tuesday to Sunday, 10:00 to 18:00.</p><iframe src="https://maps.example.com/embed?pb=!1m18!1m12…" title="Map of Kiln Room, 4 Mill Lane" width="600" height="320" style="border:0" loading="lazy"></iframe> <h2>Take the tour</h2><iframe src="https://video.example.com/embed/x7Kq2" title="Studio tour video" width="560" height="315" allowfullscreen></iframe>Why this fix: Use native HTML first
const booking = document.getElementById('booking');const nameFrames = () => { for (const frame of booking.querySelectorAll('iframe')) { if (frame.title !== 'Booking calendar') frame.title = 'Booking calendar'; }};nameFrames();new MutationObserver(nameFrames).observe(booking, { childList: true, subtree: true });The map's frame has no name, and the video's name is the host's default, so neither tells a screen reader user what the frame holds.
Each frame now has a short name that says what is in it, so the screen reader reads "Map of Kiln Room, 4 Mill Lane, frame" and "Studio tour video, frame", and someone who wants directions knows which one to enter. The video's default title is replaced, not kept beside the new one. title is the HTML attribute for naming a frame, and browsers and screen readers have read it on frames for longer than any ARIA attribute.
A chat, booking, payment or review widget usually inserts its iframe with a script, so there is no markup of yours to add the title to. The iframe element is still part of your page, even though what loads inside it comes from the vendor's domain, so it can still be named. Take the first of these that works.
Use the widget's own setting. Many SDKs accept a title, a label or an accessibility option when they are set up, or copy the title from the container you give them. The option's name varies, so check the vendor's documentation. A setting is the only fix that survives the vendor's updates. A CMS or shop plugin that prints the iframe in its template is the same case: look for a setting, then for a template override or filter hook the platform offers. Either outlasts a plugin update, which editing the plugin's own files does not.
If there is no setting, set the title from your own script: in the SDK's ready or load callback if it has one, or by watching the widget's container. Many widgets replace their frame when they open, close or move to the next step, so keep naming it rather than doing it once.
Watch the widget's own container, not the whole document. The observer reacts to frames being added, not to attributes, so setting the title does not set it off again. If the widget adds more than one frame, pick out the one people use rather than giving them all the same name. This lasts only while the vendor's markup stays as it is, and does nothing if your script fails to load, so treat it as a stopgap: report the missing name to the vendor, and check the page again after each of its updates.
SDKs often add small helper frames as well, for messaging or fraud checks, that show nothing. One hidden with display: none needs nothing. One left in the page at a pixel or two still reaches screen readers, so name it for what it does, such as "Payment security check", and ask the vendor to hide it. A frame inside a closed shadow root can't be reached by any script on your page, and only the vendor can fix it.
When a widget can't be fixed, the failure is still on your page. WCAG allows a statement of partial conformance for third-party content you don't control, but that explains the gap rather than closing it. Name the widget in your accessibility statement, give another way to do the task, such as an email address for bookings, and weigh it when you choose or renew the vendor.
aria-label or aria-labelledby on an iframe also gives it a name, and either overrides title. Neither adds anything here, and a frame with both a title and an aria-label has two names that can drift apart, so set title alone.
Where the frame's markup comes from decides where its title is set.
- Frames in your own templates: set
titlein the markup, and make an embed component require it as a prop rather than default to "Embedded content". - Frames content editors paste: give the embed block a required title field, and check the published page, because some editors strip attributes from pasted code or keep the host's default.
- Frames a third-party widget, plugin or SDK inserts: there is no markup of yours to edit, so use the widget's setting, or set the title from a script, as described above.
Write the name in the page's language. Hosts often supply an English default, which a screen reader set to Japanese reads with the wrong pronunciation. Keep the name short and specific: "Studio tour video", not "Video of a two-minute tour of our pottery studio filmed in spring". The frame's role is announced with it, so the name needs neither "frame" nor "iframe".
A frame that is hidden with display: none, visibility: hidden or the hidden attribute, such as a tracking frame, is not exposed and needs no name. Don't hide a visible frame with aria-hidden to quiet a warning: anything focusable inside it still takes focus, with nothing announced.
When the framed document is your own, give it a <title> as well, matching the frame's name. Some screen readers read that document title on entering the frame, and it is the page's title if someone opens the frame on its own.
Fixing this with an AI coding assistant? Get this guide as Markdown
Verify the fix
3 checks, no mouse.
Test with: Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat whenever an embed is added or a third-party script changes.
Limits
This is a starting pattern, not a guarantee for every application. The addresses, IDs and names in the snippets are placeholders. Screen readers announce frames differently: some read the frame's name on reaching it, some read the framed document's title instead, and some read neither until you enter, so listen for the names rather than the exact phrasing. This guide covers naming frames, not whether what is inside them is accessible, such as a map's keyboard controls or a video's captions. Test the complete journey with your target assistive technology.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
References
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.