Липкая боковая панель: придерживайтесь нижней части при прокрутке вниз, сверху при прокрутке вверх



Я уже некоторое время ищу решение моей проблемы с липкой боковой панелью. У меня есть конкретное представление о том, как я хотел бы, чтобы он действовал; эффективно, я хотел бы, чтобы он придерживался дна, когда вы прокручиваете вниз, а затем, как только вы прокручиваете вверх, я хотел бы, чтобы он придерживался вершины, плавным движением (без прыжков). Я не могу найти пример того, что я пытаюсь достичь, поэтому я создал образ, который, я надеюсь проиллюстрировать яснее:

Sticky sidebar: stick to bottom when scrolling down, top when scrolling up

  1. боковая панель находится под заголовком.
  2. при прокрутке вниз боковая панель остается на одном уровне с содержимым страницы, так что вы можете прокручивать как боковую панель, так и содержимое.
  3. достигните нижней части боковой панели, боковая панель прилипает к нижней части окна просмотра (большинство плагинов позволяют только прилипать к верхней части, некоторые из которых позволяют прилипать к нижней части не позволяют оба).
  4. достигнет дна, боковая панель сидит выше футбол.
  5. при прокрутке вверх боковая панель остается на одном уровне с содержимым, поэтому вы можете снова прокручивать содержимое и боковую панель.
  6. достигните верхней части боковой панели, боковая панель прилипает к верхней части окна просмотра.
  7. добраться до верхней и боковой панели сидит обратно под заголовком.

Я надеюсь, что это достаточно информации. Я создал jsfiddle для тестирования любых плагинов / скриптов, которые я сбросил для этого вопроса: http://jsfiddle.net/jslucas/yr9gV/2/ .

247   6  

6 ответов:

+1 к очень хорошему и иллюзорному изображению.

Я знаю, что это старый вопрос, но я случайно нашел тот же вопрос, отправленный вами в forum.jquery.com и один ответ там (by@tucker973), предложил одну хорошую библиотеку, чтобы сделать это и хотел бы поделиться его здесь.

Это называется sticky-kit by @leafo

вот у вас есть код очень простой пример, который я подготовил и рабочую демку, чтобы увидеть результат.

/*!
 * Sticky-kit
 * A jQuery plugin for making smart sticky elements
 *
 * Source: http://leafo.net/sticky-kit/
 */

$(function() {
  $(".sidebar").stick_in_parent({
    offset_top: 10
  });
});
* {
  font-size: 10px;
  color: #333;
  box-sizing: border-box;
}
.wrapper,
.header,
.main,
.footer {
  padding: 10px;
  position: relative;
}
.wrapper {
  border: 1px solid #333;
  background-color: #f5f5f5;
  padding: 10px;
}
.header {
  background-color: #6289AE;
  margin-bottom: 10px;
  height: 100px;
}
.sidebar {
  position: absolute;
  padding: 10px;
  background-color: #ccc;
  height: 300px;
  width: 100px;
  float: left;
}
.main {
  background-color: #ccc;
  height: 600px;
  margin-left: 110px;
}
.footer {
  background-color: #6289AE;
  margin-top: 10px;
  height: 250px;
}
.top {
  position: absolute;
  top: 10px;
}
.bottom {
  position: absolute;
  bottom: 10px;
}
.clear {
  clear: both;
  float: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://leafo.net/sticky-kit/src/jquery.sticky-kit.js"></script>
<div class="wrapper">
  <div class="header"> <a class="top">header top</a>
    <a class="bottom">header bottom</a>

  </div>
  <div class="content">
    <div class="sidebar"> <a class="top">sidebar top</a>
      <a class="bottom">sidebar bottom</a>

    </div>
    <div class="main"> <a class="top">main top</a>
      <a class="bottom">main bottom</a>

    </div>
    <div class="clear"></div>
  </div>
  <div class="footer"> <a class="top">footer top</a>
    <a class="bottom">footer bottom</a>

  </div>
</div>

конечно, все кредиты идут к создателю плагина, я только сделал этот пример, чтобы показать его здесь. Мне нужно для достижения того же результата, что вы были после и нашел этот плагин очень полезным.

Спасибо за отличную графику. Я также искал решение этой проблемы!

к сожалению, другой ответ, опубликованный здесь, не касается требования №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

кроме того, я изменил вашу скрипку так, что липкая боковая панель имеет градиентный фон. Это помогает показать, что демонстрируется правильное поведение.

Я надеюсь, что это кому-то пригодится!

вот пример того, как это реализовать:

JavaScript:

$(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.

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/

в репозитории Wordpress есть относительно неизвестный плагин, известный как WP Sticky Sidebar. Плагин делает именно то, что вы хотели (Sticky sidebar: stick to bottom при прокрутке вниз, top при прокрутке вверх) WP Sticky Sidebar Wordpress repository Link:https://wordpress.org/plugins/mystickysidebar/

Я искал то же самое. По-видимому, мне нужно было искать какие-то неясные термины, чтобы найти аналогичный вопрос с графикой. Оказывается, это именно то, что я ищу. Я не мог найти никаких плагинов, поэтому я решил сделать это сам. Надеюсь, кто-то увидит это и уточнит.

вот быстрый и грязный пример 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, так как я использую адаптивный дизайн и не хочу, чтобы это активировалось на меньших экранах

Если кто-то может уточнить это немного больше, что было бы здорово.

    Ничего не найдено.

Добавить ответ:
Отменить.