Skip to content

Commit 1ca2c48

Browse files
author
Jihye Hong
authored
Merge pull request w3c#12 from WICG/first-draft
Add the first draft of Spatial Navigation.
2 parents 50003fb + b424764 commit 1ca2c48

13 files changed

Lines changed: 4923 additions & 29 deletions

.DS_Store

-6 KB
Binary file not shown.

explainer.md

Lines changed: 201 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,124 @@
1-
# Proposed APIs for the spatial navigation
2-
<b>NOTE: This is an unofficial proposal draft.</b>
1+
# Proposed Model and APIs for spatial navigation
32

4-
To support the spatial navigation in the Web, we need to develop several standard APIs. The APIs seem to be discussed with the suitable working groups in W3C (mainly in CSS WG). In this explainer page, the latest status of the spatial navigation would be summarized so that the overall progress could be tracked at a glance.
3+
## Introduction
54

6-
## Enabling the spatial navigation mode
7-
It makes author set the spatial navigation mode. The following APIs could be considered for the possibilities to support the feature:
5+
Historically, most browsers have not offered features to let users move the focus directionally.
6+
Some, such as TV browsers, have enabled users to move the focus using the arrow keys out of necessity,
7+
since no other input mechanism is available on a typical TV remote control.
88

9-
#### * CSS property
10-
- If the proposed property below is applied to the element, the DOM subtree rooted at the element can be managed by the spatial navigation.
11-
```css
12-
// CSS property
13-
arrow-key-behavior: auto | focus-nav
14-
```
15-
- auto: The arrow keys work as the UA-defined manner.
16-
- focus-nav: The arrow keys work for the spatial navigation.
9+
Others, have enabled different key combinations to control spatial navigation,
10+
such as pressing the <code class=key>Shift</code> key together with arrow keys.
11+
12+
This ability to move around the page directionally is called <strong>spatial navigation</strong>
13+
(or <strong>spatnav</strong> for short).
14+
15+
Spatial navigation can be useful for a webpage built using a grid-like layout,
16+
or other predominantly non linear layouts.
17+
The figure below represents a photo gallery arranged in a grid layout.
18+
If the user presses the <code class=key>Tab</code> key to move focus,
19+
they need to press the key many times to reach the desired element.
20+
Also, the grid layout may arrange the layout of elements independently of their source order.
21+
Therefore sequential navigation using the <code class=key>Tab</code> key makes focus navigation unpredictable.
22+
In contrast, <a>spatial navigation</a> moves the focus among focusable elements
23+
depending on their position
24+
allowing it to address problems encountered with sequential navigation.
25+
26+
<img alt="Illustration of a layout which benefits from spatial nativation" src="images/spatnav-enable.png" style="width: 500px; margin: auto; display: block"/>
27+
28+
While arrow keys are naturally suited to control spatial navigation,
29+
pressing them (on devices that have such keys)
30+
has generally triggered other behavior,
31+
such as scrolling.
32+
This specification introduces CSS properties and Javascript APIs
33+
enabling authors to turn on spatial navigation using arrow keys
34+
and to control its behavior.
35+
36+
Some aspects of this specification, such as the Javascript Events,
37+
also extends how sequential navigation work,
38+
in order to make sure that keyboard navigation in general
39+
has a consistent and well defined model.
40+
41+
42+
## Overview
43+
44+
Spatial navigation is said to be <strong>active</strong> on an element
45+
when the user can invoke spatial navigation
46+
by pressing the arrow keys without modifier keys
47+
when that element is focused.
48+
49+
Authors can activate spatial navigation
50+
on a document or part of a document
51+
using the `spatial navigation` property.
52+
53+
On devices which do not have any pointing input device,
54+
and especially on devices such as TVs which also lack a <code>Tab</code> key to control
55+
<a herf="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">sequential focus navigation</a>,
56+
User Agents should make spatial navigation active.
57+
58+
When spatial navigation is active,
59+
pressing an arrow key will either
60+
move the focus from its current location to a new focusable item in the direction requested,
61+
or scroll if there is no appropriate item.
62+
63+
More specifically,
64+
the User Agent will first search for visible and focusable items
65+
in the direction indicated
66+
within the current spatial navigation focus container
67+
(by default the root element, scrollable elements, and iframes,
68+
but other elements can be made into spatial navigation focus containers
69+
using the `spatnav-container` property).
70+
71+
If it finds any, it will pick the best one for that direction,
72+
and move the focus there.
73+
74+
If it does not, it will scroll the spatial navigation focus container in the requested direction
75+
instead of moving focus.
76+
Doing so may uncover focusable elements
77+
which would then be eligible targets to move the focus to
78+
next time spatial navigation in the same direction is requested.
79+
80+
If the spatial navigation focus container cannot be scrolled,
81+
either because it is not a scrollable element
82+
or because it is already scrolled to the maximum in that direction,
83+
the User Agent will select the next spatial navigation focus container up the ancestry chain,
84+
and repeat the process of
85+
looking for eligible focus targets,
86+
selecting the best one if there's any,
87+
scrolling if not,
88+
going up the ancestry chain if it cannot scroll,
89+
until it has either moved focus,
90+
scrolled,
91+
or reached the root.
92+
93+
Additionally, when the user has focused a <a>scroll container</a> which contains focusable elements,
94+
the user may move the focus to the nested elements by pressing <code class=key>Enter</code>.
95+
96+
The User Agent will then follow a similar logic: first, search for visible and focusable items
97+
within the currently focused <a>scroll container</a>,
98+
and if there is any,
99+
select the best one and move the focus there.
100+
101+
At key points during this search for the appropriate response to the spatial navigation request,
102+
the User Agent will fires events.
103+
These enable authors to prevent the upcoming action
104+
(by calling `preventDefault()`),
105+
and if desired to provide an alternate action,
106+
such as using calling the `focus()` method on a different
107+
element of the author's choosing.
17108

18-
## Establishing focus navigation containers
19-
- If the proposed property below is applied to the element, the local logical grouping is created with the DOM subtree rooted at the element.
20-
```css
21-
// CSS property
22-
spatnav-container: auto | create
23-
```
24-
- auto: If the element is either the document element of a browsing context’s document (not limited to the top-level browsing context) or a scroll container then it establishes a spatial navigation focus container, otherwise it does not.
25-
- create: The element establishes a spatial navigation focus container.
26-
27109
## Overriding methods on top of the heuristic algorithm
28-
Developers can customize the spatial navigation with CSS properties by overriding the heuristic spatial navigation.
110+
Developers may want to customize the spatial navigation with CSS properties by overriding the heuristic spatial navigation.
111+
112+
### Approach proposed by the current specification
113+
114+
Following the principles of the [The Extensible Web Manifesto](https://github.com/extensibleweb/manifesto),
115+
the specification exposes Javascript APIs and Events that enable authors to interact with, and if necessary, override the behavior of spatial navigation.
116+
117+
### Current Approach of the CSS Basic User Interface Module Level 4
118+
119+
CSS Basic User Interface Module Level 4 offers 3 properties that can override the spatial navigation heuristic.
120+
This is currently not integrated with the present draft, but that could easily be done. They could also be implemented as a polyfil on top of the Javascript APIs and Events offered by the spatnav specification.
29121

30-
### Current Approach
31122
There were the properties about the directional focus navigation in the CSS Basic User Interface Module Level 4.
32123
- [nav-up/right/down/left properties (CSSUI4)](https://drafts.csswg.org/css-ui-4/#nav-dir)
33124
```css
@@ -46,8 +137,15 @@ nav-up: auto | <id> [ current | root | <target-name> ]?
46137
- E.g. could we instead make the properties define local spatial navigation (e.g. between components) while allowing components to determine navigation behavior inside of themselves?
47138

48139

49-
### Proposal
50-
The following properties are proposed to provide ways for customization of the spatial navigation.
140+
### Other suggested extensions
141+
The following properties have been suggested to provide ways for customization of the spatial navigation.
142+
The current specification does not integrate them.
143+
We prefer focusing on the base functionality for the moment,
144+
offering author the ability to add their own behavior via Javascript APIs.
145+
146+
If experience shows that authors often use the javacript APIs to create solutions
147+
similar to the features described below,
148+
they could be considered for standardization in a later stage.
51149

52150
#### `nav-rule` property (CSSUI4)
53151
- This property can customize the spatial navigation of the group of elements in response to pressing the arrow keys.
@@ -102,9 +200,83 @@ nav-loop: auto | no-repeat | repeat
102200
- Let the element A is the first child node, and the element Z is the last child node in the DOM subtree rooted at E.
103201
- If the currently focused element is Z and there is an input from the :arrow_down: (down-arrow key), the focus is moved to A.
104202

203+
## FAQ
204+
205+
### Why is `spatial-navigation` a CSS property? Could we have an element attribute do the same thing? What's best in terms of web practices/standards?
206+
207+
CSS is 99% about styling and we should not be too careless about adding non-styling things to it,
208+
but the CSSWG is open to non styling things in css as long as it makes sense from a coupling point of view.
209+
`-webkit-user-modify` was an example of something that didn't belong in CSS,
210+
because it is arguably part of the document's semantics,
211+
and would never do anything useful anyway without some JS.
212+
213+
For activating spatnav, our logic is that it isn't semantic,
214+
and is useful even in the absence of JS,
215+
so CSS is the most practical place to put it in:
216+
217+
* Spatnav isn't about the semantics of the marup
218+
* With markup alone, you do not know if spatnav is going to be appropriate for the document/app or not. You need to consider the layout and the JS application logic to figure out if spatnav is more likely to help or to clash with the way the layout is built, with event handlers, animations, and what have you. So that leaves us with two choices: put it in JS, or put it in CSS.
219+
* The likelyhood that spatnav clashes with something in JS is arguably somewhat higher than the likelyhood that it would work poorly due to a weird layout, however:
220+
* There can be documents written without javascript at all that could want to turn on spatnav
221+
* Some users turn JS off, ad blockers sometimes block some JS, JS sometimes fail to load for other reasons broken for other reasons (ES6 parse error, network issue, etc), and there's not reason for that to turn off spatnav if the rest still works.
222+
* As an author if you really prefer to set it in JS, it is trivial to set css properties from js. If you would really prefer to put it in the markup, you can use the style attribute. But the opposite isn't true, and you cannot set markup or JS things from CSS.
223+
224+
### Why do we need a `focus-container` property? Is it not enough to placing the focusables next to each other to create a group? What use cases do you see for focus-container?
225+
226+
First, we needed to define a container concept anyway (the blink implementation uses "ScrollableArea or Document"),
227+
to define the rest of the logic.
228+
Then, based on that, pretty much nothing changes in the specification
229+
if we allow users to turn other elements into containers as well,
230+
so we thought it was an easy addition.
231+
It could be removed for now,
232+
as it would be easy to add back later without breaking compatibility,
233+
but was included because we think there is a justification / use case:
234+
235+
Take for example something like a TV program schedule, or a calendar:
236+
it will have a grid of elements representing TV shows or calendar entries,
237+
and some UI buttons around it.
238+
Here's an simplified demo:
239+
http://output.jsbin.com/cuyasob
240+
241+
In this case, the grid is quite sparse,
242+
so if you try to move down from "Foo",
243+
you will end up on "Next Week",
244+
as it is objectively closer in the down direction.
245+
Same for going down from "Bar" and ending up on "Previous Week".
246+
247+
This may be ok,
248+
but quite possibly the author wants to provide a different UX,
249+
where once you are inside the program grid, you mostly want to move inside the grid
250+
(because you are navigating your calendar, so things around it don't matter as much).
251+
If you turn `focus-container: create` on the table, you get that.
252+
You can still escape it,
253+
for example by going right from "Foo".
254+
Since there is nothing in the grid that is to the right,
255+
you'll go to "Next week",
256+
but if you go down from "Foo" there is something inside the grid,
257+
so it will go there without considering things that are outside.
258+
259+
You could achieve the same effect by wrapping the table in a div
260+
and using the overflow property on the div to make it scrollable,
261+
but that has side effects you probably do not want.
262+
263+
### Maybe authors could create "spatnav containers" with JavaScript instead? They could listen for spat nav events to cancel (=preventDefault) the navigation? Such an event could give authors even more freedom: they might wanna grab the event and manually put focus somewhere else (to override the spatnav's default choice). Such event would allow authors to "patch" the default algorithm in a more flexible way?
264+
265+
Yes, they absolutely could.
266+
We have prepared the spec with an event model that lets js authors take control,
267+
and override the default spatnav algo to do anything they like.
268+
That could indeed be used to manually create spatial navigation containers other than documents or scrollers.
269+
270+
We had various idea for other controls to influence what gets the focus,
271+
(e.g. looping when you reach an edge, picking a different heuristic...),
272+
and we decided to leave these out because they could indeed be left to JS
273+
and be added later with declarative syntax if there was strong demand.
274+
275+
However, we still included this property, because:
276+
1. This is trivial to add to the spec (and presumably, to implementations as well), since the concept of looking for a container and searching for focusable things inside it is built-in into the spatnav logic, and we're merely exposing a hook to add additional containers
277+
2. Recreating that logic in JS if you're fine with everything else could be quite fiddly
278+
3. It seems like a fairly basic need
279+
105280
## Demo
106281
- [Calendar App using the proposed spatial navigation features](https://wicg.github.io/spatial-navigation/demo/)
107282
- [Test cases for the heuristic spatial navigation](https://wicg.github.io/spatial-navigation/demo/heuristic/heuristic_testcases)
108-
109-
## Future work
110-
Solving unreachability, saving last focus, group concept, aligning with scrolling, pointer/key mode selection

images/navnotarget-example-2.png

9.22 KB
Loading

images/navnotarget-example.png

9.09 KB
Loading

images/scroll-spatnav1.png

8.88 KB
Loading

images/scroll-spatnav2.png

8.93 KB
Loading

images/scroll-spatnav3.png

7.66 KB
Loading

images/scroll-spatnav4.png

9.13 KB
Loading

images/spatnav-enable.png

15.8 KB
Loading

0 commit comments

Comments
 (0)