Open rachelandrew opened 2 years ago
I’d really like that feature 😍
Regarding the naming: the term “visual” might be confusing as it does not represent the actual visual order (after transforms applied and so on).
Maybe naming it something like focus-order: layout;
and the current one focus-order: markup;
can help to resolve this.
Related twitter thread: https://twitter.com/ausi/status/1538772128581013504
This would be a great feature. Seconded with @ausi - the "visual" keyword has a separate meaning from "source order" or "flow / layout". Looking at the example code: https://codepen.io/rachelandrew/full/xxRJBGz the visual order may change purely by the visual design of the content without any source order or layout changes. For example if one box was fluorescent yellow with large black text, and another was the same but with smaller text, and every other box was monochrome greyscale - that establishes a visual order that's independent of layout and source order. That's what design is about doing, so naming the current mode "visual" is not accurate and potentially confusing. I don't see how a focus-order: visual
would be possible in an automated way as the browser would have to understand how humans see things and rank attention in visual processing.
focus-order: layout;
or focus-order: flow;
would both work for a system that re-indexes focus based on the two dimensional order of content - though you still need to decide whether the order follows left-to-right as the primary axis or top-to-bottom as the primary axis, which may involve another keyword. I don't think it's safe to assume that flow will follow the document writing direction for this.
2d display throws some spanners in the works. These suggestion's aren't likely to be right, but I think you'd need some mechanism to achieve a similar thing:
focus-order: source
- the default we have now.
focus-order: flow
- in order of the language's document flow (e.g., left to right then top to bottom - row based)
focus-order: cross-axis
- the cross axis of the document flow (e.g., top to bottom then left to right - column based)
Just to clarify, is the suggestion here to have focus/tab order differ from the accessibility tree/screen reader virtual cursor order? I'm probably missing something, just from the proposal text I assumed focus-order
would influence both the accessibility tree order and the focus order, but the earlier sections are making me second-guess 😅.
First off, this is really needed and could be super helpful. Especially for complex responsive visual order changes.
Just wanted to also voice (purely due to work of late) that this is also a really big deal from a component lib POV. If library A is set for one flow type and library B is set for another, both would ideally need a lib wide flow setting and top level options/inheritance for the downstream component users to set across all their component libs. Well that or discourage lib authors from declaring any flow state at all. 🤔
Good stuff, many thanks, and awesome work!
I am so sorry to have spammed this with so very many words. I also have ignored all other comments because this is long enough.
I appreciate that the opening lays out the current situation, but there are a couple assumptions within worth reconsidering:
[…] With care from the author in creating a good document, this in general works well for screen reader users. […]
Some examples might be handy here. Moving an image visually before a heading in a card layout is good example (so the image retains its position, and meaning, following the heading in the DOM).
[…] For example, by being able to show something visually near the top of the page but, because it would be repetitive for a screen reader user, physically locate it in elsewhere in the document. […]
This may be true in some contexts for blind screen reader users. But since ¼ to ⅓ of screen readers are not blind this tends to be a problem. I am wary of the broad strokes here because I see devs making assumptions about "repetitiveness" and visual placement often.
Problem
Visual/tab order disconnect for keyboard users
[…] Authors also want to be able to reorder content at different breakpoints, to provide the best presentation of the layout for different amounts of screen real estate. In this case again, it is likely that by starting with a sensible document source, a screen reader user will not be affected.
A blind screen reader user may not be affected. A blind screen reader user who contacts support, or has a sighted person guide them in any way, may discover that directions like "the box after the heading" are meaningless when the DOM order does not match the visual layout. A low-vision screen reader user may also struggle when zooming causes breakpoints to visually reflow the visual order distinctly from the DOM order. The example, however, is a fantastic visual demo.
Impact on screen reader users if the author assumes the visual order is the logical order
[…] the screen reader user is going to hear things in a different order than the author intended. […]
No tweaking here; I am using this opportunity to let readers know that some screen reader users do not hear the output, but instead experience it on a Braille display. It should not affect this conversation much, but it is worthyknowing.
- Twitter thread (the demo uses order to re-order things by interest, it was pointed out this may have accessibility issues)
The "zero client-side JS" example is a bit of a red herring. Truly accessible interfaces would leverage script to re-order the content as appropriate. Most CSS-only UI efforts have questionable accessibility since things like state, properties, values all have to be managed and live outside the scope of CSS.
This is another case where a CSS-only solution is only performing a visual change. This is the job for a DOM re-order via script. Not only that, developers (should) have known for years that CSS flex/grid-only solutions break semantics (not linking much-maligned original tweet), even though browsers fixed those gaps. That 2019 post should not have survived testing in real use.
Proposal
Provide a method in CSS for authors to opt into following the visual order when in a flex or grid context.
Essentially mimic how Firefox used to behave (2015), before it was changed (January 2016 / Firefox 44). At least, that is how I am reading this. These old bugs may be useful to peruse to understand why the change (or not?):
For example: […]
focus-order: visual;
[…]
This is where I have my issue — the concern is about reading order, which begets focus order based on position in the DOM. The property name is disconnected from the intent or, if the intent is only to apply to focusable elements, will create greater problems as those will break from surrounding context.
order
property?There is a genuine risk of a reading order, focus order, and DOM order disconnect. Incidentally, those are two separate WCAG Success Criteria to consider:
An opt in would enable use cases such as this thread.
I maintain that thread is a red herring. The wrong tool is being used for the job. Script should have been employed to re-order the DOM.
It would also mean visual design tools that allow people to create layout by drag and drop could add the opt-in as soon as the user started to create a layout that had the potential of reordering.
I don't understand. A design tool like Figma or like WordPress's block editor? The former should not render production code and so this proposal would be moot in that context. The latter suggests a visual designer is already working with a developer to enable some form of reflow. This may also be my lack of imagination.
We could also consider making the default ordering visual in cases such as grid masonry layout, or auto-flow: dense where reordering is almost inevitable.
If this means what I think it means, I refer readers to the Firefox issues I linked.
Alternate approaches and related work
An HTML attribute
For all the reasons cited, and years of tabindex
misuse, I agree this is not a good approach.
CSS Spatial Navigation
The Spatial Navigation spec proposes a method of navigating a 2d space.
Spatial navigation is meant only for interactive controls. Which, again, causes me concern since disconnecting focus order and reading order brings a bunch of unnecessary risk. Which is also why I am confused about this proposal overall since it seems to alternately equate the two and ignore one or the other.
Anyway, if readers want to try spatial navigation, I have instructions how you can do it today as part of a larger post about keyboard navigation in scrolling content areas (which maybe should be a concern within this proposal as well).
Open UI: focusgroup
The focusgroup primitive aims to facilitate focus navigation using arrow keys.
My comments about spatial navigation generally apply here, minus being able to play around with it.
I think this feature is desirable from an accessibility point of view.
in most cases this will serve screen reader users well. It can actually work against those using the keyboard to navigate
I also tend to separate keyboard/switch (visual) use from screenreader use to explain things, but as Adrian notes it is more of a continuum. Some people with cognitive issues using screenreaders, and some low-vision people partially using a screenreader. Therefore the focus-order should follow the content order in general.
I think this needs to be the wholistic reading / content order, e.g. reading-order
, or content-order: visual;
? Otherwise it might be thought to only affect interactive controls.
Also, if the other value was "logical", I think that might get confusing as many orders can be "logical" depending on your perspective. Wouldn't it be better as DOM
or source-code
?
Assuming this would apply within media queries, it would also solve the responsive order conflict I noted previously. That is also a good argument for having it in the CSS rather than HTML, the desired order might vary based on things in the CSS.
Yes please this would be a nice feature! 😍
I agree with a lot of the concerns noted by @aardrian in https://github.com/w3c/csswg-drafts/issues/7387#issuecomment-1160991881 and while I think it's clear we need to do something here, I want us to be careful about what we're doing so that we don't make things worse. To that end, there's a few things we should consider:
order
as a convenience to perform semantic reordering (e.g. sorting lists). These are cases where all the orders should match, including the source order.My proposal here is twofold:
Element.sortChildrenBy(attribute or comparison function)
could go a long way towards reducing inappropriate use of order
for semantic ordering, especially if it can be so simple that we can slip copy-pasteable examples into various tutorials and reference pages on order
itself.Add a property (“reading-order”) that affects reading and interaction order simultaneously, not just focus order, and in a way that lends itself to explicit tailoring for each case of reordering, e.g.:
reading-order: source | auto | <integer>
impacts screenreader, 'speech' media, focus order (subordinate to tabindex)
source = document source order (as currently)
auto = source, except match randomizing layout methods (dense/masonry)
<integer> = modify source order by <integer> (just like order/z-index)
Could even make it a longhand of order
(bikeshed keyword):
order: <'box-order'> [ <'reading-order'> | reading-matches-box-order ]?
box-order: <integer> /* current order property */
reading-order: source | auto | <integer>
This makes it easy to think about them together, and allows a lot of flexibility in tailoring the reading order compared to the box order, but requires considering the reading order explicitly in order to affect it.
The CSS Working Group just discussed [css-flexbox][css-grid] Providing authors with a method of opting into following the visual order, rather than logical order
, and agreed to the following:
RESOLVED: the WG not accept ‘visual-order’ as a switch, but continue working on other methods of order that will aid various technologies
RESOLVED: (and vice-versa for the last baseline)
Agenda+ to discuss and resolve on reading-order
as proposed here. Let's include a11y representatives in that discussion also.
I thought I'd add some examples here as to how reading-order
might behave from the point of view of the different use cases authors have. This is based on my understanding after our break discussion at TPAC.
Example 1: The layout uses grid-auto-flow: dense
In this case, using dense packing indicates that the elements inside this layout do not have a defined order. The grid items should have reading-order: auto
, and the reading order will then follow the grid-modified order that is created by the dense packing.
Example 2: To create the optimal reading order at different breakpoints, the author uses media queries to change the reading order of elements at one or more breakpoints.
Within media queries, in addition to changing where items sit on the grid, the author will add the reading-order
property to each grid item, with an integer indicating the reading order of that item at that breakpoint. When developing such a layout, the author should create a canonical source order that makes the most sense if the document were read with no CSS. They will then only need to add reading-order
to grid items in presentations of the layout where reordering happens.
Example 3: The layout is being created by a WYSIWYG editor that allows people to create a layout visually.
The spec should clearly define that UAs used to create such layouts are non-conforming if they use reading-order
to avoid needing to re-order the source. As with an author creating such a layout manually, the UA should create a canonical source order, and re-order the underlying HTML to match it. It can then enable authors to create other presentations of the content, by using reading-order
.
@chrishtr
Agenda+ to discuss and resolve on reading-order as proposed https://github.com/w3c/csswg-drafts/issues/7387#issuecomment-1217193918. Let's include a11y representatives in that discussion also.
I take this to mean you do/did not have accessibility reps in the prior session. Do you have any for the coming discussion? Or are you looking for some?
I take this to mean you do/did not have accessibility reps in the prior session. Do you have any for the coming discussion? Or are you looking for some?
I am looking for some, and have emailed public-aria inviting that group to attend.
One thing I did not see mentioned is, what should happen to KB or AT focus when the layout order and/or focus order changes out from underneath the user? KB focus is easily detectable, but AT focus is usually not, so there is no consistent way to know whether the user is in an appropriate context where it's acceptable for the author to change the respective orders. Perhaps the recommendation should be to only change the order on user action, and have an optional parameter (if a JS API?) that hints where the new KB focus and/or AT focus should go.
I'm looking forward to attending the CSS call to discuss this. I think the proposal is a good starting point, but a CSS algorithm may be insufficient to determine flow order or where KB or AT focus should "land." That said, requiring authors to call focus() after a layout change also hasn't proven to work well… most forget. I could be convinced that algorithms may handle the general cases if explicit ordering and focus hint options remain.
Some additional comments that came from Apple internal discussion:
The CSS Working Group just discussed [css-flexbox][css-grid] Providing authors with a method of opting into following the visual order, rather than logical order
, and agreed to the following:
RESOLVED: Draft reading-order (minus source value) into css-display-4 ED
Drafted up css-display-4 ED with reading-order
and layout-order
longhands for order
as outlined in https://github.com/w3c/csswg-drafts/issues/7387#issuecomment-1217193918.
Agenda+ to request CSSWG review of the text and the following details:
order
as shorthand for reading-order
and layout-order
reading-order
applied to all elements, not just flex and gridorder
shorthand syntax defined as:
[ <'layout-order'> <'reading-order'>? ] | /* reading defaults to 0 */
[ reading && <'reading-order'> ] | /* set reading to value, layout to value */
[ layout && <'layout-order'> ] | /* set layout to value, reading to zero */
[ [ reading && layout ] && <integer> ] /* set both to same value */
Note: We are deliberately making it uncomfortable to set both, since in most cases where you want to change both you're supposed to fix the source order.
I think -webkit-order
must become an alias of reading-order
or layout-order
. I think it does not really matter but can you please tell me which one?
I think
-webkit-order
must become an alias ofreading-order
orlayout-order
. I think it does not really matter but can you please tell me which one?
-webkit-order
is an alias to order
, which will become a shorthand for reading-order
and layout-order
. As far as I understand, for example, setting order
(or -webkit-order
) shortcut to -1
will set layout-order: -1
and reading-order: 0
. This way it will keep all existing order
s and -webkit-order
s from changing reading order.
So, there’s no need to change anything, apart from implementing these two new properties. Please correct me if I’m wrong.
What should be -webkit-order
if you only declare reading-order
or layout-order
? Empty string?
What should be
-webkit-order
if you only declarereading-order
orlayout-order
? Empty string?
The same that’s already happening with animation, for example: the computed duration will be 0.5.
div {
-webkit-animation: 1s name;
animation-duration: 0.5s;
}
I checked it in Safari.
Or, specifically:
div {
-webkit-order: -1;
/* like you would set
layout-order: -1;
reading-order: 0;
*/
layout-order: 1;
}
In non-supporting browsers element’s order would be -1, in the supporting ones 1.
I think I was wrong saying that it does not matter which sub-property -webkit-order
should be an alias: imo, it should be an alias of layout-order
because order
currently changes the layout (visual) order but not the reading (focus) order, if I am not mistaken.
In non-supporting browsers element’s order would be -1, in the supporting ones 1.
I was thinking about this:
el.style.layoutOrder = 2
el.style.order; // ''
el.style.webkitOrder; // ?
A shorthand must serialize to empty string when it cannot represent all its longhands (CSSOM), so order
must serialize to empty string. Legacy name aliases (like -webkit-order
) require to replace the legacy name with the new property name (Cascade). So -webkit-order
must also serialize to empty string if it is an alias of order
.
In your example, -webkit-order
would be replaced with order
so -webkit-order
cannot be -1
.
Now I see no reason why someone would want to reflect layout-order
on -webkit-order
. The bidirectional mirroring is just a "happy" accident resulting from the legacy aliasing mechanism.
The issue also applies to -webkit-box-ordinal-group
, which is currently a mapping to order
. Imo, Compatibility should update it as a mapping to layout-order
.
@tabatkins suggested replacing [ reading-and-layout && <integer> ]
with [ [ reading && layout ] && <integer> ]
which folds the entire keyword-based grammar to an appropriately CSSy [ [ reading || layout ] && <integer> ]
so I've gone ahead and done that in https://github.com/w3c/csswg-drafts/commit/a00550093461a75b54215f500f724c97dfa368b9
BTW, this kind of feature could also offer a (moderately hacky) solution to being unable to effectively reorder animating nodes and such: https://github.com/whatwg/dom/issues/586#issuecomment-1420231217
Another example of the value of a constraint layout solver in css; not having to muck about with order properties.
Instead we kept bolting on never ending properties in the hopes that just one more will make layout not horrendous in css.
While I believe to be a great solution, I think the problem with assistive technologies is how you get them to read the layout that is different from the source order though.
We all know that assistive technologies do NOT read the page but the source order as stated in your proposal so for assistive technologies to figure out a way to read the actual page order/layout I believe is going to be a tough ask.
I'm more inclined to have order be taken out totally from the equation honestly. While I do see benefits from using order (both grid and flexbox) I am in the camp where I believe causes more harm than good for assistive technologies thus authors should be implementing their source code semantically and in order of work flow.
My 2¢
Having read the Chrome blog write-up, this seems like a great idea that admittedly I haven't hit too much, but have wondered about its implications when I have.
My initial thoughts are that it would be useful for the defaults to solve most use cases so that the reading order follows the layout, rather than having to remember "when I change the rendering order of the source I also need to apply a few more new rules". The reading-order
and focus-order
rules would then be useful for intentionally following the CSS-defined layout if that's desired. This stems from a feeling that this should be handled automatically with available manual interventions for (presumably) rare cases that would want to follow the source order in visually modified layouts, in line with;
We could also consider making the default ordering visual in cases such as grid masonry layout, or auto-flow: dense where reordering is almost inevitable.
Have there been considerations for enabling authors to retrieve the new focus/tab order from the DOM? A use-case for this is implementing something like a roving tab index. Imagine wanting to add arrow key listeners to move between cards (links) in a masonry layout where the whole grid is a single tab-stop.
Current solutions parse the DOM for focusable elements and assume they're in the correct visual order. These implementations are buggy when elements are reordered and without a way to get the visual/reading order from the DOM, they'll stay buggy after this change.
We're adding this to the agenda to see if we can get agreement on the simplified approach discussed in https://github.com/w3c/csswg-drafts/issues/8589
I wrote this up as a blog post, which has examples of the two possible ways an author would invoke this ordering.
So the proposal is to keep reading-order: auto
on the grid items of randomized methods, and to add a reading-order-items
property for the grid or flex container, which is used in the non-randomized cases, allowing the author to explain their intent for the reading order.
We simplify by removing reading-order: <integer>
, however this approach wouldn't prevent us from going down that line in the future if needed.
The CSS Working Group just discussed [css-flexbox][css-grid] Providing authors with a method of opting into following the visual order, rather than logical order
.
A proposal to provide a method in CSS for authors to opt in to following the visual order when in a flex or grid context.
The grid and flexbox specifications detail that reordering caused by these methods is only visual, and note that use of order or grid placement to do logical ordering is non-conforming.
With care from the author in creating a good document, this in general works well for screen reader users. Authors sometimes also use this to improve the experience for screenreader users. For example, by being able to show something visually near the top of the page but, because it would be repetitive for a screen reader user, physically locate it in elsewhere in the document.
Problems
Visual/tab order disconnect for keyboard users
In most cases, the document order is the correct logical order for screen reader users who are not able to see the visual display at all. However, if the author has reordered content using grid or flexbox, then the tab order of the document for keyboard users who are referencing the visual display can become disconnected, as it follows the document order.
Some use of grid layout in particular can cause reordering without input from the author. For example using
grid-auto-flow: dense
. In this case a screen reader user is likely well served by the document order, the keyboard navigator may experience unexpected jumps around the component as items appear out of logical order.Example: https://codepen.io/rachelandrew/pen/NWbLRQE
Authors also want to be able to reorder content at different breakpoints, to provide the best presentation of the layout for different amounts of screen real estate. In this case again, it is likely that by starting with a sensible document source, a screen reader user will not be affected. A keyboard navigator could experience big jumps around the layout if, for example, an item that logically appears near the top of the source is placed in the footer.
Example: https://codepen.io/rachelandrew/pen/xxRJBGz
Impact on screen reader users if the author assumes the visual order is the logical order
Screen reader users can be impacted by the issue if the author assumes the visual order is the logical order. For example, someone building a site using a visual design tool that lets them drag elements about and places them using grid layout. In this scenario the author may never see the document order. If that tool does not also modify the source to reflect the visual layout, the screen reader user is going to hear things in a different order than the author intended.
In addition, tools that use the CSS order to infer logical order, will affect screen reader and keyboard navigators alike. Examples:
Many discussions around this issue have ended on a note that authors should be “doing the right thing” and basing designs around a logically ordered document. As noted, in most cases this will serve screen reader users well. It can actually work against those using the keyboard to navigate however, as what they are looking at can become disconnected from the logical order.
Proposal
Provide a method in CSS for authors to opt into following the visual order when in a flex or grid context.
We already know the "visual order" of elements when in a flex or grid context:
When in a flex or grid context, authors could add a property, with a value that opts a component into a state where the order-modified, or grid-modified order should be followed. This would enable authors to indicate where this was appropriate, while still allowing order modification to be used without affecting logical order if that was appropriate.
For example:
An opt in would enable use cases such as this thread. It would also mean visual design tools that allow people to create layout by drag and drop could add the opt-in as soon as the user started to create a layout that had the potential of reordering.
We could also consider making the default ordering
visual
in cases such as grid masonry layout, orauto-flow: dense
where reordering is almost inevitable.Alternate approaches and related work
An HTML attribute
During the breaks in a 2019 CSS WG meeting I discussed this issue with @bkardell and @hober, we have considered using an HTML attribute to indicate that the contents of that element had no logical order, therefore order should be inferred by other means (such as that created by CSS).
I think this could have broader implications than we really need to solve the issues that authors have. It could lead to people always adding this attribute to the body, and therefore treating the document as a bunch of unsorted stuff. It would also require that this worked in block and inline layout too, for example with positioning. While it is possible to reorder with absolute positioning, positioning an element requires some work and thought form an author already, and many of the use cases are better solved with grid today.
In addition, in a responsive design, it may only be at certain breakpoints where this disconnect happens. This would mean that authors could opt in only at the point at which they use a media or container query with the express purpose of doing some reordering.
CSS Spatial Navigation
The Spatial Navigation spec proposes a method of navigating a 2d space.
Open UI: focusgroup
The focusgroup primitive aims to facilitate focus navigation using arrow keys.
Research and further reading
Various people have already written about this problem. These posts also include examples of the issue.
Examples from the community
I’ve asked for examples of this and related issues, please add a comment if you have more examples: