Open Bug 1069739 Opened 10 years ago Updated 2 months ago

DIVs with overflow receiving focus, causing issues for accessibility user

Categories

(Core :: DOM: Selection, defect)

31 Branch
defect

Tracking

()

UNCONFIRMED

People

(Reporter: kaushik.patel, Unassigned)

References

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36 Steps to reproduce: User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b9) Gecko/20100101 Firefox/4.0b9 Build Identifier: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b9) Gecko/20100101 Firefox/4.0b9 An div element with overflow-y:hidden in its style is focusable Reproducible: Always Steps to Reproduce: <html> <body> <input> <div style="overflow-y:hidden"></div> <input> </body> </html> Actual Results: div is focusable Expected Results: div should not receive focus up on tabbing Actual results: Accessibility user uses keyboard TAB key to navigate across the Web-Page. In the above case, the DIV receives the focus and nothing can be announced by Screen Readers , creating confusing and usability issue for these users. Ours is a Web Based Enterprise application and this issue is critical for us to receive 508 compliance for us Expected results: Div should not receive focus
Priority: -- → P1
Kaushik, This doesn't need to be security sensitive. Please don't change the priority. Leave that to the developers. You filed this under version 32 but the actual useragent values were for a beta version of Firefox 4.
Group: core-security
Priority: P1 → --
Attached file testcase
Attachment #8492001 - Attachment mime type: text/plain → text/html
Marco, I can't reproduce this on Linux. Can you check it out?
I cannot reproduce this on Windows using Firefox 32 or 35 Nightly, with either NVDA or JAWS. Both inputs are focusable just fine and I can type in them. No problem as far as I can see.
Thanks Marco! Kaushik, it is not clear to me what build you were actually testing. If it was really Firefox 4 beta, that is far too out of date. I'm going to mark this as works for me. Please read https://developer.mozilla.org/en/Bug_writing_guidelines and if you can reproduce it with a current build, please reopen and give us detailed instructions on how to reproduce and exactly which build you were using. Thanks!
Status: UNCONFIRMED → RESOLVED
Closed: 10 years ago
Resolution: --- → WORKSFORME
Attached file FFDIV.html
The Div receives the Focus in FF ESR 31.0
I have attached the sample HTML where the DIV receives the focus.
Kaushik, that attachment was only example data and did not in any way contain real information on names and salaries?
Flags: needinfo?(kaushik.patel)
Attached file FFDIV.html
semi reduced FFDIV.html
I can reproduce the focus issue with Nightly 35 on Linux. Marco, which product/component should we put this?
Status: RESOLVED → REOPENED
Ever confirmed: true
OS: Windows 7 → All
Hardware: x86_64 → All
Resolution: WORKSFORME → ---
Version: 32 Branch → 31 Branch
Ya..the data in the table is just an example data
Flags: needinfo?(kaushik.patel)
I still don't see the problem, or I didn't understand it. To me this looks like a contentEditable table that I can navigate with my Windows screen reader. Note that contentEditable for tables is not well defined and in general behaves badly. This is an Editor bug, IMO.
Marco, when I tab in Firefox the focus changes from the urlbar to the search input to the document and then to the table. In Chrome 37 the urlbar is focused and blurred only. I'll move this to Core Editor for triage.
Status: REOPENED → UNCONFIRMED
Component: Untriaged → Editor
Ever confirmed: false
Product: Firefox → Core
Confirming that <div style="overflow:auto"> is focusable in Firefox 37 Mac. Focus can be set by script and keyboard, however not by mouse. A simple test case can be found here: https://jsbin.com/biyapa/1/edit Chrome 42 and IE11 do not show this behavior. Note that https://bugzilla.mozilla.org/show_bug.cgi?id=626919 looks like a duplicate (or this one is, since the other issue is older).
To be clear, despite the example in the first post, this bug occurs whenever a scrollbar is present. This can be with overflow-x or simply overflow: auto. For anyone experiencing this bug, setting a normally unnecessary tabindex="-1" can disable the focusing.
This issue is still not fixed in v.45.2.0. Are there any plan to get this issue fixed in the upcoming versions? - It's not a fare idea to keep adding tabindex='-1' to every element (having overflow:auto) only for firefox browser.
(In reply to satheeshdom from comment #17) > This issue is still not fixed in v.45.2.0. Are there any plan to get this > issue fixed in the upcoming versions? > - It's not a fare idea to keep adding tabindex='-1' to every element (having > overflow:auto) only for firefox browser. I agree with satheeshdom, is this going to be fixed any time soon? Pretty big issue and it's only in Firefox.
+1. The "tabindex=-1" has the rather unpleasant side effect of making nodes click-focusable.
Flags: needinfo?(m_kato)
per comment #15's sample, this doesn't use contenteditable. Is this Core: Selection or DOM: ?
Component: Editor → Selection
Flags: needinfo?(m_kato)
Flags: needinfo?(bugs)
Hello, This is what I've found out: When a div contains an element that is bigger (either taller or wider) than the parent and has the property overflow-x or overflow-y set to any value, then it can receive the focus. See an example below: https://codepen.io/alexcanessa/pen/JNmdgN Testing on: MacBook Pro (Retina, 15-inch, Late 2013) Firefox 53.0.2 OS 10.12.3 (Sierra)
Clearly ni on Jet as he no longer works at Mozilla.
Flags: needinfo?(bugs)
See Also: → 1532965

A more accurate title is "DIVs with [scrollable] overflow receiving focus, causing issues for accessibility user".

Here is a minimal reproduction of the behavior https://jsfiddle.net/sjnpd04v/

This behavior may be beneficial, when the scrollable element contains no focusable children. If the scrollable element would not be able to receive focus, then a keyboard-only user would not be able to focus and scroll the element. This is in fact the case in Chrome, where in the test case above you can not focus the .focusable div.

When the scrollable element does have focusable children, tabbing through the container becomes unnecessary.

As Craig points out, adding tabindex="-1" makes the element click focusable on both Firefox and Chrome.

The issue is that it is considerably more difficult to stop this behavior than it is to enable it, which can be done with tabindex="0" on elements you want to receive focus.

I'm not aware of any way to stop this behavior without JavaScript and even then I don't know how it should be done.

(In reply to M from comment #23)

This behavior may be beneficial, when the scrollable element contains no focusable children. If the scrollable element would not be able to receive focus, then a keyboard-only user would not be able to focus and scroll the element. This is in fact the case in Chrome, where in the test case above you can not focus the .focusable div.

Indeed, and that is precisely why this behaviour was implemented (a long time ago).

When the scrollable element does have focusable children, tabbing through the container becomes unnecessary.

That's true, and in principle, I guess it'd be nice if the scrollable area wasn't focusable in the presence of focusable descendants. In practice, while I'm not super familiar with that area of the code, I imagine trying to actually implement this (accounting for dynamic mutations, CSS hiding, etc.) would be fraught with nasty edge cases and a world of pain.

As Craig points out, adding tabindex="-1" makes the element click focusable on both Firefox and Chrome.

The issue is that it is considerably more difficult to stop this behavior than it is to enable it, which can be done with tabindex="0" on elements you want to receive focus.

I'm not aware of any way to stop this behavior without JavaScript and even then I don't know how it should be done.

Add a mousedown listener which calls event.preventDefault(). I realise this might not be feasible in some cases due to other side effects (e.g. it will stop drag events from firing), but I thought it worth noting as a potential solution.

To be clear, I understand the concern for screen reader users here and it obviously isn't ideal. However, it also wouldn't be ideal if a keyboard only (non-screen reader) user couldn't scroll. I'm not sure we can reasonably sacrifice one for the other.

Hi James, thanks for the comments! That certainly helps clarify things, and I agree that it is useful and Inclusive for a scrollable element with no focusable children to be tabbable in this way.

In my particular use cases (both the one ~4 years ago and the one from yesterday), a role=listbox element is becoming tabbable in a way that a focus trap is created, which is of course its own (arguably worse) a11y issue. But, knowing that the scrollable-tabbable behavior is useful to some folks, we can work around it with the tabindex=-1 approach by adding an onFocus handler that redirects focus to an item in the listbox.

With that option, the most critical issue I'd like if we could improve here: the mysterious and undocumented behavior that results in my coworkers pulling their hair out trying to figure out why an element without a tabindex is suddenly tabbable, and in only one browser! At the very least it would be great if this was documented somewhere on MDN. Scott O'Hara also mentioned in a discussion yesterday that this behavior was intentional, and added that Chrome had actually tried to ship something similar maybe ~1 year ago but ran into some obstacles. So, perhaps this should also be brought up in the context of a W3C discussion to evaluate whether it belongs in a standards proposal.

Another idea I had -- and I don't know how feasible this would be in terms of both the browser engine and the OS native UI primitives -- would be to focus the scrollbar itself, rather than making the scrollable element tabbable. That would allow e.g. a sighted keyboard-only user to scroll the overflowing element in a way that is handled by the engine/OS, rather than handled spookily inside the DOM. I can't say I've ever seen a pattern like this before (maybe in early DOS days?), but an option I wanted to throw out :)

Thanks again for the attention on this.

Another issue with the status quo (for sighted keyboard users) is that these scrollable elements when focused do not have any default browser focus indicator. This violates WCAG 2.1 2.4.7 Focus Visible.

I'm also curious what exactly the heuristic is that FF uses to determine whether to place a scrollable element in the tab order? If it's documented somewhere (maybe on MDN as Craig mentioned above), then it'd be easier developers to target these elements when writing code (i.e. to do things like override the default browser focus indicator for all scrollable elements that FF has decided to put in the tab order).

(In reply to zelliottm from comment #27)

Another issue with the status quo (for sighted keyboard users) is that these scrollable elements when focused do not have any default browser focus indicator. This violates WCAG 2.1 2.4.7 Focus Visible.

How not? When I tab the testcase above I do get a focus ring.

I'm also curious what exactly the heuristic is that FF uses to determine whether to place a scrollable element in the tab order? If it's documented somewhere (maybe on MDN as Craig mentioned above), then it'd be easier developers to target these elements when writing code (i.e. to do things like override the default browser focus indicator for all scrollable elements that FF has decided to put in the tab order).

It's not quite an heuristic. The code is here, and it basically ensures that there's some scroll range, and it's an HTML element. So basically all scrollable boxes that you'd find. The other special-cases there are not particularly interesting, but I can explain them if you want.

How not? When I tab the testcase above I do get a focus ring.

My bad - I didn't notice the dotted, 1px outline. I was looking for the thick, blue focus ring that is rendered on form controls (https://codepen.io/zelliottm/pen/KKabavq) (I'm used to Chrome's keyboard focus indicator). I'm not sure if it meets contrast requirements per https://www.w3.org/WAI/WCAG21/Understanding/focus-visible-enhanced, but it's better than nothing. :)

Thanks for the link to the code. I guess the problem that I'm encountering is that I want to globally apply a stronger focus indicator to these elements, but I'm unable to do so with a CSS selector as I can with other tabbable elements (i.e. form controls, buttons, arbitrary elements with [tabindex], etc).

They do match the :focus-visible pseudo-class, is that not enough?

In my case that overmatches, I'd like to write as specific of a selector as possible. I think my best approach is to try to copy FF's logic with JavaScript to identify these elements.

Severity: normal → S3

I run into a similar issue implementing a table with virtual scroll capabilities.

<html>
  <body>
    <h1>Focus test</h1>
    <div><button id="el1">focusable element 1</button></div>

    <!-- virtual scroll viewport (should never receive focus) -->
    <div id="viewport" style="padding:1rem;overflow:auto;width: 200px;height:50px;">

      <table border=1>
	<tr><td id="el2" tabindex="0">focusable element 2</td></tr>
	<tr><td>cell</td></tr>
	<tr><td>cell</td></tr>
	<tr><td>cell</td></tr>
	<tr><td>cell</td></tr>
	<tr><td>cell</td></tr>
	<tr><td>cell</td></tr>
	<tr><td>cell</td></tr>
      </table>
    </div>

    <div><button id="el3">focusable element 3</button></div>
  </body>

Firefox focuses the viewport, which should not receive the focus at all.

TAB order(firefox): el1, viewport, el2, el3

TAB order(chrome, webkit): el1, el2, el3

The workaround setting tabindex="-1" to the viewport works, but may introduce other problems (make it focusable via mouse).

(In reply to dietmar from comment #32)

Firefox focuses the viewport, which should not receive the focus at all.

See comment 24 and comment 25 as to why this occurs. My understanding is that Chromium is looking at implementing this as well, as the inability to keyboard scroll a scrollable area is an accessibility problem. This got implemented in https://bugs.chromium.org/p/chromium/issues/detail?id=585413, though it got reverted and is now being discussed in https://bugs.chromium.org/p/chromium/issues/detail?id=907284.

First, thanks for those links.

For my use case, it would help if there is a way to disable that behavior without setting tabindex to -1.

Note: I am implementing some custom widgets that controls scrolling by themself (table with virtual scroll, ...).

So... https://searchfox.org/mozilla-central/rev/77a39e7595198fd30b57550749c15761d30314fb/layout/generic/nsIFrame.cpp#10276 is the relevant code. So ways to disable would be making the element not an HTML element or so... Alternatively, is making the element not focusable at all an option?

  • Does setting -moz-user-focus: none; (setting -moz-user-focus: normal back on kids) work? If it doesn't, I'd argue it probably should.
  • Making the scroller visibility: hidden and kids visibility: visible would also work, but that might have the unintended effect of showing the kids unconditionally even if the ancestor is visible (plus hiding the scrollbar) which isn't amazing.

I want to stress that this is a feature of Firefox, not a bug.

Please do not try to override it unless:

  1. You give another (ancestor or descendant) container tabindex="0";
  2. You also give it an accessible name;
  3. You give it an appropriate role;
  4. And you provide some focus styles.

If you create a scrolling area that cannot be scrolled by keyboard alone, then you will have made a WCAG 2.1 SC 2.1.1 Keyboard (A) failure. If you do not assign an accessible name or role then you risk a 4.1.2 Name, Role, Value (A) failure. If you allow Firefox to scroll the content area for you then you are off the hook.

Given WCAG conformance is a requirement in many government and corporate contexts, creating a failure is a bad idea.

If you create your own "custom scrolling", then ensure a keyboard user can use it with only the keyboard. A scrolling table is quite easy to achieve with no script and very little HTML.

References:

(In reply to Emilio Cobos Álvarez (:emilio) from comment #35)

So... https://searchfox.org/mozilla-central/rev/77a39e7595198fd30b57550749c15761d30314fb/layout/generic/nsIFrame.cpp#10276 is the relevant code. So ways to disable would be making the element not an HTML element or so...

Sorry, I don't get that?

Alternatively, is making the element not focusable at all an option?

  • Does setting -moz-user-focus: none; (setting -moz-user-focus: normal back on kids) work? If it doesn't, I'd argue it probably should.

I tried that already, but it seems -moz-user-focus does not have any effect.

(In reply to Adrian Roselli from comment #36)

I want to stress that this is a feature of Firefox, not a bug.

Please do not try to override it unless:

  1. You give another (ancestor or descendant) container tabindex="0";

Sure, I always make sure there is a focusable element inside...

If you create a scrolling area that cannot be scrolled by keyboard alone

Point is that my component is perfectly accessible without this firefox feature, and the firefox feature make accessibility worse in this case.

It would really help if I can simply set "-moz-user-focus: none;". But this does not have any effect. Is that expected to work?

This is a problem for multiple components in React Spectrum, Adobe's component library. We had a similar issue with our table component, which we initially solved by adding tabindex="-1" to the scrollable element. However, now we realized that this has broken the accessibility tree - the role="presentation" on this element is ignored and the extra accessible element breaks the grid hierarchy. Another similar case where this is broken is in our date picker component. In both cases we already have focusable children within the scrollable area, and allow the user to scroll with the keyboard so adding an additional tab stop is unnecessary. See issue here: https://github.com/adobe/react-spectrum/issues/3633. You can also see the problem in our docs if you make the window narrow so the date picker scrolls: https://react-spectrum.adobe.com/react-spectrum/DateRangePicker.html.

I can also confirm that -moz-user-focus does not appear to have an effect, but it would be nice if it did. Perhaps the heuristics could also be improved if there is a focusable element within the scrollable region?

This also causes problems for a use-case we have in our Next.js app. We have this search box that reflects its value to the URL using Next's router.replace. The problem is that when there's a scroll container, it just steals the focus in the middle of typing in the input, which is just bad.

Here's a CodeSandbox: https://codesandbox.io/p/sandbox/tender-pine-9x9f38?file=/app/page.tsx:34,1

FWIW, this doesn't happen if I use history.replaceState instead, but I'd prefer to not bypass the framework's router. I'll file an issue with them as well.

Here's the issue I filed with Next: https://github.com/vercel/next.js/issues/54838

As far as I know, Firefox only focuses scroll containers if the user or the page explicitly set focus to them. I don't know of any reason that any other API would focus the container. I wonder if Next's router.replace is calling focus on the container for some reason? That wouldn't impact other browsers, since the container isn't focusable there, but regardless, it's not the correct thing to do.

IIRC last time I interacted with this bug, scrollable containers were automatic tab stops.

Yes, they are, but that still requires explicit action by the user (tabbing). Comment 40 suggests that this is somehow happening without the user explicitly tabbing, which shouldn't be the case.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: