问题描述
当元素 position:sticky
被卡住并且比视口长时,只能在滚动到容器底部后才能看到其内容。
When element with position: sticky
is "stuck" and is longer than viewport, you can only see its content after you scroll to the bottom of container.
如果卡住元素与文档一起滚动并且一旦到达其下边缘就停止,那将会很酷。如果用户向后滚动,同样的事情会再次发生,但反之亦然。
It would be cool, if the "stuck" element scrolled with the document and stopped, once it reaches its bottom edge. If user scrolled back, the same thing would happen again, but in reverse.
TLDR;有一个图书馆()可以完成我正在寻找的工作,但在新版本中表现不佳异步滚动。
TLDR; There is a library (StickyKit) that does what I'm looking for, but performs badly with new async scrolling.
JSFiddle with StickyKit - - (这就是我所描述的,但表现不佳,见下文)
JSFiddle with StickyKit - https://jsfiddle.net/cibulka/4nd3b0tt/ - (this does what I'm describing, but performs poorly, see below)
JSFiddle 原生 位置:粘性
- - - (这不)
JSFiddle with native position: sticky
- https://jsfiddle.net/cibulka/np6afe9c/1/ - https://jsfiddle.net/cibulka/pxz6e0qv/ - (this does not)
很长一段时间,我是StickyKit的快乐用户。不幸的是,它与
I've created an issue in StickyKit Github, but package seems to be abandonned by the author: https://github.com/leafo/sticky-kit/issues/252
因此,我不得不弃用StickyKit并转移到本机位置:粘性
(使用进行填充。不幸的是有一些事情 position:sticky
不能做,这就是其中之一。
Because of that, I am forced to deprecate StickyKit and move to native position:sticky
(polyfilled with StickyFill). Unfortunately there is a couple of things position:sticky
can't do and this is one of them.
那里也是我在位置的另一个问题:粘性
:
推荐,基本上,如何解决这个问题。我正在使用不同的JS / jQuery库,编写我自己的代码或者使用一些古怪的CSS hack来破解 position:sticky
的功能。
A recommendation, basically, how to approach this issue. I'm up for using different JS/jQuery library, writing my own code or use some quirky CSS hack to hack position:sticky
functionality.
推荐答案
我已经接受了jnns的回答并对其进行了更新,以便在像粘贴套件这样的滚动之间保持平滑。唯一的问题是它需要一个包含div s.t的幻数。容器保持它的大小而div是绝对定位的 - 这可以通过css变量在你的代码中解决。
I've taken jnns answer and updated it so that it is smooth between scrolls like sticky kit may have been. The only issue is that it required a magic number for a containing div s.t. the container maintains it's size while the div is absolutely positioned - this might be solved in your code by a css variable.
window.onscroll = function (e) {
if (window.scrollY < this.prevScrollY) {
// Track position state of nav
// 1 == stuck to top
// 0 == absolute positioning
// -1 == stuck to bottom
this.stick_pos = scrollUpwards(this.stick_pos);
} else {
this.stick_pos = scrollDownwards(this.stick_pos);
}
this.prevScrollY = window.scrollY;
}
function scrollUpwards(stick_pos) {
// If the element is already stuck to the top then we are fine
if(stick_pos === 1) return stick_pos;
// Figure out where the new window will be after scroll
let aside = $("aside").get(0);
let aboveAside = aside.getBoundingClientRect().top > 0;
// If we are going above the element then we know we must stick
// it to the top
if (aboveAside){
$("aside").css("position", "sticky")
.css("top", 0)
.css("bottom", '')
.css("align-self", "flex-start");
return 1;
}
// If it will still be below the top of the element, then we
// must absolutely position it to its current position - if it already is absolutely positioned then we do nothing
if (stick_pos == 0) return stick_pos;
// Undo the stick to the bottom
// First get the current position
$("aside")
.css("top", aside.offsetTop)
.css("position", "absolute")
.css("bottom", '')
.css("align-self", "");
return 0;
}
function scrollDownwards(stick_pos) {
/*
let aside = $("aside").get(0);
let aboveAside = aside.offsetTop >= window.scrollY;
let browser_bottom = window.scrollY + window.innerHeight;
let aside_bottom = aside.offsetTop + aside.offsetHeight;
let belowAside = browser_bottom >= aside_bottom;
if (aboveAside) {
//console.log("stick to bottom");
$("aside").css("top", '');
$("aside").css("bottom", 0);
$("aside").css("align-self", "flex-end");
}
*/
// If the element is already stuck to the bottom then we are fine
if(stick_pos === -1) return stick_pos;
// Figure out where the new window will be after scroll
let aside = $("aside").get(0);
let browser_bottom = window.innerHeight;
let aside_bottom = aside.getBoundingClientRect().top + aside.offsetHeight;
let belowAside = browser_bottom > aside_bottom;
// If we are going below the element then we know we must stick
// it to the bottom.
if (belowAside){
$("aside").css("position", "sticky")
.css("top", '')
.css("bottom", 0)
.css("align-self", "flex-end");
return -1;
}
// If it will still be above the bottom of the element, then we
// must absolutely position it to its current position - if it already is absolutely positioned then we do nothing
if (stick_pos == 0) return stick_pos;
// Undo the stick to the top
// First get the current position
// $("aside").css("position", "absolute")
// .css("top", aside.offsetTop);
$("aside")
.css("top", aside.offsetTop)
.css("position", "absolute")
.css("bottom", '')
.css("align-self", "");
return 0;
}
div#section {
/* begin: irrelevant styling */
margin: 5em auto;
padding: 0.625rem;
max-width: 300px;
font-family: sans-serif;
font-size: 18px;
line-height: 1.5em;
text-align: justify;
background-color: #dbe4ee;
/* end: irrelevant styling */
display: flex;
justify-content: space-around;
}
div#section div#nav-container {
position: relative;
display: flex;
min-width: 2em;
}
div#section div#nav-container aside {
position: sticky;
align-self: flex-start;
/* begin: irrelevant styling */
background-color: #81a4cd;
color: white;
text-align: center;
width: 2em;
}
div#section div#nav-container aside div {
padding: 0 .3em;
}
div#section article {
margin-left: 0.5em;
}
div#section article p {
margin: 0;
}
div#section article p + p {
margin-top: 1.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='section'>
<div id='nav-container'>
<aside>
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
<div>H</div>
<div>I</div>
<div>J</div>
<div>K</div>
<div>L</div>
<div>M</div>
<div>N</div>
<div>O</div>
<div>P</div>
<div>Q</div>
<div>R</div>
<div>S</div>
<div>T</div>
<div>U</div>
<div>V</div>
<div>W</div>
<div>X</div>
<div>Y</div>
<div>Z</div>
</aside>
</div>
<article>
<p>Perferendis ut iusto voluptatem ex temporibus aut autem amet. Sit vero in soluta. Est officia asperiores tenetur vel quam nostrum eum facere. Sed totam quasi libero at facilis doloremque. Non aut velit odio. Tempora dolore sunt recusandae sed quia
sunt.</p>
<p>Voluptatem optio asperiores dolorem voluptatem. Ipsa alias perspiciatis doloribus est nisi ut. Fuga aut et vitae consequatur dolor corrupti aut minima.</p>
<p>Facilis et ut eligendi. Excepturi labore asperiores vero. Perferendis porro sunt molestiae. In sit dolorem eum esse sit inventore est. Atque perspiciatis commodi nihil.</p>
<p>Consequatur ipsa id repellendus voluptatem perspiciatis temporibus. Praesentium eveniet nemo laudantium inventore similique impedit nihil esse. Maiores iste commodi molestiae quas odit nihil ex corrupti. Illum id amet non vero.</p>
<p>Voluptas soluta itaque et. Aperiam quasi sint eos ullam. Assumenda facilis omnis alias numquam. Odio quia esse vel et minima soluta architecto. Qui saepe consequatur aut rerum. Et et aut voluptatibus inventore.</p>
<p>Perferendis ut iusto voluptatem ex temporibus aut autem amet. Sit vero in soluta. Est officia asperiores tenetur vel quam nostrum eum facere. Sed totam quasi libero at facilis doloremque. Non aut velit odio. Tempora dolore sunt recusandae sed quia sunt.</p>
<p>Voluptatem optio asperiores dolorem voluptatem. Ipsa alias perspiciatis doloribus est nisi ut. Fuga aut et vitae consequatur dolor corrupti aut minima.</p>
<p>Facilis et ut eligendi. Excepturi labore asperiores vero. Perferendis porro sunt molestiae. In sit dolorem eum esse sit inventore est. Atque perspiciatis commodi nihil.</p>
<p>Consequatur ipsa id repellendus voluptatem perspiciatis temporibus. Praesentium eveniet nemo laudantium inventore similique impedit nihil esse. Maiores iste commodi molestiae quas odit nihil ex corrupti. Illum id amet non vero.</p>
<p>Voluptas soluta itaque et. Aperiam quasi sint eos ullam. Assumenda facilis omnis alias numquam. Odio quia esse vel et minima soluta architecto. Qui saepe consequatur aut rerum. Et et aut voluptatibus inventore.</p>
</div>
这篇关于粘贴位置:可滚动,比视口长的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!