Skip to content

Commit

Permalink
[css-overflow-5] Editorial improvements to css-overflow-5 scroll mark…
Browse files Browse the repository at this point in the history
…ers (#11048)

Editorial improvements to css-overflow-5 scroll markers:
- Combines pseudo-element and general scroll marker text into single shared section.
- Defines common terms at the start of the section used throughout.
- Provides clear example of highlighting the active marker.
- Organized headings to provide natural section for subsequent controls (i.e. scroll-button).
  • Loading branch information
flackr authored Oct 21, 2024
1 parent 5b29ce2 commit b924e45
Showing 1 changed file with 131 additions and 111 deletions.
242 changes: 131 additions & 111 deletions css-overflow-5/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,17 @@ Introduction</h2>

This specification extends [[!CSS-OVERFLOW-4]].

: [[#scroll-marker-group|Scroll marker groups]]
: [[#scroll-navigation|Scroll navigation controls]]
::
This section defines pseudo-elements for automatically constructed [[#scroll-navigation|scroll navigation controls]].
This section defines stylable scroll navigation controls
with defined user interactions and accessible labels,
and pseudo-classes which automatically construct them.

: [[#fragmentation|Redirection of Overflow]]
::
This section defines a highly experimental, exploratory new model
for handling overflow by redirecting it into newly-generated [=fragmentation containers=].

: [[#scroll-navigation|Scroll navigation controls]]
::
This section defines stylable scroll navigation controls
with defined user interactions and accessible labels.


Note: At the time of writing, [[CSS-OVERFLOW-4]] is not completely finalized yet.
To avoid accidental divergences and maintenance overhead,
Expand All @@ -158,8 +155,45 @@ its content will be integrated into this specification,
which will then replace it.
Until then, this specification only contains additions and extensions to level 4.

<h2 id="scroll-marker-group">
Overflow Controls: the 'scroll-marker-group' property and pseudo-elements</h2>
<h2 id="scroll-navigation">
Scroll navigation controls</h2>

<h3 id="scroll-markers">
Scroll markers</h3>

A <dfn>scroll marker</dfn> is any element or pseudo-element with a [=scroll target=].
An element or pseudo-element's <dfn>scroll target</dfn> is the {{Element}} indicated by the [=scroll marker=].
Which elements are [=scroll markers=], and what their [=scroll targets=] are, is host-language defined.
The [[html#the-a-element|HTML &lt;a> element]] and [[svg2#Links|SVG &lt;a> element]]
are [=scroll markers=],
whose [=scroll target=] is the <l spec=html>[=indicated part=]</l>.
While these navigational links can be created today,
there is little feedback to the user regarding the current content being viewed, and
the interaction model does not match the expectations of many modern accessible UI components.

This specification adds a mechanism for creating groups of [=scroll marker=]s,
and for automatically creating '::scroll-marker'' pseudo-elements.
Within each group, the active marker reflects the current scroll position,
and can be styled to give the user an indication of which section they are in.

Use cases include a table of contents with links to relevant contents,
markers for scrolling carousel pages,
and scrollable tab panels.

Issue: Add images representing these examples.

<h4 id="scroll-marker-grouping">
Scroll marker grouping</h4>

An element with a <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a> attribute defines a <dfn>scroll marker group container</dfn>
having a <dfn>scroll marker group</dfn> containing all of the [=scroll marker=] elements for which this is the nearest ancestor [=scroll marker group container=].

Issue: The grouping of markers for scroll progress tracking should be separated from opting into focusgroup focus behavior.

A ''::scroll-marker-group'' pseudo-element is the [=scroll marker group container=] for its contained ''::scroll-marker'' pseudo-elements, which form a [=scroll marker group=] together.

<h4 id="scroll-marker-group">
The 'scroll-marker-group' property</h4>

<pre class=propdef>
Name: scroll-marker-group
Expand Down Expand Up @@ -192,38 +226,119 @@ Overflow Controls: the 'scroll-marker-group' property and pseudo-elements</h2>

</dl>

<h3 id="scroll-marker-group-pseudo">The ''::scroll-marker-group'' pseudo-element</h3>
<h4 id="scroll-marker-group-pseudo">The ''::scroll-marker-group'' pseudo-element</h4>

The <dfn selector>::scroll-marker-group</dfn> pseudo-element box
The <dfn selector>::scroll-marker-group</dfn> [=fully stylable pseudo-element=]
is generated by a [=scroll container=] element
having a computed 'scroll-marker-group' property that is not 'none',
representing a stylable sibling pseudo-element immediately adjacent to the [=scroll container=].
adjacent to the [=scroll container=].

The following additions are recommended for the default UA stylesheet
to ensure that the generation of scroll marker pseudo-elements does not invalidate the layout of the site:

<pre class="lang-css">
/* The generation of ::scroll-marker pseudo-elements cannot invalidate layout outside of this pseudo-element. */
/* The generation of ::scroll-marker pseudo-elements shouldn't
* invalidate layout outside of this pseudo-element. */
::scroll-marker-group { contain: size !important; }
</pre>

The 'scroll-marker-group' implicitly behaves as a single focusable component,
establishing a <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a>.

<h3 id="scroll-marker-pseudo">The ''::scroll-marker'' pseudo-element</h3>
<h4 id="scroll-marker-pseudo">The ''::scroll-marker'' pseudo-element</h4>

Similar to ''::before'' and ''::after'', all elements can have a ''::scroll-marker'' pseudo-element,
which is collected into the ''::scroll-marker-group'' of the nearest [=scroll container=] ancestor,
and scrolls to the element when activated.

When the computed 'content' value of a <dfn selector>::scroll-marker</dfn> pseudo-element is not 'none'
and its nearest ancestor [=scroll container=] [=scroll container=] has a computed 'scroll-marker-group' property that is not 'none',
the pseudo-element generates a box attached as a child of the ''::scroll-marker-group'' pseudo-element's generated box
on its nearest ancestor [=scroll container=].
These boxes are added in the [=tree order=] of their <a>originating element</a>.

These pseudo-elements have their {{HTMLLinkElement/scrollTargetElement}} set to their <a>originating element</a>.
They have a <a href="https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex"><code>tabindex</code></a> of '-1',
These pseudo-elements have an indicated [=scroll target=] of their <a>originating element</a>.
They behave as an element with a <a href="https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex"><code>tabindex</code></a> of '-1',
making them focusable within their '::scroll-marker-group' either by arrow key navigation within the group,
or via the tab key when currently active or when no other ''::scroll-marker'' is active and this is the first marker in the group,
ensuring the group has a <a href="https://open-ui.org/components/focusgroup.explainer/#guaranteed-tab-stop">guaranteed tab stop</a>.

<h4 id="active-scroll-marker">The active scroll marker</h4>

Exactly one [=scroll marker=] within each [=scroll marker group=] is determined to be active at a time.
An active [=scroll marker=] can be styled by the '':checked'' pseudo-class.

<div class='example'>
The following snippet shows how the link to the currently scrolled section can be highlighted:

<pre highlight=css>
a:checked {
font-weight: bold;
}
</pre>
</div>

A scrolling operation might animate towards a particular position
(e.g. scrollbar arrow clicks, arrow key presses, "behavior: smooth" programmatic scrolls)
or might directly track a user’s input
(e.g. touch scrolling, scrollbar dragging).
In either case, the user agent chooses an 'eventual scroll position' to which the scroller
will reach. This ensures that the relevant marker is activated immediately.

This 'eventual scroll position' is used to determine the active marker within each [=scroll marker group=].
Since markers themselves may represent just the start of the content (e.g. headers), we consider the active marker to be the first one which we are at or beyond the scroll position of.

<div algorithm="scroll tracking">
Whenever a [=scroll container=] is scrolled, or layout changes the scroll position, the user agent must run these steps to determine the active marker:

1. Let <var>position</var> be the 'eventual scroll position' for the scrolling operation.
1. For each focusgroup <var>group</var> containing one or more [=scroll marker control=] elements whose [=scroll target=] is a descendant of [=scroll container=]:

1. Let <var>markers</var> be all of the [=scroll marker control=] elements which are a part of the [=scroll marker group=] for the [=scroll container=].
1. Let <var>targets</var> be the [=scroll target=]s of |markers|, associated with the item of |markers| they came from, and sorted in [=tree order=].
1. For each |target| in |targets|, <a>determine the scroll-into-view position</a> of |target|, storing this as the associated |target position| of |target|.
1. Let |selected target| be the largest-indexed item of |targets|
whose associated |target position| is equal to or before |position| in both the block and inline axises in the current writing mode direction of the [=scroll container=].

Issue: When the next marker is closer to being aligned than the previous we should use the next marker, in a manner similar to mandatory snap point selection.

1. : If there is no such item,
::
Set the active state of all |markers| in the |group| to false and return.

1. Let |selected marker| be the marker associated with |selected target|.
If multiple items of |markers| are associated with |selected target|,
set |selected marker| to be the marker that is earliest in tree order.
1. Set the active state of |selected marker| to true.
1. : If the active element was the <a href="https://open-ui.org/components/focusgroup.explainer/#last-focused-memory">last-focused element</a> of the |group|,
::
Focus |selected marker|
1. Set the <a href="https://open-ui.org/components/focusgroup.explainer/#last-focused-memory">last-focused element</a> of the |group| to |selected marker|.
1. Set the active state of all other |markers| in the |group| to false.
</div>

<h4 id="scroll-marker-activation">Activation behavior</h4>

<div algorithm="scrollTargetElement activation">
When a [=scroll marker=] with a non-null [=scroll target=] is activated by explicit invocation or arrow key focus:

1. Let <var>element</var> be the [=scroll target=] of the control.
1. Let <var>block</var> be "<code>start</code>".
1. Let <var>inline</var> be "<code>start</code>".
1. <a lt='scroll a target into view'>Scroll the element into view</a> with <var>behavior</var>, <var>block</var>, and <var>inline</var>.
1. : If the activation was triggered by invocation
::
1. <a spec=html>Follow the hyperlink</a> updating the URL, however retain focus on the marker element.

Note: If the user tabs away the focus behavior will ensure they tab into the relevant content.
</div>

<h4 id="scroll-target-focus">Focus behavior</h4>

When a [=scroll marker control=] is activated,
the next tabindex-ordered focus navigation will focus the [=scroll target=] if it is focusable,
otherwise, it will find the next focusable element from this <var>element</var> as though it were focused.

<h2 id="fragmentation" class=no-num>
Appendix A: Redirection of Overflow</h2>

Expand Down Expand Up @@ -883,101 +998,6 @@ the ''continue/fragments'' value of the 'continue' property.
</td></tr></table>
</div>

<h2 id="scroll-navigation">
Appendix B: Scroll navigation controls</h2>

[[html#the-a-element]] allows creating navigational links to a particular scroll position within the same page.
However, there is little feedback to the user regarding the current content being viewed, and
the interaction model does not match the expectations of modern accessible UI components.

This specification adds a mechanism for creating scroll navigation controls within groups of <{a}> elements.
A group is created through the <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a> attribute
on an ancestor containing one or more <{a}> elements whose <a spec=html>indicated part</a> is on the current page.
Within each group, the active marker reflects the current scroll position, and can be styled to give the user an indication of which section they are in.

Use cases include a table of contents with links to relevant contents,
markers for scrolling carousel pages,
and scrollable tab panels.

Issue: Add images representing these examples.

<h3 id="scroll-target">{{HTMLLinkElement/scrollTargetElement}} attribute</h3>

An <{a}> element has its {{HTMLLinkElement/scrollTargetElement}}
initialized to the result of running the <a spec=html>select the indicated part</a> given the current {{Document}} and the <dfn element-attr for=a>href</dfn> attribute value as the |URL|,
turning it into a [=scroll marker control=] if the resulting <a spec=html>indicated part</a> is non-null.

The <dfn attribute for=HTMLLinkElement lt=scrollTargetElement>HTMLLinkElement.scrollTargetElement</dfn> instance property
gets and sets the element being interacted with by the anchor link and can be used to override the initial value established by the |href| property.

An <{a}> element or ''::scroll-marker'' pseudo-element with a non-null {{HTMLLinkElement/scrollTargetElement}}
represents a <dfn export>scroll marker control</dfn> which participates in a <dfn>scroll marker group</dfn>
defined by the containing ''::scroll-marker-group'' psuedo-element (for ''::scroll-marker'' pseudo-elements)
or nearest ancestor element establishing a <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a>.
Exactly one control in a group will have its "checked" state set to true.
A [=scroll marker control=] with a true "checked" state can be styled by the '':checked'' pseudo-class.

<div algorithm="scrollTargetElement activation">
When a [=scroll marker control=] is activated by explicit invocation or arrow key focus:

1. Let <var>element</var> be the {{HTMLLinkElement/scrollTargetElement}} of the control.
1. Let <var>block</var> be "<code>start</code>".
1. Let <var>inline</var> be "<code>start</code>".
1. <a lt='scroll a target into view'>Scroll the element into view</a> with <var>behavior</var>, <var>block</var>, and <var>inline</var>.
1. : If the activation was triggered by invocation
::
1. <a spec=html>Follow the hyperlink</a> updating the URL, however retain focus on the marker element.

Note: If the user tabs away the focus behavior will ensure they tab into the relevant content.
</div>

<h4 id="scroll-container-scroll">Scroll tracking</h4>

A scrolling operation might animate towards a particular position
(e.g. scrollbar arrow clicks, arrow key presses, "behavior: smooth" programmatic scrolls)
or might directly track a user’s input
(e.g. touch scrolling, scrollbar dragging).
In either case, the user agent chooses an 'eventual scroll position' to which the scroller
will reach. This ensures that the relevant marker is activated immediately.

This 'eventual scroll position' is used to determine the active marker within each [=scroll marker group=].
Since markers themselves may represent just the start of the content (e.g. headers), we consider the active marker to be the first one which we are at or beyond the scroll position of.

<div algorithm="scroll tracking">
Whenever a [=scroll container=] is scrolled, or layout changes the scroll position, the user agent must run these steps to determine the active marker:

1. Let <var>position</var> be the 'eventual scroll position' for the scrolling operation.
1. For each focusgroup <var>group</var> containing one or more [=scroll marker control=] elements whose {{HTMLLinkElement/scrollTargetElement}} is a descendant of [=scroll container=]:

1. Let <var>markers</var> be all of the [=scroll marker control=] elements which are a part of the [=scroll marker group=] for the [=scroll container=].
1. Let <var>targets</var> be the {{HTMLLinkElement/scrollTargetElement}}s of |markers|, associated with the item of |markers| they came from, and sorted in [=tree order=].
1. For each |target| in |targets|, <a>determine the scroll-into-view position</a> of |target|, storing this as the associated |target position| of |target|.
1. Let |selected target| be the largest-indexed item of |targets|
whose associated |target position| is equal to or before |position| in both the block and inline axises in the current writing mode direction of the [=scroll container=].

Issue: When the next marker is closer to being aligned than the previous we should use the next marker, in a manner similar to mandatory snap point selection.

1. : If there is no such item,
::
Set the "checked" state of all |markers| in the |group| to false and return.

1. Let |selected marker| be the marker associated with |selected target|.
If multiple items of |markers| are associated with |selected target|,
set |selected marker| to be the marker that is earliest in tree order.
1. Set the "checked" state of |selected marker| to true.
1. : If the active element was the <a href="https://open-ui.org/components/focusgroup.explainer/#last-focused-memory">last-focused element</a> of the |group|,
::
Focus |selected marker|
1. Set the <a href="https://open-ui.org/components/focusgroup.explainer/#last-focused-memory">last-focused element</a> of the |group| to |selected marker|.
1. Set the "checked" state of all other |markers| in the |group| to false.
</div>

<h4 id="scroll-target-focus">Focus behavior</h4>

When a [=scroll marker control=] is activated,
the next tabindex-ordered focus navigation will focus the {{HTMLLinkElement/scrollTargetElement}} if it is focusable,
otherwise, it will find the next focusable element from this <var>element</var> as though it were focused.

<h2 id=privclass=nonum>
Appendix C: Privacy Considerations</h2>

Expand Down

0 comments on commit b924e45

Please sign in to comment.