Skip to content

Commit 8739881

Browse files
authored
Add more use cases and alternatives considered. (#11352)
1 parent 8814e9e commit 8739881

File tree

1 file changed

+203
-1
lines changed

1 file changed

+203
-1
lines changed

css-overflow-5/carousel-explainer.md

Lines changed: 203 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,9 @@ ul::column::scroll-marker {
261261
}
262262
```
263263

264-
## Putting it all together
264+
## Use cases
265+
266+
### Carousels
265267

266268
With the features described, developers can create an automatically paginated carousel UX from a semantic list of items, e.g.
267269

@@ -342,11 +344,100 @@ and only having the user tab through content on the current page.
342344
}
343345
```
344346

347+
Of note, is that they can mix and match the features they want
348+
and style each piece.
349+
350+
### Table of contents auto-highlighting
351+
352+
The scroll marker feature provides a great drop-in way for a table of contents to automatically highlight the current section, e.g.
353+
354+
```
355+
<style>
356+
/* A floating table of contents similar to spec pages */
357+
#table-of-contents {
358+
position: fixed;
359+
top: 0;
360+
left: 0;
361+
scroll-marker-contain: auto;
362+
363+
& a:target-current {
364+
font-weight: bold;
365+
}
366+
}
367+
</style>
368+
<ul id=table-of-contents>
369+
<li><a href="#s1">Section 1</a></li>
370+
<li><a href="#s2">Section 2</a>
371+
<ul>
372+
<li><a href="#s2-1">Subsection 1</a>
373+
<li><a href="#s2-2">Subsection 2</a>
374+
<li>
375+
</li>
376+
...
377+
<li><a href="#s2">Section n</a></li>
378+
</ul>
379+
```
380+
381+
### Paginated reading UI
382+
383+
A book reading interface can be created by using the automatic pagination. E.g.
384+
385+
```html
386+
<style>
387+
.book {
388+
columns: 1;
389+
overflow: auto;
390+
scroll-snap-type: x mandatory;
391+
}
392+
.book::column {
393+
scroll-snap-align: center;
394+
}
395+
/* Optionally adding next/prev page buttons: */
396+
.book::scroll-button(next) {
397+
content: ">" / "Next page";
398+
}
399+
.book::scroll-button(prev) {
400+
content: "<" / "Previous page";
401+
}
402+
```
403+
345404
## Future work
346405
347406
There are a few carousel designs not currently addressed.
348407
This section enumerates and explores these areas.
349408
409+
### Vertical auto-paged carousels
410+
411+
Column fragmentation is a convenient way to automatically paginate a list of items horizontally,
412+
however we should have a mechanism for paginating vertically as well.
413+
Most likely, this will be of the form `column-wrap: wrap` similar to the `flex-wrap` property,
414+
resulting in columns wrapping in the block direction after they overflow the inline direction.
415+
With this a vertically paginated carousel could be defined as the following:
416+
417+
```css
418+
.carousel {
419+
overflow: auto;
420+
scroll-snap-type: y mandatory;
421+
columns: 1;
422+
column-wrap: wrap;
423+
}
424+
425+
.carousel::column {
426+
scroll-snap-align: center;
427+
}
428+
429+
.carousel::column::scroll-marker {
430+
/* marker styles */
431+
}
432+
```
433+
434+
### Improved pagination styling
435+
436+
Many paginated interfaces allow the user to peek into the subsequent / previous pages.
437+
Column layouts force an integer number of columns per page meaning they always perfectly fill the space.
438+
This could be supported by allowing for a fractional column value,
439+
or specifying the desired overlap region.
440+
350441
### Cyclic carousels
351442
352443
Many carousels allow scrolling from the last item in the list to the first, or vice versa.
@@ -363,3 +454,114 @@ Auto-advancing carousels introduces many potential accessibility issues if not i
363454
The [Web Accessibility Initiative Carousel Animations](https://www.w3.org/WAI/tutorials/carousels/animations/) guidelines explores the necessary affordances.
364455
Most carousel experiences can be authored without automatically advancing sections,
365456
and in the mean-time author script could implement the animation following the WAI guidelines.
457+
458+
## Alternative approaches considered
459+
460+
There are many other ways that we could deliver these capabilities.
461+
462+
### &lt;carousel&gt; element
463+
464+
An element could encapsulate a lot of the features without needing to express them directly as CSS properties.
465+
One of the main challenges with this approach is that carousels have a large amount of variation in their designs.
466+
This would likely add significant complexity to the design of a high level element,
467+
or require some of the individual features proposed anyways.
468+
469+
### Templated content instead of columns and pseudo-elements
470+
471+
It would be nice for authors to be able to slot in rich content,
472+
as they would with a custom element.
473+
For example, they could provide a template of content to be created per page
474+
with a slot for the contents of that page.
475+
476+
One challenge is that the original content should retain its original structure.
477+
This may be possible by dynamically slotting elements to particular pages in a shadow tree.
478+
479+
### Using regions or grid-flow instead of ::scroll-marker-group
480+
481+
It would be reasonable to think that if we had a way of flowing elements into another area,
482+
we could use that to create the group of scroll markers.
483+
E.g. you could imagine using the [flow-into](https://drafts.csswg.org/css-regions/#the-flow-into-property) and [flow-from](https://drafts.csswg.org/css-regions/#flow-from) properties as follows:
484+
485+
```html
486+
<style>
487+
.markers {
488+
flow-from: markers;
489+
}
490+
/* Generated within the element, similar to a ::before pseudo-element. */
491+
li::scroll-marker {
492+
flow-into: markers;
493+
content: ' ';
494+
}
495+
</style>
496+
<ul class=scroller>
497+
<li>Item 1</li>
498+
<li>Item 2</li>
499+
<li>Item 3</li>
500+
</ul>
501+
<div class=markers>
502+
</div>
503+
```
504+
505+
This is in fact very similar to the original direction of this proposal,
506+
and is nice in its generality, but was abandoned for a few main reasons:
507+
508+
1. In most use cases that developers use scroll markers,
509+
they would want them to flow elsewhere rather than inline where the user is already scrolled to the content.
510+
Having this implicit with the `::scroll-marker-group` reduces the number of features needed to be combined to establish this.
511+
A notable exception to this is that when not reflowed they could serve as self links [#10498](https://github.com/w3c/csswg-drafts/issues/10498).
512+
2. Having an implicit group containing the markers makes allows for the implicit establishment of focusgroup semantics for those markers.
513+
One is active at a time, and can automatically assign appropriate itemized AX roles.
514+
If they're completely independent then there's an expectation they're focused in dom order w.r.t. their owning element,
515+
and not necessarily linked with the other markers.
516+
3. Requires the developer to create the area for the markers.
517+
This could be alleviated by allowing the `::before` or `::after` pseudo-elements to contain flowing content,
518+
but would likely introduce significant complexity. E.g.
519+
```css
520+
.scroller::after {
521+
flow-from: markers;
522+
}
523+
```
524+
525+
This is still a nice direction to be considered, and potentially which we could even explain the behavior of `::scroll-marker-group` in the future.
526+
E.g. If we decide to do this later, we could explain that the default `::scroll-marker` `flow-into` value is the `flow-from` established by the `::scroll-marker-group`.
527+
528+
### Invoker action and focusgroup invoke action instead of scroll markers
529+
530+
We could add a new built-in `invoke-action` (see [invokers](https://open-ui.org/components/invokers.explainer/)) `scrollTo`. When invoked, the `invokeTarget` will be scrolled to within its ancestor scrolling container. E.g.
531+
532+
```html
533+
<button invoketarget="my-section" invokeaction="scrollTo">Scroll to section</button>
534+
...
535+
<section id="my-section">
536+
This will be scrolled into view when you click the button
537+
</section>
538+
```
539+
540+
Invoker actions are only [invoked](https://open-ui.org/components/invokers.explainer/#terms) on explicit activation,
541+
and interest actions are shown [interest](https://open-ui.org/components/interest-invokers.explainer/#terms) on focus or hover.
542+
For scroll markers, we want the action to be taken only when the selected marker changes, which occurs on focus navigation within the group, but not on hover.
543+
544+
As such, we'd propose adding the `invoke` keyword to the `focusgroup` attribute to allow invoking the `invokeaction` on focusgroup focus changes. E.g.
545+
546+
```html
547+
<style>
548+
#toc {
549+
position: sticky;
550+
top: 0;
551+
}
552+
</style>
553+
<ul class="toc" focusgroup="invoke">
554+
<li><button tabindex="-1" invoketarget="section-1" invokeaction="scrollTo">Section 1</button></li>
555+
<li><button tabindex="-1" invoketarget="section-2" invokeaction="scrollTo">Section 2</button></li>
556+
<li><button tabindex="-1" invoketarget="section-3" invokeaction="scrollTo">Section 3</button></li>
557+
<li><button tabindex="-1" invoketarget="section-4" invokeaction="scrollTo">Section 4</button></li>
558+
</ul>
559+
<section id="section-1">...</section>
560+
<section id="section-2">...</section>
561+
<section id="section-3">...</section>
562+
<section id="section-4">...</section>
563+
```
564+
565+
Note that this example uses tabindex="-1" to apply the [roving tab index with a guaranteed tab stop](https://open-ui.org/components/focusgroup.explainer/#guaranteed-tab-stop) behavior from focusgroup.
566+
567+
This approach implements the navigation behavior, but notably does not explain how scroll markers would track the scroll state and allow styling the active marker.

0 commit comments

Comments
 (0)