Skip to content

'reading-flow' and "display: contents" #10643

Closed
@tabatkins

Description

@tabatkins

What is the issue with the HTML Standard?

Currently, the reading-flow PR specifies that if a reading flow item is display:contents, then two things happen:

  1. The item itself is treated as "not participating", so it gets put at the end of the reading order, arranged in DOM order with other non-participating things.
  2. The item is treated as a reading flow container itself, so its children follow it to the end of the order, and are arranged in the visual order specified by the parent reading flow container.

There was significant discussion on this behavior in the joint CSS/WHATWG meeting at TPAC about making this work better in several cases. Notably, it was considered bad if adding a "useless" 'reading-flow' value (applied to an element where DOM order and visual order are already consistent) could cause the reading order to now mismatch the visual order, because some of the items are in a display:contents subtree. For example, this markup:

<div class=flex>
  <button class=item>A</button>
  <div class="item container">
    <button class=item>B1</button>
    <button class=item>B2</button>
  </div>
  <button class=item>C</button>
</div>
<style>
.flex { display: flex; }
.container { display: contents; }
</style>

Currently, has consistent DOM, visual, and tabbing order: A, B1, B2, C. But if we added .flex { reading-order: flex-flow; }, the tabbing order would change to A, C, B1, B2, despite the DOM order already matching the "flex-flow" order!

Conclusions reached during the meeting:

  • The display:contents should not move to the end of the order as a "non-participating" item. Its children should go into the tabbing order according to their visual position as normal, according to whatever reading-flow says.
    1. If the display:contents element itself is focusable, it should go in the tab order immediately before the first of its children that are reading order items (according to the reading-flow order). (So if you're tabbing backwards, it will be tabbed to after its first-per-reading-flow child.)
      • [not decided during the discussion] If it doesn't have any children that are valid reading order items, then it either:
        1. goes at the end as a non-participating item
        2. or just placed following its nearest preceding-in-DOM-order sibling that is a valid reading order item
    2. [This is contested and needs further discussion.] The display:contents item shouldn't be a reading order scope container. If layout causes other elements to interleave between the display:contents item's children, tabbing order should follow the reading-flow order strictly.
      • The argument for making it a group is that the a11y tree cannot reorder across siblings. That is, in the example markup from above, B1 and B2 will always be together in the a11y tree, and nested under their parent element if it is meaningful in the a11y tree as well.
      • The argument for it being possible to change is that tabindex is already possible to jump back and forth across these scopes, without actually reordering the a11y tree.
      • Later in the day, during the CSS/A11Y joint meeting, we discussed this again. Some opinion leans toward "follow proper visual order" (aka allow skipping back and forth in the A11Y tree), but we were asked to explicitly tag the APA for more guidance.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions