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

时间:2018-08-28 16:07:51

标签: javascript jquery css wordpress scroll

我需要一个严格的jQuery解决方案来解决这个问题。这是因为我使用的是Wordpress,而要粘贴的侧边栏小部件位于<aside>元素内,因此无法达到全高。

.scrollTop()检测到我要使页面侧边小部件变粘的页面向下的方式相同,我需要JS检测我从页面底部到通过分配来“取消粘帖”该窗口小部件的距离一个新的固定职位。

我尝试使用.offset()来做到这一点,但是到目前为止,我仍然无法使其工作。

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

正如您在侧边栏下方的代码段中所看到的那样,滚动条应该会滚动,但是当我距页脚<10px距离时,我希望侧边栏处于新的固定位置。

我希望边栏在页脚上方占据一个新的固定位置,直到用户向上滚动为止。

编辑:@Benvc所建议的以下解决方案在代码段中运行正常,但在我的wordpress网站上却不行。这是我遇到的控制台错误:

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>

2 个答案:

答案 0 :(得分:1)

我们可以将其分解为2个不同的问题。问题1,您需要元素的底部Y弦(a),问题2,您需要页面的底部Y(b)。如果您有这些数据,那么答案就是(b-a)。

为帮助我们,让我们这样创建一个辅助函数:

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
  };
}

使用它,它应该像getOffset(document.body).bottom - getOffset(yourElement).bottom一样简单。

希望这会有所帮助!

(请注意,我现在无法实际测试此代码,因此它可能开箱即用,因此请更多地用作指导,而不是复制/粘贴)。

答案 1 :(得分:1)

编辑-jQuery解决方案(以下仅原始CSS回答):

根据您的问题编辑提供了更多的约束,并使html / css唯一的解决方案变得更加困难,下面是一个jquery解决方案,其中将您的代码与新的jquery一起用于粘性侧边栏小部件,而css则使侧边栏小部件{{ 1}}和position: absolute(该值是任意值,具体取决于您希望小部件位于边栏中的确切位置)。另外,请注释掉其他几行css行,这些行可能什么都不做,或干扰了网格布局的响应能力(粘性侧边栏功能可以更改或不更改,尽管您可能需要调整right: 30px css您的小部件元素(包括媒体查询),具体取决于最终布局的位置。

right
$(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;
}

原始-CSS解决方案:

根据对页脚和浏览器兼容性的要求,无需任何javascript / jquery即可获得所需的效果。您将需要对html进行细微调整,将页脚移到网格外并单独设置样式(在下面的示例中,我仅添加了高度)。然后,您可以将<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>position: sticky添加到top: 10px CSS中。

结果是,在滚动标题后,侧边栏开始滚动,然后在碰到页脚时停止滚动。

请注意,IE中不支持.sidebar(存在polyfill for sticky)。

请参见下面的代码片段,并对代码进行示例调整:

position: sticky
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;
}