Skip to content

Commit eac9300

Browse files
authored
[css-overflow-5] Create scroll markers from <a> elements. (#10617)
This changes the scroll marker primitive to be based on a regular <a> element within a focusgroup.
1 parent 9b890a4 commit eac9300

File tree

1 file changed

+58
-60
lines changed

1 file changed

+58
-60
lines changed

css-overflow-5/Overview.bs

Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ Overflow Controls: the 'scroll-marker-group' property and pseudo-elements</h2>
207207
::scroll-marker-group { contain: size !important; }
208208
</pre>
209209

210+
The 'scroll-marker-group' implicitly behaves as a single focusable component,
211+
establishing a <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a>.
212+
210213
<h3 id="scroll-marker-pseudo">The ''::scroll-marker'' pseudo-element</h3>
211214

212215
When the computed 'content' value of a <dfn selector>::scroll-marker</dfn> pseudo-element is not 'none'
@@ -215,9 +218,11 @@ Overflow Controls: the 'scroll-marker-group' property and pseudo-elements</h2>
215218
on its nearest ancestor [=scroll container=].
216219
These boxes are added in the [=tree order=] of their <a>originating element</a>.
217220

218-
These pseudo-elements behave as a <{button}>
219-
with {{HTMLButtonElement/scrollTargetElement}} set to its <a>originating element</a>.
220-
They can be focused and invoked.
221+
These pseudo-elements have their {{HTMLLinkElement/scrollTargetElement}} set to their <a>originating element</a>.
222+
They have a <a href="https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex"><code>tabindex</code></a> of '-1',
223+
making them focusable within their '::scroll-marker-group' either by arrow key navigation within the group,
224+
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,
225+
ensuring the group has a <a href="https://open-ui.org/components/focusgroup.explainer/#guaranteed-tab-stop">guaranteed tab stop</a>.
221226

222227
<h2 id="fragmentation" class=no-num>
223228
Appendix A: Redirection of Overflow</h2>
@@ -885,51 +890,46 @@ Appendix B: Scroll navigation controls</h2>
885890
However, there is little feedback to the user regarding the current content being viewed, and
886891
the interaction model does not match the expectations of modern accessible UI components.
887892

888-
This specification adds a mechanism for creating scroll navigation controls.
889-
The active marker, reflecting the current position, can be styled to give the user an indication of which section they are in.
890-
The set of markers are treated as a component following the accessibility guidelines for keyboard navigation within components.
893+
This specification adds a mechanism for creating scroll navigation controls within groups of <{a}> elements.
894+
A group is created through the <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a> attribute
895+
on an ancestor containing one or more <{a}> elements whose <a spec=html>indicated part</a> is on the current page.
896+
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.
891897

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

896902
Issue: Add images representing these examples.
897903

898-
Issue: Explore whether scrolltarget can be more directly associated with anchor tags.
899-
900-
<h3 id="scroll-target"><{button/scrolltarget}> attribute</h3>
901-
902-
The <dfn element-attr for=button>scrolltarget</dfn> attribute turns a <{button}> element into a [=scroll marker control=].
903-
This takes the ID of the element to target as its value.
904-
905-
The <dfn attribute for=HTMLButtonElement lt=scrollTargetElement>HTMLButtonElement.scrollTargetElement</dfn> instance property
906-
gets and sets the element being interacted with by the control button.
907-
This is the JavaScript equivalent of the <{button/scrolltarget}> HTML attribute.
904+
<h3 id="scroll-target">{{HTMLLinkElement/scrollTargetElement}} attribute</h3>
908905

909-
A 'button' with a non-null {{HTMLButtonElement/scrollTargetElement}}
910-
represents a <dfn export>scroll marker control</dfn> that forms a <dfn>scroll marker group</dfn> for its nearest [=scroll container=]
911-
in which exactly one control in the group can have its 'checked' state set to true.
912-
A [=scroll marker control=] with a true 'checked' state can be styled by the '':checked'' pseudo-class.
906+
An <{a}> element has its {{HTMLLinkElement/scrollTargetElement}}
907+
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|,
908+
turning it into a [=scroll marker control=] if the resulting <a spec=html>indicated part</a> is non-null.
913909

914-
The [=scroll marker group=] that contains a <{button}> element a also contains all the other <{button}> elements b that fulfill the following conditions:
910+
The <dfn attribute for=HTMLLinkElement lt=scrollTargetElement>HTMLLinkElement.scrollTargetElement</dfn> instance property
911+
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.
915912

916-
* The <{button}> element b has a non-null {{HTMLButtonElement/scrollTargetElement}} value.
917-
* a and b's {{HTMLButtonElement/scrollTargetElement}} have the same nearest [=scroll container=].
913+
An <{a}> element or ''::scroll-marker'' pseudo-element with a non-null {{HTMLLinkElement/scrollTargetElement}}
914+
represents a <dfn export>scroll marker control</dfn> which participates in a <dfn>scroll marker group</dfn>
915+
defined by the containing ''::scroll-marker-group'' psuedo-element (for ''::scroll-marker'' pseudo-elements)
916+
or nearest ancestor element establishing a <a href="https://open-ui.org/components/focusgroup.explainer/">focusgroup</a>.
917+
Exactly one control in a group will have its "checked" state set to true.
918+
A [=scroll marker control=] with a true "checked" state can be styled by the '':checked'' pseudo-class.
918919

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

922-
1. Let <var>element</var> be the {{HTMLButtonElement/scrollTargetElement}} of the control.
923+
1. Let <var>element</var> be the {{HTMLLinkElement/scrollTargetElement}} of the control.
923924
1. Let <var>block</var> be "<code>start</code>".
924925
1. Let <var>inline</var> be "<code>start</code>".
925926
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>.
926-
1. If activated by invocation, move focus to <var>element</var>.
927-
If <var>element</var> is not focusable this will result in there being no active element,
928-
but the next focus change will proceed from this <var>element</var> as if it were focused.
929-
</div>
927+
1. : If the activation was triggered by invocation
928+
::
929+
1. <a spec=html>Follow the hyperlink</a> updating the URL, however retain focus on the marker element.
930930

931-
Issue: Moving focus to the control on activation means that the only way to control scroll markers via the keyboard is to tab into them.
932-
We should retain focus after the control is activated, while still altering the point from which the next focusable element is found if the user tabs away.
931+
Note: If the user tabs away the focus behavior will ensure they tab into the relevant content.
932+
</div>
933933

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

@@ -938,47 +938,45 @@ Issue: Explore whether scrolltarget can be more directly associated with anchor
938938
or might directly track a user’s input
939939
(e.g. touch scrolling, scrollbar dragging).
940940
In either case, the user agent chooses an 'eventual scroll position' to which the scroller
941-
will reach.
941+
will reach. This ensures that the relevant marker is activated immediately.
942942

943-
This 'eventual scroll position' is used to determine the active marker.
943+
This 'eventual scroll position' is used to determine the active marker within each [=scroll marker group=].
944944
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.
945945

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

949949
1. Let <var>position</var> be the 'eventual scroll position' for the scrolling operation.
950-
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=].
951-
1. Let <var>targets</var> be the set of {{HTMLButtonElement/scrollTargetElement}} for those controls sorted in [=tree order=].
952-
1. Let <var>selected</var> be the first element in <var>targets</var>, or null if <var>targets</var> is empty.
953-
1. For each <var>target</var> in <var>targets</var>:
954-
1. Set <var>selected</var> to <var>target</var>.
955-
1. Let <var>targetPosition</var> be the position that would be scrolled to if we scroll <var>target</var> into view.
956-
1. : If <var>targetPosition</var>'s scroll block offset is less than or equal to <var>position</var>'s scroll block offset, and
957-
<var>targetPosition</var>'s scroll inline offset is less than or equal to <var>position</var>'s scroll inline offset.
958-
::
959-
Update <var>selected</var> to <var>target</var>.
960-
Break.
961-
1. : If <var>selected</var> is not null,
962-
::
963-
1. Let <var>marker</var> be the first control in <var>markers</var> whose {{HTMLButtonElement/scrollTargetElement}} is <var>selected</var>.
964-
1. Set the 'checked' state of <var>marker</var> to true.
965-
: Otherwise,
966-
::
967-
Set the 'checked' state of all controls in <var>markers</var> to false.
968-
</div>
950+
1. For each focusgroup <var>group</var> containing one or more [=scroll marker control=] elements whose {{HTMLLinkElement/scrollTargetElement}} is a descendant of [=scroll container=]:
969951

970-
Issue: Should we allow for none of the markers to be currently active, e.g. if not yet scrolled past the position of the first marker.
952+
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=].
953+
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=].
954+
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|.
955+
1. Let |selected target| be the largest-indexed item of |targets|
956+
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=].
971957

972-
<h4 id="scroll-target-focus">Focus behavior</h4>
958+
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.
973959

974-
A [=scroll marker control=] is only focusable if it is 'checked'. Within a group, exactly one marker is 'checked' at a time.
960+
1. : If there is no such item,
961+
::
962+
Set the "checked" state of all |markers| in the |group| to false and return.
963+
964+
1. Let |selected marker| be the marker associated with |selected target|.
965+
If multiple items of |markers| are associated with |selected target|,
966+
set |selected marker| to be the marker that is earliest in tree order.
967+
1. Set the "checked" state of |selected marker| to true.
968+
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|,
969+
::
970+
Focus |selected marker|
971+
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|.
972+
1. Set the "checked" state of all other |markers| in the |group| to false.
973+
</div>
975974

976-
When such a control is focused,
977-
* The down arrow or right arrow move focus to and activate the next control from its [=scroll marker group=].
978-
* The up arrow or left arrow move focus to and activate the previous control from its [=scroll marker group=].
979-
* Space or Enter invoke the control.
975+
<h4 id="scroll-target-focus">Focus behavior</h4>
980976

981-
Issue: We should be able to tab away from the target immediately after using arrow navigations rather than requiring activating the control first.
977+
When a [=scroll marker control=] is activated,
978+
the next tabindex-ordered focus navigation will focus the {{HTMLLinkElement/scrollTargetElement}} if it is focusable,
979+
otherwise, it will find the next focusable element from this <var>element</var> as though it were focused.
982980

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

0 commit comments

Comments
 (0)