Skip to content
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

tabindex vs reading-flow property #10642

Open
tabatkins opened this issue Sep 24, 2024 · 7 comments
Open

tabindex vs reading-flow property #10642

tabatkins opened this issue Sep 24, 2024 · 7 comments

Comments

@tabatkins
Copy link
Contributor

What is the issue with the HTML Standard?

Currently, the reading-flow PR has the behavior that 'reading-flow' makes the element a scope container for tabindex, and within that scope, tabindex ordering is consulted first, with visual-order giving tiebreaking between identical values. (I think that's a correct summary of the current behavior?)

During the CSS/WHATWG joint session at TPAC, we concluded that it would be better to make tabindex more subordinate to 'reading-flow'.

The exact proposed behavior is:

  1. On the "reading flow items", tabindex is ignored for ordering purposes (it still makes the items focusable as normal, etc). 'reading-flow' is explicitly taking over the ordering of these elements.
  2. On the descendants of the "reading flow items", tabindex's ordering behavior is scoped to that reading flow item subtree. (Aka the reading flow items are scope containers for tabindex, like the spec currently defines for the "reading flow container".)

The participants in the discussion believed this has a more predictable and desirable behavior for authors. Ignoring tabindex's ordering effects on the reading order items themselves seems useful; it allows authors to use tabindex to define one particular ordering, in particular a non-visual one (or one for legacy UAs), and then let 'reading-flow' override that in other cases.

Similarly, having each item be a scope for their descendant tabindexes seemed to better match the mental model we were working with, where 'reading-flow' effectively rearranges the reading order items.

@dizhang168
Copy link
Contributor

From the conversation at issue 10533, there are some good feedback about tabindex. Right now, tabindex is already ignored in the accessibility tree. This causes confusion for users when they switch from using focus navigation to the screen reader. Further, positive tabindex values are bad because it causes confusion to the users and causes the order to jump around. Developers historically have also not been reliable about updating the tabindex value when the visual order of elements change, because they are unfamiliar with this attribute and accessibility best practices in general. Since we should aim to have the screen reader and the visual order match as much as possible, ignoring tabindex on reading-flow items does make sense.

What I am unsure about is the second part of the proposal:

On the descendants of the "reading flow items", tabindex's ordering behavior is scoped to that reading flow item subtree. (Aka the reading flow items are scope containers for tabindex, like the spec currently defines for the "reading flow container".)

I would argue that this change would be more confusing to the users, since most people are not familiar with the concept of focus scope owners. They would expect the HTML tabindex attribute to work across the document and would find this restriction weird.

For example, should we visit all elements with tabindex=2 together?
Or visit each reading flow item scope individually (go from A -> A2 -> A1)?

<style>
.box {
  display: grid;
  reading-flow: grid-order;
}

</style>

<div class="box" id="w" tabindex="0">
  <div id="A" tabindex="0" style="order: 3">
    <button tabindex="1">Item A1</button>
    <button tabindex="2">Item A2</button>
  </div>
  <div id="B" tabindex="0" style="order: 1">
    <button tabindex="1">Item B1</button>
    <button tabindex="2">Item B2</button>
  </div>
  <div id="C" tabindex="0" style="order: 2">
    <button tabindex="1">Item C1</button>
    <button tabindex="2">Item C2</button>
  </div>
</div>

I think there are too many possibilities for complexity. Considering the existing limitations with positive tabindex, I would prefer not making reading flow items focus scope owner and instead make their descendants also ignore tabindex.

@dizhang168
Copy link
Contributor

dizhang168 commented Oct 22, 2024

I take back my objection above. I looked for existing web developer feedback and there are no existing issues asking to use tabIndex weirdly like in the example above. Instead, what I see most is people setting the same tabIndex on grid/flex item and its descendants so they can have a behavior similar to reading-flow. We are adding complexity, but it can be easily documented through HTML standard and will overall be more intuitive. The current proposal is good because the CSS reading-flow property was always meant to only affect the reading flow items, not its descendants. I expand more on my research and how to change the spec here.

High level, here is how this proposal changes the specification:

A reading flow scope owner can be one of 3 cases:

  • A reading flow container scope owner
    • A reading flow container (has flex/grid and reading-flow properties)
    • A display: contents element, whose layout box parent is a reading flow container
  • A reading flow item scope owner
    • A reading flow item, whose layout box parent is a reading flow container but itself is not

Elements in reading flow container scope owner follows a reading-flow focus navigation scope. This takes the layout order into account to re-order the reading flow items. If a reading flow item has a positive tabindex, set it to 0.
Elements in reading flow item scope owner follows a tabindexed-ordered focus navigation scope.

For example:
image

Edit: Updated the example with different tabindex values

Here, the focus order is:
Wrapper -> A -> B -> Display: contents -> F -> C -> E -> D -> H -> position: absolute -> G

@mfreed7 mfreed7 added the agenda+ To be discussed at a triage meeting label Oct 22, 2024
@past past removed the agenda+ To be discussed at a triage meeting label Oct 24, 2024
@dizhang168
Copy link
Contributor

Here is a Shadow DOM example, with the same focus navigation order. The wrapper is a shadow host and the display: contents div is a slot. Its content are slotted from the light DOM.
Because a slot has CSS display: contents, it will follow a reading flow container scope navigation.

image

@dizhang168
Copy link
Contributor

During the joint CSSWG+HTML meeting, we discussed this issue again. I would like to summarize the concerns here and share my thoughts.

@fantasai was advocating that setting the reading-flow value should have the same behavior as if it is not set IF the source and visual order are the same. That is currently not true because a container with reading-flow set will create focus navigation scopes (as described in this issue). Having this side effect feels off.

Here is an illustration:
https://software.hixie.ch/utilities/js/live-dom-viewer/saved/13300

Without reading-flow set, the order would be: t1, t2, t3.
With reading-flow set, we must follow the reading flow order, order is t3, t1, t2.

I believe the proposal of having reading flow create focus navigation scopes (which scopes tabindex) is the right approach because:

  1. Focus navigation scopes is already used by existing API such as slot, shadow DOM, iframes, popover.
  2. Reading flow is meant to change the focus navigation and using focus navigation scopes have been historically, how this is done in HTML
  3. Both reading-flow and tabindex are meant to overwrite following the source order. As such, we cannot avoid side effects and must define how they interact together.
  4. This proposal avoids jumping around during the focus navigation. We don’t have a good use case of wanting to jump between reading flow items' content. The goal is to keep it as close to the visual order as possible (or at least as close to the order CSS is telling us to use).
  5. Tabindex is a misfeature and the accessibility tree ignores it. We should avoid building logic that depends on it and avoid encouraging web developers to use it.

Overall it feels off (it did for me too, see comment 2 and 3 above!). But I do think this proposal is clean and will be easier/intuitive to use and maintain.

ccing @tabatkins @annevk @mfreed7 for their input

@dizhang168
Copy link
Contributor

Could we Agenda+ this to be resolved at the next WHATNOT meeting?

@chrishtr chrishtr added the agenda+ To be discussed at a triage meeting label Dec 10, 2024
@chrishtr
Copy link
Contributor

Could we Agenda+ this to be resolved at the next WHATNOT meeting?

Done. Your preferred resolution is no change from the existing PR's behavior, right?

@dizhang168
Copy link
Contributor

Correct, my proposal is to keep the existing spec-ed behavior in this issue's fist comment: #10642 (comment).

@past past removed the agenda+ To be discussed at a triage meeting label Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

6 participants