code

jQuery로 머리글과 바닥글 사이를 스크롤할 때 사이드바를 고정시키는 방법은 무엇입니까?

starcafe 2023. 7. 2. 20:53
반응형

jQuery로 머리글과 바닥글 사이를 스크롤할 때 사이드바를 고정시키는 방법은 무엇입니까?

저는 이 문제에 대해 엄격한 jQuery 솔루션이 필요합니다.워드프레스를 사용하고 있는데 스틱으로 만들고 싶은 사이드바 위젯이 내부에 있기 때문입니다.<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가 아래에 제안한 솔루션은 스니펫에서는 잘 작동하지만, 제 워드프레스 사이트에서는 작동하지 않습니다.다음은 콘솔 오류입니다.

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>

EDIT - jquery 솔루션(아래 원본 CSS만 답변):

추가적인 제약을 제공하고 html/css 전용 솔루션을 조금 더 어렵게 만드는 질문 편집을 기반으로, 아래는 스틱 사이드바 위젯에 대한 새로운 jquery와 함께 코드를 사용하는 jquery 솔루션이고 사이드바 위젯을 만들기 위한 css입니다.position: absolute그리고.right: 30px(이 값은 위젯을 사이드바 안에 배치할 정확한 위치에 따라 임의입니다.)또한, 아무것도 하지 않거나 그리드 레이아웃의 응답성을 방해하는 몇 가지 다른 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() {
    const windowTop = $(this).scrollTop();
    const 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;
}
<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>

원본 - CSS 솔루션:

바닥글 및 브라우저 호환성에 대한 요구 사항에 따라 Javascript/jquery 없이 원하는 효과를 얻을 수 있습니다.HTML을 약간 조정하여 바닥글을 그리드 밖으로 이동하고 별도로 스타일을 지정해야 합니다(아래 예에 대해 높이를 추가했습니다).그러면, 그냥 추가하시면 됩니다.position: sticky그리고.top: 10px의 신에게에..sidebar대소문자

그 결과 사이드바는 머리글이 스크롤된 후 스크롤을 시작하고 바닥글과 충돌하면 스크롤을 중지합니다.

:position: stickyIE에서는 지원되지 않습니다(스틱용 폴리필이 있습니다).

코드 조정 예제와 함께 아래 스니펫을 참조하십시오.

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>

우리는 이것을 두 가지 다른 문제로 나눌 수 있습니다.문제 #1, 요소의 맨 아래 Y 코드(a)가 필요하고, 문제 #2 페이지 맨 아래(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.

이것이 도움이 되길 바랍니다!

(지금은 이 코드를 실제로 테스트할 수 없으므로 즉시 사용할 수 없으므로 복사/붙여넣기가 아닌 가이드로 사용하십시오.)

언급URL : https://stackoverflow.com/questions/52062163/how-to-make-a-sidebar-sticky-when-scrolling-between-header-and-footer-with-jquer

반응형