Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 122 additions & 109 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,42 @@ 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=].
In particular, [[html#the-a-element]] and [[svg2#Links]] are scroll markers whose [=scroll target=] is the <a spec=html>indicated part</a>
resulting from calling <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|.
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>

A <dfn>scroll marker group</dfn> of [=scroll marker=] elements is created by setting the <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a> attribute
on an ancestor those [=scroll marker=]s.
''::scroll-marker'' pseudo-elements are implicitly part of the ''::scroll-marker-group'' group created by their nearest ancestor [=scroll container=].

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

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

<pre class=propdef>
Name: scroll-marker-group
Expand Down Expand Up @@ -192,7 +223,7 @@ 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
is generated by a [=scroll container=] element
Expand All @@ -203,27 +234,104 @@ Overflow Controls: the 'scroll-marker-group' property and pseudo-elements</h2>
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>

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 +991,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