Skip to content

Commit

Permalink
[carousel] Implement targeted scroll-marker selection for ::column
Browse files Browse the repository at this point in the history
::column pseudos[1] may create ::scroll-markers, but do not exist in the
DOM tree as parents of the elements which are flowed into them.
They also do not appear to have LayoutObjects and are not found[2]
in the layout tree. So, when searching for the appropriate scroll-marker
to select for a targeted scroll we need to consider whether the
scroll-marker-generating element (marker-generating-element) found in
the layout tree is also flowed into the same scroll-marker-generating
::column (marker-generating-column) as the target of the scrollIntoView
operation. If the target and marker-generating-element are both in
marker-generating-column, marker-generating-element is the preferred[3]
choice. The only means we have of checking whether an element is flowed
into a ::column is by looking at the rect associated with that ::column.

[1] https://drafts.csswg.org/css-multicol-2/#column-pseudo
[2] https://source.chromium.org/chromium/chromium/src/+/165f5ddad25b289f886a248ca810d075b1e7bb87:third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc;l=254-255
[3] w3c/csswg-drafts#10738 (comment)

Bug: 380062280
Change-Id: Ie2ad58c3beca13a4945325d9aa9c4aec6a5fc332
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6088285
Commit-Queue: David Awogbemila <[email protected]>
Reviewed-by: Steve Kobes <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1399198}
  • Loading branch information
David Awogbemila authored and chromium-wpt-export-bot committed Dec 20, 2024
1 parent 9bbcdbf commit 61a2d96
Show file tree
Hide file tree
Showing 8 changed files with 857 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>CSS Test: scroll tracking for ::scroll-markers whose orignatin elements cannot be scroll-aligned </title>
<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll">
</head>

<body>
<style>
.wrapper {
display: grid;
justify-content: center;
}

.carousel {
width: 800px;
height: 200px;
overflow-x: scroll;
scroll-snap-type: x mandatory;
list-style-type: none;
scroll-behavior: smooth;
border: solid 2px grey;
padding-top: 10%;
text-align: center;
counter-set: markeridx -1;
columns: 2;

& > :nth-child(odd)::scroll-marker {
content: counter(markeridx);
counter-increment: markeridx;
align-content: center;
text-align: center;
width: 35px;
height: 35px;
border-radius: 50%;
margin: 3px;
background-color: red;
}
/* item 2 is child 3 */
& > :nth-child(3)::scroll-marker {
background-color: green;
}

&>.item {
scroll-snap-align: center;
height: 80%;
width: 158px;
border: 1px solid;
place-content: center;
display: inline-block;
}

scroll-marker-group: after;

&::scroll-marker-group {
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border: solid 1px black;
border-radius: 30px;
}
}
</style>
<div class="wrapper" id="wrapper">
<div class="carousel" id="carousel">
<div class="item item0" tabindex=0>0</div>
<div class="item item1" tabindex=0>1</div>
<div class="item item2" tabindex=0>2</div>
<div class="item item3" tabindex=0>3</div>
<div class="item item4" tabindex=0>4</div>
<div class="item item5" tabindex=0>5</div>
<div class="item item6" tabindex=0>6</div>
<div class="item item7" tabindex=0>7</div>
<div class="item item8" tabindex=0>8</div>
<div class="item item9" tabindex=0>9</div>
<div class="item item10" tabindex=0>10</div>
<div class="item item11" tabindex=0>11</div>
<div class="item item12" tabindex=0>12</div>
<div class="item item13" tabindex=0>13</div>
<div class="item item14" tabindex=0>14</div>
<div class="item item15" tabindex=0>15</div>
</div>
</div>
</body>

</html>
103 changes: 103 additions & 0 deletions css/css-overflow/targeted-column-scroll-marker-selection-001.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html class="reftest-wait">

<head>
<meta charset="utf-8">
<title>CSS Test: scroll tracking for ::scroll-markers whose orignatin elements cannot be scroll-aligned </title>
<link rel="match" href="targeted-column-scroll-marker-selection-001-ref.html">
<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll">
<script src="/css/css-transitions/support/helper.js"></script>
<script src="/dom/events/scrolling/scroll_support.js"></script>
<script src="/common/reftest-wait.js"></script>
</head>

<body>
<style>
.wrapper {
display: grid;
justify-content: center;
}

.carousel {
width: 800px;
height: 200px;
overflow-x: scroll;
scroll-snap-type: x mandatory;
list-style-type: none;
scroll-behavior: smooth;
border: solid 2px grey;
padding-top: 10%;
text-align: center;
counter-set: markeridx -1;
columns: 2;

&::column::scroll-marker {
content: counter(markeridx);
counter-increment: markeridx;
align-content: center;
text-align: center;
width: 35px;
height: 35px;
border-radius: 50%;
margin: 3px;
background-color: red;
}
&::column::scroll-marker:target-current {
background-color: green;
}
&>.item {
scroll-snap-align: center;
height: 80%;
width: 158px;
border: 1px solid;
place-content: center;
display: inline-block;
}

scroll-marker-group: after;

&::scroll-marker-group {
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border: solid 1px black;
border-radius: 30px;
}
}
</style>
<div class="wrapper" id="wrapper">
<div class="carousel" id="carousel">
<div class="item item0" tabindex=0>0</div>
<div class="item item1" tabindex=0>1</div>
<div class="item item2" tabindex=0>2</div>
<div class="item item3" tabindex=0>3</div>
<div class="item item4" tabindex=0>4</div>
<div class="item item5" tabindex=0>5</div>
<div class="item item6" tabindex=0>6</div>
<div class="item item7" tabindex=0>7</div>
<div class="item item8" tabindex=0>8</div>
<div class="item item9" tabindex=0>9</div>
<div class="item item10" tabindex=0>10</div>
<div class="item item11" tabindex=0>11</div>
<div class="item item12" tabindex=0>12</div>
<div class="item item13" tabindex=0>13</div>
<div class="item item14" tabindex=0>14</div>
<div class="item item15" tabindex=0>15</div>
</div>
</div>
<script>

const items = document.querySelectorAll(".item");
function runTest() {
const item2 = items[2];
item2.scrollIntoView();
waitForAnimationFrames(2).then(() => {
takeScreenshot();
});
}
waitForCompositorReady().then(runTest);
</script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>CSS Test: scroll tracking for ::scroll-markers whose orignatin elements cannot be scroll-aligned </title>
<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll">
</head>

<body>
<style>
.wrapper {
display: grid;
justify-content: center;
}

.carousel {
width: 800px;
height: 200px;
overflow-x: scroll;
scroll-snap-type: x mandatory;
list-style-type: none;
scroll-behavior: smooth;
border: solid 2px grey;
padding-top: 10%;
text-align: center;
counter-set: markeridx -1;
columns: 2;

& > :nth-child(odd)::scroll-marker {
content: counter(markeridx);
counter-increment: markeridx;
align-content: center;
text-align: center;
width: 35px;
height: 35px;
border-radius: 50%;
margin: 3px;
background-color: red;
}
/* item 4 is child 5 */
& > :nth-child(5)::scroll-marker {
background-color: green;
}

&>.item {
scroll-snap-align: none;
height: 80%;
width: 158px;
border: 1px solid;
place-content: center;
display: inline-block;
}

/* Item 3 is child 4. Starting from scrollLeft=0, calling
box4.scrollIntoView ends up in a position that aligns box 3. */
& > :nth-child(4){
scroll-snap-align: center;
}

scroll-marker-group: after;

&::scroll-marker-group {
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border: solid 1px black;
border-radius: 30px;
}
}
</style>
<div class="wrapper" id="wrapper">
<div class="carousel" id="carousel">
<div class="item item0" tabindex=0>0</div>
<div class="item item1" tabindex=0>1</div>
<div class="item item2" tabindex=0>2</div>
<div class="item item3" tabindex=0>3</div>
<div class="item item4" tabindex=0>4</div>
<div class="item item5" tabindex=0>5</div>
<div class="item item6" tabindex=0>6</div>
<div class="item item7" tabindex=0>7</div>
<div class="item item8" tabindex=0>8</div>
<div class="item item9" tabindex=0>9</div>
<div class="item item10" tabindex=0>10</div>
<div class="item item11" tabindex=0>11</div>
<div class="item item12" tabindex=0>12</div>
<div class="item item13" tabindex=0>13</div>
<div class="item item14" tabindex=0>14</div>
<div class="item item15" tabindex=0>15</div>
</div>
</div>
</body>

</html>
103 changes: 103 additions & 0 deletions css/css-overflow/targeted-column-scroll-marker-selection-002.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html class="reftest-wait">

<head>
<meta charset="utf-8">
<title>CSS Test: scroll tracking for ::scroll-markers whose orignatin elements cannot be scroll-aligned </title>
<link rel="match" href="targeted-column-scroll-marker-selection-002-ref.html">
<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll">
<script src="/css/css-transitions/support/helper.js"></script>
<script src="/dom/events/scrolling/scroll_support.js"></script>
<script src="/common/reftest-wait.js"></script>
</head>

<body>
<style>
.wrapper {
display: grid;
justify-content: center;
}

.carousel {
width: 800px;
height: 200px;
overflow-x: scroll;
scroll-snap-type: x mandatory;
list-style-type: none;
scroll-behavior: smooth;
border: solid 2px grey;
padding-top: 10%;
text-align: center;
counter-set: markeridx -1;
columns: 2;

&::column::scroll-marker {
content: counter(markeridx);
counter-increment: markeridx;
align-content: center;
text-align: center;
width: 35px;
height: 35px;
border-radius: 50%;
margin: 3px;
background-color: red;
}
&::column::scroll-marker:target-current {
background-color: green;
}

&>.item {
scroll-snap-align: center;
height: 80%;
width: 158px;
border: 1px solid;
place-content: center;
display: inline-block;
}

scroll-marker-group: after;

&::scroll-marker-group {
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border: solid 1px black;
border-radius: 30px;
}
}
</style>
<div class="wrapper" id="wrapper">
<div class="carousel" id="carousel">
<div class="item item0" tabindex=0>0</div>
<div class="item item1" tabindex=0>1</div>
<div class="item item2" tabindex=0>2</div>
<div class="item item3" tabindex=0>3</div>
<div class="item item4" tabindex=0>4</div>
<div class="item item5" tabindex=0>5</div>
<div class="item item6" tabindex=0>6</div>
<div class="item item7" tabindex=0>7</div>
<div class="item item8" tabindex=0>8</div>
<div class="item item9" tabindex=0>9</div>
<div class="item item10" tabindex=0>10</div>
<div class="item item11" tabindex=0>11</div>
<div class="item item12" tabindex=0>12</div>
<div class="item item13" tabindex=0>13</div>
<div class="item item14" tabindex=0>14</div>
<div class="item item15" tabindex=0>15</div>
</div>
</div>
<script>

const carousel = document.getElementById("carousel");
const items = document.querySelectorAll(".item");
function runTest() {
const item4 = items[4];
item4.scrollIntoView();
carousel.onscrollend = () => { takeScreenshot(); };
}
waitForCompositorReady().then(runTest);
</script>
</body>

</html>
Loading

0 comments on commit 61a2d96

Please sign in to comment.