Skip to content

Iframe content focus trap? #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
andykirk opened this issue Feb 25, 2021 · 7 comments
Closed

Iframe content focus trap? #149

andykirk opened this issue Feb 25, 2021 · 7 comments

Comments

@andykirk
Copy link

Hi,

I just started to see if I can implement a11y-dialog as a model for an iframe, but it breaks the focus trap.

When tabbing through the iframe's focusable elements, the tab order doesn't move back to the modal when it reaches the last focusable element, rather it continues to the next natural tab stop in the DOM/browser. This is expected, since there are no event handlers assigned to the focusable elements in the iframe, but the behaviour is undesirable.

Is it possible to add event handlers to focusable elements in an iframe to fix this behavour, or at least offer any advice on how this might be best achieved?

Let me know if you'd like me to set up a demo that illustrates this behaviour.

Many thanks,
Andy

@KittyGiraudel
Copy link
Owner

KittyGiraudel commented Feb 25, 2021

Hello Andy,

Could I ask for a demo please? :)
I'll have a look then.


Edit: I’ve been playing with it a little, and I can reproduce the problem if the <iframe> is either the first or last focusable element.
The “tabbability” of iframes is notoriously inconsistent, as illustrated in this resource: https://allyjs.io/data-tables/focusable.html#iframe-element

A workaround is to have at least one focusable element before the <iframe>, and at least one focusable element after the <iframe>. This way, the focus trap works well. I tried applying tabindex="0" to the <iframe>, but that’s not helping. :(

@andykirk
Copy link
Author

Thanks for getting back to me.,
That helps (and makes sense). I'm not surprised iframes are pain - they've caused me a LOT of headaches over the years.

It's not ideal to have a redundant focusable element after the iframe - maybe I could an another Close button so they sit on top of each other.
Do you think there is any mileage in investigating adding handler to iframe elements? Seems really messy and problematic to me, but probably the only way to fix this without potentially redundant elements.

Did you still want a demo making?

Thanks

@KittyGiraudel
Copy link
Owner

I also thought about having twice the same close button, absolutely positioned at the exact same place in the dialog. This way, tabbing problem is solved, and there is no visual impact. That’s probably the easiest. I’m not sure how to solve it otherwise. :(

@andykirk
Copy link
Author

Ok, thanks.
I added the second Close button. It works ok except you get the slightly odd experience of having to tab through 2 Close buttons in a row.
I guess some JS on the last close button to move the focus to to first might solve that, but I’m happy to tolerate a little odd-ness for now.

Cheers.

@KittyGiraudel
Copy link
Owner

I mentioned it in the docs, and will now close this. Thank you for bringing it to my attention. :)

@KittyGiraudel
Copy link
Owner

KittyGiraudel commented Sep 3, 2021

I experienced this today, so I thought I’d come back to this and clarify something.

Consider a dialog with a close button and an iframe as sole focusable elements.

<div id="your-dialog-id" aria-labelledby="your-dialog-title-id" aria-hidden="true">
  <div data-a11y-dialog-hide></div>
  <div role="document">
    <button type="button" data-a11y-dialog-hide aria-label="Close dialog">
      &times;
    </button>
    <h1 id="your-dialog-title-id">Your dialog title</h1>
    <iframe width="560" height="315" src="https://www.youtube.com/embed/SB-qEYVdvXA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
  </div>
</div>

As per version 7.2.0, opening the dialog focuses the dialog container. Tabbing a first time moves the focus to the close button. When tabbing on the close button, the focus moves to the iframe. Tabbing further will enter the iframe and go through the focusable elements. When tabbing on the last element of the iframe, the expectation would be to land on the close button again.

However, the aforementioned bug happens and the focus moves out of the dialog. That being said, a11y-dialog catches that, and focuses the dialog back immediately. So the focus ends up back on the dialog container itself. It’s not exactly what’s expected, but it’s also not a horrible behaviour, nor is it a broken experience.

So while my recommendation would be to avoid having an iframe as first or last focusable element of a dialog, I wouldn’t recommend hacking around it too much. If it has to be the first/last element, it’s not the end of the world.

Edit: the reason the focus could move underneath the dialog while open back when this issue was created was due to a regression introduced in version 6.0.0 and that was fixed in versions 6.1.1 and version 7.0.2. Since then, any attempt at moving the focus somewhere else than within the dialog container will result in said container to be focused.

@andykirk
Copy link
Author

andykirk commented Sep 3, 2021

Awesome - thanks for the follow-up. That's very helpful. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants