Request for developer feedback on reading-flow and elements with display: contents

Last year we published the blog post Solving the CSS layout and source order disconnect. This detailed a proposal being discussed in the CSS Working Group, aiming to solve the issue where reordering items in flexbox and grid causes a disconnected tabbing experience. The beginning section of that post outlines the problem that the working group is trying to solve. Things have moved on since then, and this post gives a brief update of where we are now. We also have a specific area where we need your feedback—how do we deal with items that have display-contents?

Updates to the proposal

There is now draft specification text in the CSS Display Level 4 specification. This introduces a new property called reading-flow. This property is added to the containing element for the flex or grid layout (the element with display: grid or display: flex).

The property accepts the following values:

  • normal: Follow the order of elements in the DOM, which is the current behavior.
  • flex-visual: Only takes effect on flex containers. Follows the visual reading order of flex items, taking the writing mode into account.
  • flex-flow: Only takes effect on flex containers. Follows the flex-flow direction.
  • grid-rows: Only takes effect on grid containers. Follows the visual order of grid items by row, taking the writing mode into account.
  • grid-columns: Only takes effect on grid containers. Follows the visual order of grid items by column, taking the writing mode into account.
  • grid-order: Only takes effect on grid containers. Takes the order property into account, but otherwise acts like normal.

For example, if you have three flex items in a container, and set their flex-direction to row-reverse, they line up from the end of the flex container and the tab order moves from right to left.

.flex {
  display: flex;
  flex-direction: row-reverse;
}
Default flow of flex items with row-reverse.

Add flex-flow: visual then reading flow will follow the visual order in English, therefore left to right.

.flex {
  display: flex;
  flex-direction: row-reverse;
  reading-flow: flex-visual;
}
With reading-flow:flex-visual.

In grid layouts use reading-flow to follow the visual rows or columns rather than the source order. In the following example the reading flow follows the rows.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 150px);
  grid-template-areas: "d b b"
                       "c c a";
  reading-flow: grid-rows;
}

.a { grid-area: a; }
.b { grid-area: b; }
.c { grid-area: c; }
.d { grid-area: d; }
With reading-flow: grid-rows.

Try it out

This CSS property is currently experimental, however it's possible to enable it for testing. To try it out, install Chrome Dev or Canary version 128 or higher, and enable the runtime flag CSSReadingFlow. There are some examples to get you started, which all work in Canary with the flag enabled.

The behavior for display: contents cases is still a work in progress and might change based on the feedback you provide after reading the following section of this post.

Elements with display: contents and web components

There's an outstanding issue for the CSS working group to decide how to deal with the situation where one of the children of an element with reading-flow has display: contents, and similarly if the item were a <slot>.

In the following example, the <div> elements have display: contents. Due to this, all of the <button> elements are promoted to participate in the flex layout, and therefore reading-flow takes account of their order.

 .wrapper {
   display: flex;
   reading-flow: flex-visual;
 }
<div class="wrapper">
   <div style="display: contents" id="contents1">
     <button style="order: 3" id="o3">3</button>
     <button style="order: 1" id="o1">1</button>
     <div style="display: contents" id=contents2>
       <button style="order: 4" id="o4">4</button>
       <button style="order: 2" id=o2>2</button>
     </div>
   </div>
 </div>

We'd like to know if you have any real-world examples that cause the situation seen in this example. Do you ever need to reorder items that are inside an element that has display: contents with items that are not siblings, due to being siblings of the item that has display: contents.

In addition, as we work to resolve the issues around display: contents it would be helpful to see any examples where you might want to use the reading-flow property with display: contents. Understanding the real-world use cases you have will help us design a solution that meets your needs.

Add use cases to the CSS working group issue. If you have examples on live sites or can create a demo on CodePen or JSFiddle that would be incredibly useful when we come to discuss this issue as a group. If you have thoughts on what you would expect to happen, that's also useful. However, the most important thing is to see the real use cases.