css 滚动Div沿着页面,停止在自身的底部(像Twitter)

lb3vh1jj  于 2023-06-25  发布在  其他
关注(0)|答案(4)|浏览(72)

bounty还有4天到期。回答此问题可获得+250声望奖励。swift nub引起更多注意这个问题:这些例子不正确。1. stackoverflow.com/questions/71821650/… 2. stackoverflow.com/questions/15228224/…

这些例子中的sticky导致div存储在顶部,而不是像twitter那样存储在底部。
我被困在某个地方了。我想做一个三栏的页面布局。中间部分是文章,右边部分是一些其他的链接和参考等等(有点长)。左边是固定的。
我的问题是;当右div到达底部时,如何阻止它移动?如果中间的div的内容更短,那么右边的div也有一个滚动条。就像Twitter一样。
我试着做一些头脑 Storm 。我想Twitter可能会为这些部分设置双重div。一个是正常的,另一个是固定的底部。所以正常的一个拉伸页面滚动,另一个粘在上面。但我不确定我是不是对的。
或者可以使用纯CSS?(我也在使用TailwindCSS
不管怎样,这里是我的想法。(或者你可以简单地看看Twitter主页提要)

这里还有一个gif;
click

mwg9r5ms

mwg9r5ms1#

我认为你可以使用一个名为sticky-sidebar的js库。

var sidebar = new StickySidebar('#sidebar', {
  containerSelector: '#main',
  innerWrapperSelector: '.sidebar__inner',
});
body {
  background: #3f87c2;
  margin: 0;
  padding: 0;
  text-align: center;
}

#main {
  display: flex;
}

#middle {
  flex-grow: 1;
  background: #4dd2ff;
}

#sidebar {
  min-height: 1000px;
  width: 200px;
  background: #4dd2ff;
  margin-left: 15px;
}

.sidebar {
  will-change: min-height;
}

.sidebar__inner {
  transform: translate(0, 0);
  /* For browsers don't support translate3d. */
  transform: translate3d(0, 0, 0);
  will-change: position, transform;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/sticky-sidebar/3.3.1/sticky-sidebar.min.js" integrity="sha512-iVhJqV0j477IrAkkzsn/tVJWXYsEqAj4PSS7AG+z1F7eD6uLKQxYBg09x13viaJ1Z5yYhlpyx0zLAUUErdHM6A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="main">
  <div id="middle">
    <div>Middle Div Content (Sooo long)</div>
    <div style="margin-top: 2400px">End of Middle Content</div>
  </div>
  <div id="sidebar" class="sidebar">
    <div class="sidebar__inner">
      <div>Right Div Content</div>
      <div style="margin-top: 900px">Right Div Content Bottom</div>
    </div>
  </div>
</div>

也许可以从头开始做这样的东西,但是这个库处理了所有的向后兼容性和性能,所以我认为它是一个很好的库。完整的文档是here

zengzsys

zengzsys2#

这里的其他解决方案有一些颠簸。这必须通过在窗口滚动上附加事件来完成。
你正在寻找的确切答案是“滚动粘边栏”。here是一个代码最少的简洁实现。
在此粘贴相关部分:

首先:

创建一个侧边栏容器和子容器 Package 器

<div class="sidebar">
  <div class="content-wrapper">
    <!-- content -->
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>
</div>

秒:

获取组件并检查滚动位置,然后设置值,如果在末尾

let sidebar = document.getElementsByClassName("sidebar")[0];
let sidebar_content = document.getElementsByClassName("content-wrapper")[0];

window.onscroll = () => {
        let scrollTop = window.scrollY; // current scroll position
        let viewportHeight = window.innerHeight; //viewport height
        let contentHeight = sidebar_content.getBoundingClientRect().height; // current content height
        let sidebarTop = sidebar.getBoundingClientRect().top + window.pageYOffset; //distance from top to sidebar
}

if(scrollTop >= contentHeight - viewportHeight + sidebarTop) {
  sidebar_content.style.transform = `translateY(-${contentHeight - viewportHeight + sidebarTop}px)`;
  sidebar_content.style.position = "fixed";
}
else {
  sidebar_content.style.transform = "";
  sidebar_content.style.position = "";
}

结果:

阅读上面的链接,因为它有更多的细节。

wljmcqd8

wljmcqd83#

我想这就是你要找的。这是一个两个parter:

1. Flexbox和位置:粘性

诀窍在于使用flexbox layout,并为侧边栏容器设置position:stickyalign-self:flex-endbottom位置(在我的示例中为20%)。这样,当你滚动时,侧边栏内容就像一个 * 相对 * 定位的元素,直到达到粘性阈值(在我的例子中,侧边栏div的bottom位置达到了20%),之后它就保持“粘性”状态。

2.滚动JavaScript

另一部分便于工具栏在用户开始向上滚动时再次 * 立即 * 向上滚动,而不是用户必须再次一路向上滚动以“取消触发”粘性位置。这需要一些JavaScript:它需要检测滚动方向的变化。如果是,则:
1.设置一个scrolling-up类来翻转align-self属性,并取消从bottom:0top:0的粘滞滚动
1.向上滚动时设置margin-bottom,向下滚动时设置margin-top。此边距是根据滚动方向改变时元素上方或下方剩余的像素量计算的。这个边距将侧边栏向下或向上“推”了一点,这取决于用户滚动的方式。这使得侧边栏在视觉上保持在原位,而上面的(参见1.)属性翻转。
虽然我不完全相信这是最好的方法,但它似乎工作得很好。如果我有更好的方法,我会更新这个答案。

Demo

请参阅下面的演示或Codepen here上的演示。
注意:我在编写演示时考虑了Stack Overflow的代码片段窗口尺寸。如果全屏运行演示,则没有足够的文本来触发滚动,效果也不会明显(尝试调整浏览器窗口的大小)。

编辑:正如damzaky所指出的,我的解决方案没有考虑到侧边栏需要在用户再次滚动时立即开始向上滚动,所以我编写并添加了JavaScript部分。

//select sidebar and create a states object for storing states
const sidebar = document.querySelector('.sidebar');
const states = {};

//listen for scroll
window.addEventListener('scroll', (e) => {
  //check scrolling direction
  let scrollUp = (states.prevY || window.scrollY) > window.scrollY;  
  //check if the direction has actually changed from the last time whe checked
  //this prevents the margin from being set on each scroll call
  
  if (states.prevState !== scrollUp) {
    //set a margin-bottom if scrolling up, or a margin-top if scrolling down
    //calculate it based on the amount of pixels above or below the sidebar
    if (scrollUp) {
      sidebar.style.marginTop = '';
      sidebar.style.marginBottom = sidebar.parentElement.scrollHeight - (sidebar.offsetTop + sidebar.getBoundingClientRect().height) + 'px';
      sidebar.classList.add('scrolling-up');
    } else {
      sidebar.classList.remove('scrolling-up');
      sidebar.style.marginBottom = '';
      sidebar.style.marginTop = sidebar.offsetTop + 'px';
    }
  }
  //store scrollposition and scrolling direction for next call
  states.prevY = window.scrollY;
  states.prevState = scrollUp;
})
div {
  display: flex;
  border: 1px solid red;
}
div.wrapper {
  position: relative; /* if you omit this, the margin calculatio will be off */
  flex-direction: row;
  width: 100vw;
}
div.wrapper .scroller {
  width: 80%;
  overflow-y: visible;
  flex-direction: column;
}
div.wrapper .sidebar {
  position: relative; /* if you omit this, the margin calculatio will be off */
  width: 20%;
  flex-direction: column;
  flex-grow: 0;
  align-self: flex-end;
  height: fit-content;
  position: sticky;
  bottom: 20%;
}
div.wrapper .sidebar.scrolling-up {
  align-self: flex-start;
  top: 0;
  bottom: auto;
}
<div class="wrapper">
  <div class="scroller">
    <h2>Main scroller</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a mattis augue. Aliquam mattis est at consequat molestie. Maecenas suscipit orci turpis, ut porttitor velit posuere ac. Integer tellus diam, condimentum ac tellus vitae, fermentum dapibus nisl. Nulla euismod pharetra maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris ut augue mi. Integer nec rhoncus lectus, sed ullamcorper tellus. Pellentesque ultrices rutrum mauris, quis sagittis metus dapibus vel. Donec at enim nunc. Praesent egestas luctus justo, sed consequat neque auctor vel. Mauris non volutpat ipsum. Sed id ligula quis nisl blandit auctor. Fusce lobortis consectetur ullamcorper.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
  </div>
  <div class="sidebar">
    <h2>Sidebar</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor viverra imperdiet. Duis rutrum mauris purus, vel ornare erat malesuada in. Vestibulum eu magna ut tortor auctor tempus. Pellentesque malesuada, nisl sit amet posuere sagittis, ex leo gravida magna, a elementum ante purus vel magna. Integer id aliquet felis. Morbi imperdiet ultrices neque, sit amet convallis enim sagittis nec.</p>

  </div>
</div>
enyaitl3

enyaitl34#

您可以在需要停止position: sticky; bottom: 0的元素中使用以下CSS代码
请参阅以下关于Stackoverflow的文章,了解更多信息How does the "position: sticky;" property work?
希望这能回答你的问题!
编辑:[试用此]

.main {
  width: 100%;
  height: 1000px;
  display: flex;
}

.first {
  width: 30%;
  background-color: red;
}

.second {
  width: 40%;
  background-color: green;
}

.third {
  width: 30%;
  background-color: blue;
  height: 500px;
  position: sticky; 
  top: 0px;
}

p {
  margin-left: 20px;
}
<div class="main">
  <div class="first">
    <p>
      Left content.
    </p>
  </div>

  <div class="second">
    <p>
      Main content.
    </p>
  </div>
  <div class="third">
    <p>
      Right content.
    </p>
  </div>
</div>

相关问题