고정 사이드 바 : 아래로 스크롤하면 하단에 고정, 위로 스크롤하면 상단에 고정


94

나는 끈적 끈적한 사이드 바 문제에 대한 해결책을 찾고 있습니다. 나는 그것이 어떻게 행동하고 싶은지에 대한 구체적인 아이디어를 가지고 있습니다. 효과적으로, 나는 당신이 아래로 스크롤 할 때 바닥에 붙어 있길 원하고, 다시 위로 스크롤하자마자 유동적 인 동작 (점프 없음)으로 맨 위에 붙어 있길 원합니다. 내가 달성하려는 것의 예를 찾을 수 없으므로 요점을 더 명확하게 설명 할 수있는 이미지를 만들었습니다.

고정 사이드 바 : 아래로 스크롤하면 하단에 고정, 위로 스크롤하면 상단에 고정

  1. 사이드 바는 헤더 아래에 있습니다.
  2. 아래로 스크롤 할 때 사이드 바는 페이지 콘텐츠와 수평을 유지하므로 사이드 바와 콘텐츠를 모두 스크롤 할 수 있습니다.
  3. 사이드 바의 하단에 도달하면 사이드 바가 뷰포트 하단에 고정됩니다 (대부분의 플러그인은 상단 고정 만 허용하고 일부 플러그인은 하단 고정을 허용하는 것은 둘 다 허용하지 않음).
  4. 하단에 도달하면 사이드 바가 바닥 글 위에 있습니다.
  5. 위로 스크롤하면 사이드 바는 콘텐츠와 수평을 유지하므로 콘텐츠와 사이드 바를 다시 스크롤 할 수 있습니다.
  6. 사이드 바의 상단에 도달하면 사이드 바가 뷰포트 상단에 고정됩니다.
  7. 상단에 도달하면 사이드 바가 헤더 아래에 있습니다.

이것이 충분한 정보가되기를 바랍니다. 이 질문에 대해 재설정 한 플러그인 / 스크립트를 테스트하기 위해 jsfiddle을 만들었습니다 : http://jsfiddle.net/jslucas/yr9gV/2/ .

답변:


25

+1아주 멋지고 그림 같은 이미지에 합니다.

나는 그것이 오래된 질문이라는 것을 알고 있지만, forum.jquery.com 에 귀하가 게시 한 동일한 질문 과 거기에 하나의 답변 (by @ tucker973)을 우연히 발견했습니다. 이것을 만들기 위해 하나의 멋진 라이브러리를 제안했고 여기에서 공유하고 싶었습니다.

그것은라고 끈적 키트@leafo

여기에 제가 준비한 매우 기본적인 예제 코드와 결과를보기위한 작업 데모가 있습니다.

물론 모든 크레딧은 플러그인 제작자에게 전달됩니다. 여기서는이 예제 만 보여 드리겠습니다. 나는 당신이 추구했던 것과 동일한 결과를 달성해야 하며이 플러그인이 매우 유용하다는 것을 알았습니다.


나는 당신이 제안한 것처럼이 작은 플러그인을 사용하지만 그것이 상단에 붙은 후에 너비가 변경됩니다. 변경하지 않으려면 어떻게해야합니까?
vijayrana

안녕하세요 @gmo! 나는 같은 일을 찾고 있지만 일을 (스크롤 업에 상단에 부착하지 않음)하지 않습니다 때 더 이상 뷰포트보다 스크롤 ...
이고르 라즐로

13

멋진 그래픽에 감사드립니다. 나는 또한이 도전에 대한 해결책을 찾고 있었다!

불행히도 여기에 게시 된 다른 답변은 사이드 바를 부드럽게 뒤로 스크롤하는 기능을 규정하는 요구 사항 # 5를 다루지 않습니다.

모든 요구 사항을 구현하는 바이올린을 만들었습니다. http://jsfiddle.net/bN4qu/5/

구현해야하는 핵심 로직은 다음과 같습니다.

If scrolling up OR the element is shorter than viewport Then
  Set top of element to top of viewport If scrolled above top of element
If scrolling down then
  Set bottom of element at bottom of viewport If scrolled past bottom of element

바이올린에서는 대상 요소를 이동하기 위해 CSS3 변환을 사용하므로 IE <9에서는 작동하지 않습니다. 논리는 다른 접근 방식을 사용하는 것이 좋습니다.

또한 스티커 사이드 바에 그라데이션 배경이 있도록 바이올린을 수정했습니다. 이것은 적절한 행동이 나타나고 있음을 보여주는 데 도움이됩니다.

누군가에게 유용하기를 바랍니다!


2
답을 찾는 사람에게 Travis의이 답변은 지금까지 찾은 것 중 가장 완벽합니다. 고마워요.
marcovega

대단한 시도였습니다. 기본적으로 이것을 떨어 뜨렸을 때 효과가있었습니다. 다른 플러그인에 대해 말할 수있는 것보다 더 많은 것입니다. :) 성능이 큰 타격을 받았지만, 비 네이티브 고정 구현에서는 거의 주어진 것 같습니다.
jClark

이것은 훌륭한 출발점이었습니다! $.css함수를 a에 래핑하고 requestAnimationFramevue / react와 같은 최신 프런트 엔드 프레임 워크에서 사용하기 위해 destroy / unbind 함수를 추가했습니다. 그 후 성능은 절대 문제가 아닙니다!
Christophe Marois 2017 년

@Cristophe Marois jsfiddle에 대한 예제를 제공 할 수 있습니까?
DuArme

감사합니다,하지만이 코드 작은 사이드 바없는 일 뷰포트의 짧은 (뷰포트의 높이)
세예드 압바스 Seyedi

12

이를 구현하는 방법의 예는 다음과 같습니다.

자바 스크립트 :

$(function() {

var $window = $(window);
var lastScrollTop = $window.scrollTop();
var wasScrollingDown = true;

var $sidebar = $("#sidebar");
if ($sidebar.length > 0) {

    var initialSidebarTop = $sidebar.position().top;

    $window.scroll(function(event) {

        var windowHeight = $window.height();
        var sidebarHeight = $sidebar.outerHeight();

        var scrollTop = $window.scrollTop();
        var scrollBottom = scrollTop + windowHeight;

        var sidebarTop = $sidebar.position().top;
        var sidebarBottom = sidebarTop + sidebarHeight;

        var heightDelta = Math.abs(windowHeight - sidebarHeight);
        var scrollDelta = lastScrollTop - scrollTop;

        var isScrollingDown = (scrollTop > lastScrollTop);
        var isWindowLarger = (windowHeight > sidebarHeight);

        if ((isWindowLarger && scrollTop > initialSidebarTop) || (!isWindowLarger && scrollTop > initialSidebarTop + heightDelta)) {
            $sidebar.addClass('fixed');
        } else if (!isScrollingDown && scrollTop <= initialSidebarTop) {
            $sidebar.removeClass('fixed');
        }

        var dragBottomDown = (sidebarBottom <= scrollBottom && isScrollingDown);
        var dragTopUp = (sidebarTop >= scrollTop && !isScrollingDown);

        if (dragBottomDown) {
            if (isWindowLarger) {
                $sidebar.css('top', 0);
            } else {
                $sidebar.css('top', -heightDelta);
            }
        } else if (dragTopUp) {
            $sidebar.css('top', 0);
        } else if ($sidebar.hasClass('fixed')) {
            var currentTop = parseInt($sidebar.css('top'), 10);

            var minTop = -heightDelta;
            var scrolledTop = currentTop + scrollDelta;

            var isPageAtBottom = (scrollTop + windowHeight >= $(document).height());
            var newTop = (isPageAtBottom) ? minTop : scrolledTop;

            $sidebar.css('top', newTop);
        }

        lastScrollTop = scrollTop;
        wasScrollingDown = isScrollingDown;
    });
}
});

CSS :

#sidebar {
  width: 180px;
  padding: 10px;
  background: red;
  float: right;
}

.fixed {
  position: fixed;
  right: 50%;
  margin-right: -50%;
}

데모 : http://jsfiddle.net/ryanmaxwell/25QaE/

이것은 모든 시나리오에서 예상대로 작동하며 IE에서도 잘 지원됩니다.


이 답변을 참조하고 설명 stackoverflow.com/questions/28428327/…
theinlwin

@Anoop Naik-제가 찾고있는 것이 거의 좋습니다 ... sticky-kit은 뷰포트보다 긴 사이드 바에서는 작동하지 않습니다. 그러나 나는 그 반대를 원한다. 내가 아래로 스크롤하면 위쪽에 붙어 있고, 위로 스크롤하면 아래쪽에 붙어있다 ... 바이올린에서 그 작은 변화로 나를 기쁘게 도와 줄 수 있니?
Igor Laszlo

1
@IgorLaszlo 확실히, 시간 내놔, 언젠가 당신을 업데이트 할 것입니다 ...
Anoop Naik

이것은 또한 내 문제를 설명합니다. "위치가있는 요소가"고정 "되고 뷰포트보다 길면 컨테이너의 맨 아래로 스크롤 한 후에 만 ​​해당 콘텐츠를 볼 수 있습니다."고정 "요소가 스크롤되면 멋질 것입니다. 문서와 함께 중지 된 후 아래쪽 가장자리에 도달하면 사용자가 뒤로 스크롤하면 같은 일이 다시 발생하지만 반대로 진행됩니다. " - 같은 문제 (가 다른 사람에 의해 쓰여진 stackoverflow.com/questions/47618271/...을 )
이고르 라즐로

@Anoop Naik! 노력 해주셔서 감사합니다 . 제 문제를 해결하기 위해 Sticky jquery 플러그인을 찾았습니다. abouolia.github.io/sticky-sidebar 다시 한 번 감사드립니다!
Igor Laszlo

0

나는 똑같은 것을 찾고 있었다. 그래픽과 유사한 질문을 찾기 위해 모호한 용어를 검색해야했던 것 같습니다. 내가 찾던 바로 그것 인 것으로 밝혀졌습니다. 플러그인을 찾을 수 없어서 직접 만들기로 결정했습니다. 누군가가 이것을보고 다듬기를 바랍니다.

여기 내가 사용하고있는 빠르고 더러운 샘플 html이 있습니다.

<div id="main">
    <div class="col-1">
    </div>
    <div class="col-2">
        <div class="side-wrapper">
            sidebar content
        </div>
    </div>
</div>

내가 만든 jQuery는 다음과 같습니다.

var lastScrollPos = $(window).scrollTop();
var originalPos = $('.side-wrapper').offset().top;
if ($('.col-2').css('float') != 'none') {
    $(window).scroll(function(){
        var rectbtfadPos = $('.rectbtfad').offset().top + $('.rectbtfad').height();
        // scroll up direction
        if ( lastScrollPos > $(window).scrollTop() ) {
            // unstick if scrolling the opposite direction so content will scroll with user
            if ($('.side-wrapper').css('position') == 'fixed') {
                $('.side-wrapper').css({
                    'position': 'absolute',
                    'top': $('.side-wrapper').offset().top + 'px',
                    'bottom': 'auto'
                });
            } 
            // if has reached the original position, return to relative positioning
            if ( ($(window).scrollTop() + $('#masthead').height()) < originalPos ) {
                $('.side-wrapper').css({
                    'position': 'relative',
                    'top': 'auto',
                    'bottom': 'auto'
                });
            } 
            // sticky to top if scroll past top of sidebar
            else if ( ($(window).scrollTop() + $('#masthead').height()) < $('.side-wrapper').offset().top && $('.side-wrapper').css('position') == 'absolute' ) {
                $('.side-wrapper').css({
                    'position': 'fixed',
                    'top': 15 + $('#masthead').height() + 'px', // padding to compensate for sticky header
                    'bottom': 'auto'
                });
            }
        } 
        // scroll down
        else {
            // unstick if scrolling the opposite direction so content will scroll with user
            if ($('.side-wrapper').css('position') == 'fixed') {
                $('.side-wrapper').css({
                    'position': 'absolute',
                    'top': $('.side-wrapper').offset().top + 'px',
                    'bottom': 'auto'
                });
            } 
            // check if rectbtfad (bottom most element) has reached the bottom
            if ( ($(window).scrollTop() + $(window).height()) > rectbtfadPos && $('.side-wrapper').css('position') != 'fixed' ) {
                $('.side-wrapper').css({
                    'width': $('.col-2').width(),
                    'position': 'fixed',
                    'bottom': '0',
                    'top': 'auto'
                });
            }
        }
        // set last scroll position to determine if scrolling up or down
        lastScrollPos = $(window).scrollTop();

    });
}

몇 가지 참고 사항 :

  • .rectbtfad는 내 사이드 ​​바에서 가장 하단에있는 요소입니다.
  • # 마스트 헤드의 높이를 사용하고 있습니다. 고정 헤더이기 때문에이를 보완해야합니다.
  • 반응 형 디자인을 사용하고 있으며 더 작은 화면에서 활성화되는 것을 원하지 않기 때문에 col-2 float에 대한 검사가 있습니다.

누군가 이것을 조금 더 다듬을 수 있다면 좋을 것입니다.


0
function fixMe(id) {
    var e = $(id);
    var lastScrollTop = 0;
    var firstOffset = e.offset().top;
    var lastA = e.offset().top;
    var isFixed = false;
    $(window).scroll(function(event){
        if (isFixed) {
            return;
        }
        var a = e.offset().top;
        var b = e.height();
        var c = $(window).height();
        var d = $(window).scrollTop();
        if (b <= c - a) {
            e.css({position: "fixed"});
            isFixed = true;
            return;
        }           
        if (d > lastScrollTop){ // scroll down
            if (e.css("position") != "fixed" && c + d >= a + b) {
                e.css({position: "fixed", bottom: 0, top: "auto"});
            }
            if (a - d >= firstOffset) {
                e.css({position: "absolute", bottom: "auto", top: lastA});
            }
        } else { // scroll up
            if (a - d >= firstOffset) {
                if (e.css("position") != "fixed") {
                    e.css({position: "fixed", bottom: "auto", top: firstOffset});
                }
            } else {
                if (e.css("position") != "absolute") {
                    e.css({position: "absolute", bottom: "auto", top: lastA});
                }               
            }
        }
        lastScrollTop = d;
        lastA = a;
    });
}

fixMe("#stick");

작업 예 : https://jsfiddle.net/L7xoopst/6/


약간의 설명을 추가 하시겠습니까?
HaveNoDisplayName

끈적한 항목 내에서 높이를 업데이트하면 몇 가지 문제가 있습니다
Callam

0

WP Sticky Sidebar로 알려진 Wordpress 저장소에 비교적 알려지지 않은 플러그인이 있습니다. 플러그인은 당신이 원하는 것을 정확하게 수행 (고정 사이드 바 : 하단에 스틱 아래로 스크롤 할 때, 맨 위로 스크롤 할 때) WP 스티커 사이드 바 워드 프레스 저장소 링크 : https://wordpress.org/plugins/mystickysidebar/


정보에 대해서 감사드립니다! 완벽하게 작동했습니다. 그것은 행동 일러스트 그래픽 :) 기능을 갖춘 이미지를 플러그인에 대한 동일하다는 것을 재미
옥사나 Romaniv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.