简体   繁体   English

如何在使用jQuery在页眉和页脚之间滚动时使侧边栏变粘(不滚动它们)?

[英]How to make a sidebar sticky when scrolling between header and footer with jQuery (without scrolling over them)?

I need a strictly jQuery solution for this problem. 我需要一个严格的jQuery解决方案来解决这个问题。 This is because I'm using Wordpress and the sidebar widget that I want to make sticky is inside an <aside> element which I cannot make full height. 这是因为我正在使用Wordpress,而我想制作粘贴的侧边栏小部件位于<aside>元素内,我无法使其达到全高。

In the same way that .scrollTop() detects how far down the page I am to make the sidebar widget sticky I need JS detect how far up I am from the bottom of the page to "unstick" the widget via assigning a new fixed position. 就像.scrollTop()检测页面向下移动侧边栏小部件的距离一样,我需要JS检测我从页面底部到目前为止通过分配新的固定位置来“取消”小部件。

I tried to to this with .offset() but I have been unable to make it work so far. 我尝试使用.offset()进行此操作,但到目前为止我还无法使其工作。

  function stopDiv() {
    var distance = $('.footer').offset().top - $('.widget').offset().top;
    if (distance < 10) {
      $('.widget').css({
        'top': 'auto',
        'bottom': '10px'
      });
    }
  }

As you can see in the snippet below my sidebar scrolls as it should, but I want the sidebar to assume a new fixed position when I reach <10px distance from the footer. 你可以在我的侧栏下方的片段中看到它应该滚动,但我希望侧边栏在距离页脚距离<10px时采用新的固定位置。

I want the sidebar to assume a new fixed position above the footer until the user scrolls back up. 我希望侧边栏在页脚上方采用新的固定位置,直到用户向上滚动。

Edit: The solution suggested below by @Benvc works fine in the snippet, but not on my wordpress site. 编辑: @Benvc下面建议的解决方案在片段中工作正常,但在我的wordpress网站上没有。 Here are the console errors I'm getting: 以下是我得到的控制台错误:

scripts.js:18 Uncaught ReferenceError: s is not defined
    at HTMLDocument.<anonymous> (scripts.js:18)
    at i (jquery.js:2)
    at Object.fireWith [as resolveWith] (jquery.js:2)
    at Function.ready (jquery.js:2)
    at HTMLDocument.K (jquery.js:2)
    at HTMLDocument.s (VM11874 rocket-loader.min.js:1)
    at p (VM11874 rocket-loader.min.js:1)
    at t.simulateStateAfterDeferScriptsActivation (VM11874 rocket-loader.min.js:1)
    at Object.callback (VM11874 rocket-loader.min.js:1)
    at t.run (VM11874 rocket-loader.min.js:1)

  // Fixed Widget function fixDiv() { var $cache = $('.widget'); if ($(window).scrollTop() > 380) $cache.css({ 'position': 'fixed', 'top': '10px', 'right': '30px' }); else $cache.css({ 'position': 'relative', 'top': 'auto', 'right': 'auto' }); } $(window).scroll(fixDiv); fixDiv(); /* My attempt function stopDiv() { var distance = $('.footer').offset().top - $('.widget').offset().top; if (distance < 10) { $('.widget').css({ 'top': 'auto', 'bottom': '10px' }); } } $(window).scroll(stopDiv); stopDiv(); */ 
 @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700'); * { font-family: 'Open Sans'; color: #fff; box-sizing: content-box; } body { padding: 0; margin: 0; } p { margin: 20px; } hr { width: 85%; border-style: solid; } .main-content { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: 150px auto; grid-template-areas: "nav nav nav nav" "main main main sidebar"; grid-column-gap: 20px; grid-row-gap: 0px; } .nav { grid-area: nav; background-color: #266392; display: grid; grid-template-columns: 1fr 3fr 1fr; } .nav h1 { place-self: center; font-weight: 400; font-size: 40px; grid-column: 2; } .nav i { align-self: center; font-size: 40px; } .main { height: 1500px; width: 98%; justify-self: start; grid-area: main; padding: 10px; float: left; background-color: #e8624c; margin: 10px; } .sidebar-container { height: 900px; width: 300px; justify-self: start; background-color: #209B66; grid-area: sidebar; grid-column: 4; top: 10px; margin: 10px; padding: 20px; display: grid; grid-template-rows: auto; grid-row-gap: 10px; } .sidebar-container>p { display: grid; align-items: start; padding: 0; margin: 0; } .widget { height: 500px; width: 300px; background-color: #E3962F; } .footer { background-color: #333; height: 800px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div class="main-content"> <div class="nav"> <h1>Sticky Sidebar Problem</h1> <i class="fa fa-arrow-down" aria-hidden="true"></i> </div> <div class="main"> <p> [Main Content] </p> </div> <div class="sidebar-container"> <p>[Sidebar Container]</p> <div class="widget"> <p> [Widget]</p> </div> </div> </div> <div class="footer"></div> </body> 

We can break this up into 2 different problems. 我们可以将其分解为两个不同的问题。 Problem #1, you need the bottom Y-chord of your element (a), and Problem #2 you need the bottom of the page (b). 问题#1,您需要元素(a)的底部Y和弦,而问题#2需要页面底部(b)。 If you have this data, then your answer is simply (b - a). 如果您有这些数据,那么您的答案就是(b - a)。

To help us, let's create a helper function as such: 为了帮助我们,让我们创建一个辅助函数:

function getOffset(el) {
  const rect = el.getBoundingClientRect();
  return {
    left: rect.left + window.scrollX,
    right: rect.left - window.scrollX,
    top: rect.top + window.scrollY,
    bottom: rect.bottom -window.scrollY
  };
}

Using this, it should be as simple as getOffset(document.body).bottom - getOffset(yourElement).bottom . 使用它,它应该像getOffset(document.body).bottom - getOffset(yourElement).bottom一样简单。

Hope this helps! 希望这可以帮助!

(Note that I can't actually test this code now so it may not work out of the box, so use it more as a guide not a copy/paste). (请注意,我现在无法实际测试此代码,因此它可能无法开箱即用,因此请将其更多地用作指南而不是复制/粘贴)。

EDIT - jquery solution (original css only answer below): 编辑 - jquery解决方案(原css只在下面回答):

Based on your question edits that provide additional constraints and make an html / css only solution a bit more difficult, below is a jquery solution using your code with new jquery for the sticky sidebar widget and css to make the sidebar widget position: absolute and right: 30px (that value is arbitrary depending on where exactly you want the widget to sit inside the sidebar). 基于你的问题编辑,提供额外的约束,并使一个html / css唯一的解决方案有点困难,下面是一个jquery解决方案使用你的代码与新的jquery粘粘侧边栏小部件和CSS使侧边栏小部件的position: absoluteright: 30px (该值是任意的,具体取决于您希望窗口小部件位于侧边right: 30px确切位置)。 Also, commented out a few other css lines that either weren't doing anything or interfered with the responsiveness of your grid layout (sticky sidebar functionality works with or without those changes, although you may need to adjust the right css of your widget element, including media queries, depending on where your layout ultimately ends up). 此外,注释掉了一些其他css行,这些行或者没有做任何事情或者干扰了网格布局的响应性(粘性侧边栏功能可以使用或不使用这些更改,尽管您可能需要调整窗口小部件元素的right css,包括媒体查询,具体取决于您的布局最终结束的位置)。

 $(function() { const sidebar = $('.sidebar-container'); const widget = $('.widget'); const footer = $('.footer'); const space = 10; // arbitrary value to create space between the window and widget const startTop = sidebar.offset().top + 60; // arbitrary start top position const endTop = footer.offset().top - widget.height() - space; widget.css('top', startTop); $(window).scroll(function() { let windowTop = $(this).scrollTop(); let widgetTop = widget.offset().top; let newTop = startTop; if (widgetTop >= startTop && widgetTop <= endTop) { if (windowTop > startTop - space && windowTop < endTop - space) { newTop = windowTop + space; } else if (windowTop > endTop - space) { newTop = endTop; } widget.stop().animate({ 'top': newTop }); } }); }); 
 @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700'); * { font-family: 'Open Sans'; color: #fff; box-sizing: content-box; } body { padding: 0; margin: 0; } p { margin: 20px; } hr { width: 85%; border-style: solid; } .main-content { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: 150px auto; grid-template-areas: "nav nav nav nav" "main main main sidebar"; grid-column-gap: 20px; grid-row-gap: 0px; } .nav { grid-area: nav; background-color: #266392; display: grid; grid-template-columns: 1fr 3fr 1fr; } .nav h1 { place-self: center; font-weight: 400; font-size: 40px; grid-column: 2; } .nav i { align-self: center; font-size: 40px; } .main { height: 1500px; /*width: 98%; justify-self: start;*/ grid-area: main; padding: 10px; /*float: left;*/ background-color: #e8624c; margin: 10px; } .sidebar-container { height: 900px; width: 300px; justify-self: end; background-color: #209B66; grid-area: sidebar; grid-column: 4; /*top: 10px;*/ margin: 10px; padding: 20px; display: grid; grid-template-rows: auto; grid-row-gap: 10px; } .sidebar-container>p { display: grid; align-items: start; padding: 0; margin: 0; } .widget { height: 500px; width: 300px; background-color: #E3962F; position: absolute; right: 30px; } .footer { background-color: #333; height: 800px; } 
 <body> <div class="main-content"> <div class="nav"> <h1>Sticky Sidebar Problem</h1> <i class="fa fa-arrow-down" aria-hidden="true"></i> </div> <div class="main"> <p> [Main Content] </p> </div> <div class="sidebar-container"> <p>[Sidebar Container]</p> <div class="widget"> <p> [Widget]</p> </div> </div> </div> <div class="footer"></div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> </body> 

ORIGINAL - css solution: ORIGINAL - css解决方案:

Depending on what your requirements are for the footer and browser compatibility, you can get the effect you are looking for without any javascript / jquery. 根据您对页脚和浏览器兼容性的要求,您可以获得所需的效果,而无需任何javascript / jquery。 You would have to make a minor adjustment to your html, moving your footer outside the grid and styling it separately (I just added height for the example below). 您必须对您的html进行微调,将页脚移动到网格外并单独设置样式(我只是为下面的示例添加了高度)。 Then, you could just add position: sticky and top: 10px to your .sidebar css. 然后,你可以添加position: stickytop: 10px到你的.sidebar css。

Result is that sidebar starts scrolling after the header is scrolled and then stops scrolling when it bumps into the footer. 结果是标题滚动后侧边栏开始滚动,然后当它碰到页脚时停止滚动。

Note that position: sticky is not supported in IE (there is a polyfill for sticky ). 请注意,IE中不支持position: sticky (有一个粘贴polyfill )。

See the snippet below with example adjustments to your code: 通过示例调整代码,查看下面的代码段:

 body { padding: 0; margin: 0; } .main-content { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: 80px auto 400px; grid-template-areas: "nav nav nav nav" "main main main sidebar" "footer footer footer footer"; grid-column-gap: 20px; grid-row-gap: 10px; height: 100%; } .nav { grid-area: nav; background-color: #007ccc; } .main { height: 100%; max-width: 600px; justify-self: start; grid-area: main; padding: 10px; float: left; } .sidebar { height: 600px; width: 300px; justify-self: start; background-color: #4BA25E; grid-area: sidebar; grid-column: 4; margin: 10px; position: sticky; top: 10px; } .footer { background-color: #333; height: 400px; } 
 <body> <div class="main-content"> <div class="nav"></div> <div class="main"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tincidunt tempus nisi, vitae finibus nunc pharetra quis. Quisque in vehicula nunc. Nullam nec velit sed mi posuere ultricies pellentesque quis nibh. Morbi consequat, dui at consequat rhoncus, neque nulla posuere odio, non dapibus velit urna in turpis. In feugiat massa orci, vitae scelerisque sem posuere ut.</p> <p>Phasellus porttitor diam metus. Suspendisse quis mi sollicitudin, lobortis orci eu, pharetra ex. Cras ex nibh, dapibus quis tortor a, placerat commodo lorem. Mauris sed sapien ligula. Praesent lobortis cursus varius. Donec vulputate pulvinar interdum. Suspendisse laoreet malesuada commodo.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tincidunt tempus nisi, vitae finibus nunc pharetra quis. Quisque in vehicula nunc. Nullam nec velit sed mi posuere ultricies pellentesque quis nibh. Morbi consequat, dui at consequat rhoncus, neque nulla posuere odio, non dapibus velit urna in turpis. In feugiat massa orci, vitae scelerisque sem posuere ut.</p> <p>Phasellus porttitor diam metus. Suspendisse quis mi sollicitudin, lobortis orci eu, pharetra ex. Cras ex nibh, dapibus quis tortor a, placerat commodo lorem. Mauris sed sapien ligula. Praesent lobortis cursus varius. Donec vulputate pulvinar interdum. Suspendisse laoreet malesuada commodo.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tincidunt tempus nisi, vitae finibus nunc pharetra quis. Quisque in vehicula nunc. Nullam nec velit sed mi posuere ultricies pellentesque quis nibh. Morbi consequat, dui at consequat rhoncus, neque nulla posuere odio, non dapibus velit urna in turpis. In feugiat massa orci, vitae scelerisque sem posuere ut.</p> <p>Phasellus porttitor diam metus. Suspendisse quis mi sollicitudin, lobortis orci eu, pharetra ex. Cras ex nibh, dapibus quis tortor a, placerat commodo lorem. Mauris sed sapien ligula. Praesent lobortis cursus varius. Donec vulputate pulvinar interdum. Suspendisse laoreet malesuada commodo.</p> <p>In hac habitasse platea dictumst. Maecenas et mauris nunc. Aliquam erat volutpat. Duis eu condimentum ipsum. Etiam a mattis ipsum, sit amet vestibulum felis. In fermentum purus augue, vitae interdum ante gravida non. In tincidunt risus vitae ligula dignissim pellentesque. Vivamus id est eget metus placerat euismod et nec diam. Integer luctus bibendum condimentum.</p> <p>Vestibulum pretium quis mauris id pellentesque. Donec placerat iaculis ex, ut porta dolor vestibulum ac. Phasellus nunc tellus, viverra vestibulum posuere eu, faucibus vitae ex. Aenean efficitur maximus nunc, at sagittis nunc mattis sed. Vivamus et magna vitae magna interdum sodales. Ut imperdiet lobortis consectetur.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tincidunt tempus nisi, vitae finibus nunc pharetra quis. Quisque in vehicula nunc. Nullam nec velit sed mi posuere ultricies pellentesque quis nibh. Morbi consequat, dui at consequat rhoncus, neque nulla posuere odio, non dapibus velit urna in turpis. In feugiat massa orci, vitae scelerisque sem posuere ut.</p> <p>Phasellus porttitor diam metus. Suspendisse quis mi sollicitudin, lobortis orci eu, pharetra ex. Cras ex nibh, dapibus quis tortor a, placerat commodo lorem. Mauris sed sapien ligula. Praesent lobortis cursus varius. Donec vulputate pulvinar interdum. Suspendisse laoreet malesuada commodo.</p> <p>In hac habitasse platea dictumst. Maecenas et mauris nunc. Aliquam erat volutpat. Duis eu condimentum ipsum. Etiam a mattis ipsum, sit amet vestibulum felis. In fermentum purus augue, vitae interdum ante gravida non. In tincidunt risus vitae ligula dignissim pellentesque. Vivamus id est eget metus placerat euismod et nec diam. Integer luctus bibendum condimentum.</p> <p>Vestibulum pretium quis mauris id pellentesque. Donec placerat iaculis ex, ut porta dolor vestibulum ac. Phasellus nunc tellus, viverra vestibulum posuere eu, faucibus vitae ex. Aenean efficitur maximus nunc, at sagittis nunc mattis sed. Vivamus etmagna vitae magna interdum sodales. Ut imperdiet lobortis consectetur.</p> <p>Vestibulum pretium quis mauris id pellentesque. Donec placerat iaculis ex, ut porta dolor vestibulum ac. Phasellus nunc tellus, viverra vestibulum posuere eu, faucibus vitae ex. Aenean efficitur maximus nunc, at sagittis nunc mattis sed. Vivamus etmagna vitae magna interdum sodales. Ut imperdiet lobortis consectetur.</p> <p>Vestibulum pretium quis mauris id pellentesque. Donec placerat iaculis ex, ut porta dolor vestibulum ac. Phasellus nunc tellus, viverra vestibulum posuere eu, faucibus vitae ex. Aenean efficitur maximus nunc, at sagittis nunc mattis sed. Vivamus etmagna vitae magna interdum sodales. Ut imperdiet lobortis consectetur.</p> </div> <div class="sidebar"></div> </div> <div class="footer"></div> </body> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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