I'm trying to have a web page scroll and snap to beginning of some elements as the user scrolls through a webpage using scroll-snap-type: y mandatory
and scroll-snap-align: start
. My problem is that it's a large webpage and unlike many samples where the whole page is just a div and children, I've got many divs and children. If I restrict my divs' direct container to have 100vh the scroll snapping works but there is double scrollable content problem: the document scrolls and the inner div's snapping content scrolls independently of the whole document. If I don't restrict the direct parent's height then snapping doesn't work.
Here is an example: https://codepen.io/canp/pen/abGJKXX
Basically the example in the above link does snap but there is the double scroll problem. I want the outer
class div the only scrolling component, while still snapping to mid
's children page
divs without double scrollbars.
How can I make document scrolling to snap to a grand-grandchild's start position?
It is not entirely clear what your detailed objective is, but the code provided below satisfies the following requirements:
The CSS is straight out of the box from https://www.w3.org/TR/css-scroll-snap/, so should work universally in any browser that supports snapping.
The thing to do is to have no (other) scrolling defined between the level you have the scroll container at and the elements you want to snap.
/* Single scroll level with arbitrary decendent depth all snapping to the one scroll level */
.outer {
overflow-y: auto;
scroll-snap-type: y mandatory;
scroll-padding-top: 5vh;
height: 100vh;
}
.page {
height: 100vh;
scroll-snap-align: start;
}
/* For this example get rid of typical extra spacing which will impact the size of the available view */
body {
margin: 0px;
}
/* Make pages stand out, and advise what generation they are. */
.outer > div.page {
background: red;
}
.outer > div.page > p::after {
content: ': A child of the outer div has a red background.';
}
.outer > div > div.page {
background: orange;
}
.outer > div > div.page > p::after {
content: ': A grand child of the outer div has an orange background.';
}
.outer > div > div > div.page {
background: yellow;
}
.outer > div > div > div.page > p::after {
content: ': A great grand child of the outer div has an yellow background.';
}
.outer > div > div > div > div.page {
background: green;
}
.outer > div > div > div > div.page > p::after {
content: ': A great great grand child of the outer div has a green background.';
}
.outer > div > div > div > div > div.page {
background: blue;
color: white;
}
.outer > div > div > div > div > div.page > p::after {
content: ': A great great great grand child of the outer div has a blue background and white text.';
}
<div class="outer">
<div class="page">
<p>Page 0</p>
</div>
<div>
<div class="page">
<p>Page 1</p>
</div>
<div>
<div class="page">
<p>Page 2</p>
</div>
</div>
<div class="page">
<p>Page 3</p>
</div>
<div>
<div>
<div class="page">
<p>Page 4</p>
</div>
</div>
<div class="page">
<p>Page 5</p>
</div>
</div>
<div>
<div>
<div>
<div class="page">
<p>Page 6</p>
</div>
</div>
</div>
<div class="page">
<p>Page 7</p>
</div>
</div>
</div>
<div class="page">
<p>Page 8</p>
</div>
</div>