-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[css-scroll-snap] Adopt focused, targeted, block priority order
As agreed to in a recent spec issue[1], when re-snapping after a layout change, if it is not possible to follow the selected targets in both axes, we should select an axis to follow. Priority should be given among axes according to: 1. the axis with a focused area, if any, 2. the axis with a targeted [2] area, if any, 3. the block axis. [1]w3c/csswg-drafts#9622 (comment) [2]https://drafts.csswg.org/selectors/#the-target-pseudo Bug: 329250094 Change-Id: Idef6ddbbe0f613ec32f220c89848ea809fd10922 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5444525 Reviewed-by: Steve Kobes <[email protected]> Commit-Queue: David Awogbemila <[email protected]> Cr-Commit-Position: refs/heads/main@{#1286690}
- Loading branch information
1 parent
b0c7328
commit 8905c6f
Showing
2 changed files
with
172 additions
and
0 deletions.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
css/css-scroll-snap/snap-after-relayout/layout-follows-focused-targeted-block-iframe.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<body> | ||
<style> | ||
.scroller { | ||
width: 200px; | ||
height: 200px; | ||
border: solid 1px black; | ||
overflow: scroll; | ||
scroll-snap-type: both mandatory; | ||
position: relative; | ||
resize: both; | ||
} | ||
.target { | ||
scroll-snap-align: start; | ||
width: 50px; | ||
height: 50px; | ||
background-color: green; | ||
position: absolute; | ||
} | ||
.target:target { | ||
background-color: blue; | ||
} | ||
.target:focus { | ||
background-color: yellow; | ||
} | ||
#box1 { | ||
left: 150px; | ||
top: 0px; | ||
} | ||
#box2 { | ||
left: 0px; | ||
top: 150px; | ||
} | ||
.space { | ||
width: 500%; | ||
height: 500%; | ||
position: absolute; | ||
} | ||
</style> | ||
<div class="scroller" id="scroller"> | ||
<div tabindex="1" id="box1" class="target">Box 1</div> | ||
<div tabindex="1" id="box2" class="target">Box 2</div> | ||
<div class="space"></div> | ||
</div> | ||
</body> | ||
|
||
</html> |
124 changes: 124 additions & 0 deletions
124
css/css-scroll-snap/snap-after-relayout/layout-follows-focused-targeted-block.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<link rel="help" href="https://drafts.csswg.org/css-scroll-snap" /> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/dom/events/scrolling/scroll_support.js"></script> | ||
</head> | ||
<body> | ||
<style> | ||
iframe { | ||
width: 1000px; | ||
height: 1000px; | ||
} | ||
</style> | ||
<script> | ||
let scroller; | ||
let box1; | ||
let box2; | ||
let frame; | ||
|
||
const iframe_load_promise = new Promise((resolve) => { | ||
frame = document.createElement("iframe"); | ||
frame.onload = async () => { | ||
scroller = frame.contentDocument.getElementById("scroller"); | ||
box1 = frame.contentDocument.getElementById("box1"); | ||
box2 = frame.contentDocument.getElementById("box2"); | ||
resolve(); | ||
}; | ||
frame.src = "./layout-follows-focused-targeted-block-iframe.html#box2"; | ||
document.body.appendChild(frame); | ||
}); | ||
|
||
const displacement = 150; | ||
async function test_resnap(t, target) { | ||
// Save box1's position and setup the cleanup. | ||
const box1_left = box1.style.left; | ||
t.add_cleanup(async () => { | ||
// Reset box1's position. | ||
box1.style.left = box1_left; | ||
// Reset scroller's writing-mode. | ||
scroller.style.writingMode = "horizontal-tb"; | ||
// Reset scroll position. | ||
await waitForScrollReset(t, scroller); | ||
}); | ||
|
||
assert_equals(scroller.scrollTop, 0, "scroll top is reset"); | ||
assert_equals(scroller.scrollLeft, 0, "scroll left is reset"); | ||
|
||
// Move box1 outside the scrollport by translating it 150px | ||
// horizontally. | ||
const new_left = box1.offsetLeft + displacement; | ||
box1.style.left = `${new_left}px`; | ||
|
||
assert_equals(scroller.scrollLeft, target.offsetLeft, | ||
`scroller followed ${target.id} in x axis`); | ||
|
||
assert_equals(scroller.scrollTop, target.offsetTop, | ||
`scroller followed ${target.id} in y axis`); | ||
} | ||
|
||
promise_test(async (t) => { | ||
await iframe_load_promise; | ||
|
||
box1.focus(); | ||
assert_equals(frame.contentDocument.activeElement, box1, | ||
"sanity check that box1 is focused."); | ||
assert_equals(frame.contentDocument.querySelector(":target"), box2, | ||
"sanity check that box2 is targeted."); | ||
// box2 is targeted but box1 is focused, so box1 should be | ||
// followed. | ||
await test_resnap(t, box1); | ||
|
||
// Remove focus from box1. | ||
scroller.focus(); | ||
}, "focused area prefered over targeted area."); | ||
|
||
promise_test(async (t) => { | ||
await iframe_load_promise; | ||
|
||
assert_not_equals(frame.contentDocument.activeElement, box1, | ||
"sanity check that box1 is not focused."); | ||
assert_equals(frame.contentDocument.querySelector(":target"), box2, | ||
"sanity check that box2 is targeted."); | ||
// box2 is targeted and box1 is not focused, so box2 should be | ||
// followed. | ||
await test_resnap(t, box2); | ||
}, "targeted area prefered over non-focused area."); | ||
|
||
promise_test(async (t) => { | ||
await iframe_load_promise; | ||
|
||
// Clear the targeted element. | ||
frame.contentDocument.location.hash = ""; | ||
assert_equals(frame.contentDocument.querySelector(":target"), null, | ||
"sanity check that no box is targeted."); | ||
assert_not_equals(frame.contentDocument.activeElement, box1, | ||
"sanity check that box1 is not focused."); | ||
|
||
// Neither box is targeted or focused; so, the block axis target should | ||
// be followed. | ||
await test_resnap(t, box1); | ||
}, "block axis area is preferred."); | ||
|
||
promise_test(async (t) => { | ||
await iframe_load_promise; | ||
|
||
scroller.style.writingMode = "vertical-lr"; | ||
|
||
// Clear the targeted element. | ||
frame.contentDocument.location.hash = ""; | ||
assert_equals(frame.contentDocument.querySelector(":target"), null, | ||
"sanity check that no box is targeted."); | ||
assert_not_equals(frame.contentDocument.activeElement, box1, | ||
"sanity check that box1 is not focused."); | ||
|
||
// Neither box is targeted or focused; so, the block (x) axis target | ||
// should be followed. | ||
await test_resnap(t, box2); | ||
}, "block axis area is preferred (vertical writing-mode)."); | ||
</script> | ||
</body> | ||
|
||
</html> |