简体   繁体   中英

How can I scroll to an element with sticky positioning?

I have the following code and I want to use ids to switch between slides, but with an id it doesn't work and als with JS scrollTo, scrollIntoView and other variations. It works on the way down but not up.

I try to make a website which overlaps with itself and creates a nice progressive flow for surveys. It should also be able to move to a previous slide, so you can enter or change some answer in such a survey.

I hope you can help me and maybe see something which i didn't see.

 // set color for each slide window.onload = function() { let slides = [...document.getElementsByClassName("slide")]; for(let n in slides) { let slide = slides[n]; slide.style.backgroundColor = "hsl("+((360 / slides.length) * n)+", 100%, 25%)"; } }
 body { font-size: 3vw; margin: 0; padding: 0; position: relative; } #ref { background-color: black; position: fixed; top: 0; z-index: 1000; } #ref a { color: white; text-decoration: none; }.slide { background-color: #404050; border: 1px solid white; color: white; height: calc(100vh - 2px); left: 0; position: sticky; top: 0; width: calc(100vw - 2px); }
 <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <div id="ref"> <a href="#s1">S1</a> <a href="#s2">S2</a> <a href="#s3">S3</a> <a href="#s4">S4</a> <a href="#s5">S5</a> <a href="#s6">S6</a> <a href="#s7">S7</a> <a href="#s8">S8</a> <a href="#s9">S9</a> </div> <div id="s1" class="slide"> <h1>Slide 1</h1> </div> <div id="s2" class="slide"> <h1>Slide 2</h1> </div> <div id="s3" class="slide"> <h1>Slide 3</h1> </div> <div id="s4" class="slide"> <h1>Slide 4</h1> </div> <div id="s5" class="slide"> <h1>Slide 5</h1> </div> <div id="s6" class="slide"> <h1>Slide 6</h1> </div> <div id="s7" class="slide"> <h1>Slide 7</h1> </div> <div id="s8" class="slide"> <h1>Slide 8</h1> </div> <div id="s9" class="slide"> <h1>Slide 9</h1> </div> </body> </html>

Absolutely loved the implentation. Such small css and so powerful effect.

But seems like Browser don't do the # magic with sticky elements. Although this could have been solved with JS, but thought of having a HTML-CSS solution to it by a little tweak in the HTML (adding an extra static element for # reference). Hope you like the solution.

 // set color for each slide window.onload = function() { let slides = [...document.getElementsByClassName("slide")]; for(let n in slides) { let slide = slides[n]; slide.style.backgroundColor = "hsl("+((360 / slides.length) * n)+", 100%, 25%)"; } }
 body { font-size: 3vw; margin: 0; padding: 0; position: relative; } #ref { background-color: black; position: fixed; top: 0; z-index: 1000; } #ref a { color: white; text-decoration: none; }.slide { background-color: #404050; border: 1px solid white; color: white; height: calc(100vh - 2px); left: 0; position: sticky; top: 0; width: calc(100vw - 2px); }
 <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <div id="ref"> <a href="#s1">S1</a> <a href="#s2">S2</a> <a href="#s3">S3</a> <a href="#s4">S4</a> <a href="#s5">S5</a> <a href="#s6">S6</a> <a href="#s7">S7</a> <a href="#s8">S8</a> <a href="#s9">S9</a> </div> <div id="s1"> </div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 1</h1> </div> <div id="s2"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 2</h1> </div> <div id="s3"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 3</h1> </div> <div id="s4"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 4</h1> </div> <div id="s5"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 5</h1> </div> <div id="s6"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 6</h1> </div> <div id="s7"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 7</h1> </div> <div id="s8"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 8</h1> </div> <div id="s9"></div><!--Extra static element for # reference--> <div class="slide"> <h1>Slide 9</h1> </div> </body> </html>

After trying a long time I found a solution but it is very specific.

You need to have a parent element which only includes the slides (in this case it is main ), then you need to give the parent element a height and an overflow auto.

After those steps add the javascript, which gets the selected element and its parent (here again main ), then calculates the average height per element, after that it gets the index of the elem relative to the parent and multiplies it with the height to get the scrollOffset, which is in the last step set for the parent.

 // set color for each slide window.onload = function() { let slides = [...document.getElementsByClassName("slide")]; for(let n in slides) { let slide = slides[n]; slide.style.backgroundColor = "hsl("+((360 / slides.length) * n)+", 100%, 25%)"; } } window.onhashchange = function() { let hash = document.body.querySelector(location.hash); let parent = hash.parentElement; let scrollOffset = parent.scrollHeight / parent.childElementCount; scrollOffset *= Array.prototype.indexOf.call(parent.children, hash); parent.scrollTop = scrollOffset; }
 body { font-size: 3vw; margin: 0; padding: 0; position: relative; } #ref { background-color: black; position: fixed; top: 0; z-index: 1000; } #ref a { color: white; text-decoration: none; } main { height: 100vh; overflow: auto; }.slide { background-color: #404050; border: 1px solid white; color: white; height: calc(100vh - 2px); left: 0; position: sticky; top: 0; width: calc(100vw - 2px); }
 <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <div id="ref"> <a href="#s1">S1</a> <a href="#s2">S2</a> <a href="#s3">S3</a> <a href="#s4">S4</a> <a href="#s5">S5</a> <a href="#s6">S6</a> <a href="#s7">S7</a> <a href="#s8">S8</a> <a href="#s9">S9</a> </div> <main> <div id="s1" class="slide"> <h1>Slide 1</h1> </div> <div id="s2" class="slide"> <h1>Slide 2</h1> </div> <div id="s3" class="slide"> <h1>Slide 3</h1> </div> <div id="s4" class="slide"> <h1>Slide 4</h1> </div> <div id="s5" class="slide"> <h1>Slide 5</h1> </div> <div id="s6" class="slide"> <h1>Slide 6</h1> </div> <div id="s7" class="slide"> <h1>Slide 7</h1> </div> <div id="s8" class="slide"> <h1>Slide 8</h1> </div> <div id="s9" class="slide"> <h1>Slide 9</h1> </div> </main> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM