Closed rachelandrew closed 9 months ago
The other part of the discussion on Monday was the idea that there are multiple ways one could want to auto-order certain layouts. A flexbox might want to go in flex order (source order + 'order'), or in logical order (start from the startmost flex line, and the startmost item in it, then proceed, so 'flex-direction' and 'flex-wrap' also affect things). A grid might want to be read in column-major order or row-major order. Etc.
It sounds like that's something that would be indicated on the container itself.
So I think my proposal is that we should keep the current spec as written, but add a property on the container (reading-order-order
, clearly) that controls how we assign the ordering to reading-order: auto
children. Give it an initial value that only has an effect on randomized layouts, and then we can extend it with specific-layout keywords for those other cases as we come up with them.
And by "we can extend it" I mean we should add at least one keyword per major layout type right now - block, table, flex, grid. This allows authors to get the "just do it right" behavior, but doesn't allow them to just set it on *
, since you do have to at least think enough about the individual elements to give them the correct reading-order-order value. I think that's an ok balance of friction vs usefulness?
@tabatkins so in the case of having (for example) reading-order-order: grid row
this would allow a non-randomized grid to opt into layout ordering, without needing the reading-order
property on the children?
Right, exactly. (And it would do nothing on, say, a flexbox.)
And for a non-ridiculous name suggestion, maybe reading-order-items
, paralleling the "set how normal
behaves on children" behavior of place-items
?
Yeah reading-order-items
works.
This still leaves us with the question as to whether we need reading-order: <integer>
at all. If we were to implement reading-order-items
on the parent and reading-order: auto
for the children, would that help with @fantasai's concerns of people just applying it everywhere?
Could we initially drop reading-order: integer
and then bring it back if we discovered need for it?
As a developer I'm totally ok to first have only the auto options (and I'm ok with “one keyword per major layout type” limitation) and dropping the integer for now.
I think there might be use-cases for the integers, but it can be quite a complicated issue, where things should be thought through quite extensively in order to replicate the mistakes of a tabindex, stacking context etc. So better to first have something that would work for more simple cases, and in the meantime see how the more complex cases could be handled.
I don't really get when anyone would need the reading order to be different on individual children. It seems simpler (and shorter and easier to remember the property name) to just have reading-order
set on the parent to affect the children's reading order, and not try to tie this into the order
property.
The -items
vs. -content
thing on align and justify is a major headache already, and I'd rather not have to remember which one to use for yet another property.
Proposed syntax:
reading-order-items: normal | flex [ visual | flow ] | grid [ rows | columns ]
normal
means to use DOM order. flex
only works on flex containers; it either traverses the rows visually (based on writing modes, so left-to-right or top-to-bottom for English) or per flex-flow. grid
only works on grid containers, it traverses the grid row-major or column-major.
In either of the latter cases, the 'order' property is taken into account, just like any other flex/grid layout property that affects where the element ends up. So an order: -1
element sliding to the front of the flexbox will make it first in flex flow
as well (and possibly in flex visual
, depending).
(Do we want a "DOM order, but let order
take effect as well" value? That lets you stick with the "I made a good DOM order, just follow it" behavior of normal
, but allows small tweaks for layout breakpoints. If so, I propose from-order
.)
Per issue discussion, the reading-order
property itself is no longer necessary; since we're dropping the integer value there's only the auto
value left. We can put it back if we ever need it.
I think this works.
(Do we want a "DOM order, but let order take effect as well" value? That lets you stick with the "I made a good DOM order, just follow it" behavior of normal, but allows small tweaks for layout breakpoints. If so, I propose from-order.)
So that would give the options:
order
and want the visual and reading order to be different (don't use reading-order-items
.)order
and want the visual and reading order to be the same and take order into account (use reading-order-items
and the flex or grid keyword values)reading-order-items: normal from-order
)That seems useful, and worth adding.
Some comments:
grid-auto-flow
, should there be a keyword that simply matches it?reading-flow
is a reasonable name, since it relates to flex-flow
and grid-auto-flow
?order
overriding DOM in the reading order unless the author very explicitly requests it, because the main purpose of order
is to diverge logical and spatial order. So I don't want to do that without the author opting in intentionally.It would be very nice to just add a * { reading-order-items: I-dont-wanna-think-about-this; }
to new projects and it follows grid or flex or whatever and I don't have to worry about it again unless I specifically want to do something else in an unusual situation.
@fantasai I would expect order to change the reading order too because it changes the visual order and I've requested the reading order to follow the visual order. There are uses for manually diverging visual and reading order but that should be a separate dial to turn.
I'm hesitant to have order overriding DOM in the reading order unless the author very explicitly requests it, because the main purpose of order is to diverge logical and spatial order. So I don't want to do that without the author opting in intentionally.
I'm not sure quite what you mean by this.
In the flex/grid cases, DOM order is already completely lost. Other than its incidental effects on how elements get automatically ordered, there's nothing left there. Visual order inherently and necessarily is post-order
.
In the "DOM order, but let order take effect as well" example I was asking about, it would also be an intentional opt-in.
I can also see use cases for wanting a reading order that pulls some items out of the background coordinate-based flow (e.g. in a grid) and makes them first or last in the reading order while leaving them in the middle of the visual flow. Imagine, for example, a grid of small cards with a few pulled out and enlarged 2x2: a visual navigator would perceive those 2x2 cards first, and then the rest of them, so you might want to match the reading order to that. (Or you might not, depends what you're doing.)
This is the reading-order: <integer>
case that we're explicitly discarding for now, right? (Tho the "DOM order, but pay attention to order
" would also allow this if the call-outs were explicitly positioned, as they could then use order
without actually affecting their position, just their paint layering.)
It would be very nice to just add a * { reading-order-items: I-dont-wanna-think-about-this; } to new projects and it follows grid or flex or whatever and I don't have to worry about it again unless I specifically want to do something else in an unusual situation.
We can't do this, unfortunately. There simply isn't a single correct answer for the elements that have this ability. We also somewhat want to encourage this to be something you think about a little bit. We don't need much, but it's good to have some deliberateness.
It doesn't need to be a single correct answer it just needs to be a better default than the status quo. If there were a reading-order-items: auto
meaning normal, flex, or grid depending on display it would be correct almost all of the time and it's easy to override when it's not. Otherwise you need to add this every time you use grid/flex in a way that changes the reading order so you can't tell at a glance whether "oh did they forget this" or "oh they didn't need that". This is a box-sizing: border-box thing. There's not a perfect answer but it's border-box.
While I like giving power to the designer/developer, I think we should strive towards keeping this simple, without excessive options.
I also think we should decouple reading-order-items
from a direct association with order
, even in the property name. I like reading-flow
. It would be inheritable, and affect tabbing order (when tab-index
is not an integer greater than 0) and any other sequential access such as screen reading order. We might even let it affect the initial scroll position of a scroll pane (not sure if that is a sensible thing to do or not).
Having a separate reading-order: <index>
property for tweaking individual children’s reading order separately from order
should really be a completely separate issue, IMO, and not considered in the design or naming of the parent element’s reading flow property.
I also think we shouldn’t have values like flex
that only apply apply when you have flex layout. It would be better to have “layout reading flow” value that can be set at the top of a tree and inherit down into whatever layout types exist within its decendants, including tables, grid, flex, and maybe floats. I don’t think negative margins, transforms, or abs-pos/fixed positioning should have any effect on how it works (it doesn’t seem necessary, and probably overly complicated for all parties, and would probably lead to behavior that is surprising for authors and users).
So my proposed syntax is:
reading-flow: normal | layout | cross-layout
Value meanings:
normal
: DOM order, as it is today.layout
: After layout, including the effects of order
, grid-auto-flow
, the grid-area
properties, the flex-flow
properties, and float
. Reading and tabbing happens in the direction of flex-flow
for flex-layout, and in the direction of grid-auto-flow
for grid. That determines whether you start with columns vs. rows in grid and table (if grid-template-rows
is masonry
, then reading starts with columns, and vice versa). The reading/tabbing order within each row or column would be from start to end (inline first, then block), AFTER order
and the grid-area
properties (and any dense packing) have determined the layout arrangement. The -reverse
suffix for flex-direction
and flex-wrap
would have no affect on the direction of reading/tabbing (because that would be weird).
This also means that the cells of tables would would be in accessed in writing-mode order, e.g. starting in the lower right corner for vertical-rl
writing mode. If the author didn’t want that, they could control it with something like this: html, td {reading-flow: layout } table { reading-flow: normal }
For floats, items floated to the inline-start side are read/tabbed to before other items or text in the line, and items floated to the inline-end side are read/tabbed to after other items or text in the line. (P.S. I don’t actually know how float: left|right
works in vertical layouts.)
Even if a table-cell or grid item or flex item or float is not focusable, if this property causes them to move up or down in the reading order, then anything focusable in the contents of those items would also move up or down in the tab order. Tabbing is still from outwards to inwards if both an ancestor and decendant can both be focused.
cross-layout
: same as layout
, but in the cross direction for non-masonry grid and tables. For all other layout modes, this value is indistinguishable from layout
.As mentioned above, I can’t really imagine a likely case in which you would want to read or tab in a direction that is opposite of the reading mode/direction. So in English, if you are reading by column (because of e.g. reading-flow: layout; grid-auto-flow: column
for grid, or reading-flow: cross-layout
for table), it would be top to bottom, and if you are reading by row it would be left to right.
I had a look through the initial examples of this that developers had raised (under examples from the community n the initial issue). The things people are wanting to do seem solved by the proposed solution.
Tweaks, for example to form layout, when source is not modifiable. This isn't an ideal use, and advice would be to reorder the HTML where possible, but people are going to do this sort of thing. However this could be solved by changing the layout in grid then asking the reading order to follow that order.
Different layouts for different screen sizes. This is the use case that comes up most often, and is solved by the current suggestion, assuming the grid layout is adjusted in the media/container query and the reading-order-items
property applied at the same time.
Deliberate reordering, where you want the source and display order to be different and this tweet still works as now, as you just don't use reading-order-items
in that circumstance.
I can't think of, nor have I encountered from the community, an instance where we need <reading-order: <integer>
. It feels as if this simpler approach solves the use cases I'm trying to solve for. It also doesn't block us moving forward with the <integer>
case in future if such a need arises.
Also, to respond to @bradkemper we are only considering doing this in flex and grid contexts. I don't think there's a compelling need to do this outside of those contexts. Yes you can disconnect the source and reading order by abspos etc. but I've not seen people having the issues there that they have with grid and flex layouts. This only came up as a developer request once we had layout methods that allowed easy reordering.
I think we would be totally fine without the numeric order.
Yes you can disconnect the source and reading order by abspos etc. but I've not seen people having the issues there that they have with grid and flex layouts.
I expect this could potentially be more of an issue with anchor positioning and with Popover API used for it, where the anchor and its popover (or an anchor and a sidenote as in the other use case for anchor positioning) could be separated. I did create a separate issue to tackle this: https://github.com/w3c/csswg-drafts/issues/9356 — not sure if the reading-order-items
itself could be applied to the abspos, as with it we usually want to move a certain element in the reading and tab order to a certain place, rather than reorder a set of items. But I think it is still worth to keep the abspos case with anchor positioning (where we could utilize the default anchor to determine the reading order adjustment) in mind.
The CSS Working Group just discussed [css-display-4] Do we need `reading-order: <integer>` or should `reading-order: auto` be allowable in all grid or flex layouts?
, and agreed to the following:
RESOLVED: add reading-order-items into the ED and remove reading-order:<integer>
Draft is now in the ED, and other comments have been captured as new issues.
This issue relates to the edits to CSS Display 4 based on this dicussion, and the as-yet unmerged PR at https://github.com/w3c/csswg-drafts/pull/8257.
TL:DR is that we are wondering if we only need
reading-order:auto
(on the children) and if there are reasons to doreading-order: <integer>
at all, or initially. Do compelling enough use cases exist to have that level of control or do people really just want to follow the layout?Longer notes below:
My original suggestion was a switch on the grid/flex container. In that scenario all of the following would follow the grid or flex modified order:
In the existing edits plus this PR, the reading-order: auto value is applied to the children, and only covers:
"randomized grid layouts" with dense packing (and I'm assuming masonry)
To do the following you would need
reading-order: <integer>
on the children:There are definitely use cases for people wanting to follow the layout created by placement (usually because they want different layouts at different responsive breakpoints), so if we only do auto as specced, we don't have a method to achieve those use cases, and if we go for the switch on the container that likely stops us doing this version later.
An alternative, however, would be if the only value for
reading-order
wasauto
(applied to the children) and auto applied in all layout types, not just the randomized ones. As that shouldn't roadblock us from adding the integer value in the future.Reading order and layout order being separated, is a use case. For example, this, but I think in that case, if we went with auto applied everywhere that doesn't need to affect layout-order with no reading-order.
I feel that having the property on the children is better than my idea of a switch on the parent (though I guess we could then add a switch on the parent that sets them all as a group, as with align-items), because it allows for more flexibility, but I think we could get away with that initially being auto only.