Я уже некоторое время искал решение моей проблемы с липкой боковой панелью. У меня есть конкретное представление о том, как я хочу, чтобы это действовало; эффективно, я бы хотел, чтобы он оставался внизу, когда вы прокручиваете вниз, а затем, как только вы прокручиваете обратно вверх, я хотел бы, чтобы он держался вверх, плавным движением (без прыжков). Я не могу найти пример того, чего пытаюсь достичь, поэтому я создал изображение, которое, надеюсь, проиллюстрирует мысль более четко:
- Боковая панель находится под заголовком.
- При прокрутке вниз боковая панель остается на одном уровне с содержимым страницы, поэтому вы можете прокручивать как боковую панель, так и содержимое.
- Достигнув нижней части боковой панели, боковая панель прикрепляется к нижней части области просмотра (большинство плагинов позволяют придерживаться только верхней части, некоторые, которые позволяют придерживаться нижней части, не допускают обоих).
- Достигните нижней части, боковая панель находится над нижним колонтитулом.
- При прокрутке вверх боковая панель остается на одном уровне с содержимым, поэтому вы можете снова прокручивать содержимое и боковую панель.
- Достигнув верхней части боковой панели, боковая панель прикрепляется к верхней части области просмотра.
- Достигните вершины, и боковая панель вернется под заголовок.
Надеюсь, этой информации достаточно. Я создал jsfiddle для тестирования любых плагинов / скриптов, которые я сбросил для этого вопроса: http://jsfiddle.net/jslucas/yr9gV/2/ .
Спасибо за отличную графику. Я тоже искал решение этой проблемы!
К сожалению, другой опубликованный здесь ответ не соответствует требованию № 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. Впрочем, логика использования другого подхода вполне логична.
Кроме того, я изменил вашу скрипку, чтобы на липкой боковой панели был градиентный фон. Это помогает показать, что демонстрируется правильное поведение.
Надеюсь, это кому-нибудь пригодится!
источник
$.css
заключил функцию в arequestAnimationFrame
и добавил функцию уничтожения / отмены привязки для использования в современных интерфейсных фреймворках, таких как vue / react. После этого производительность абсолютно не проблема!Вот пример того, как это реализовать:
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.
источник
Я искал то же самое. Очевидно, мне нужно было найти какие-то непонятные термины, чтобы найти аналогичный вопрос с изображением. Оказывается, это именно то, что я искал. Мне не удалось найти никаких плагинов, поэтому я решил сделать это сам. Надеюсь, кто-то это увидит и доработает.
Вот быстрый и грязный образец 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(); }); }
Некоторые примечания:
Если бы кто-нибудь мог уточнить это немного, было бы здорово.
источник
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. Плагин делает именно то, что вы хотели (липкая боковая панель: придерживаться нижней части при прокрутке вниз, вверху при прокрутке вверх) WP Sticky Sidebar Репозиторий Wordpress Ссылка: https://wordpress.org/plugins/mystickysidebar/
источник