He estado buscando durante algún tiempo una solución a mi problema de barra lateral pegajosa. Tengo una idea específica de cómo me gustaría que actuara; efectivamente, me gustaría que se quedara en la parte inferior a medida que te desplazas hacia abajo, y luego, tan pronto como te desplaces hacia arriba, me gustaría que se quedara en la parte superior, con un movimiento fluido (sin saltos). No puedo encontrar un ejemplo de lo que estoy tratando de lograr, así que he creado una imagen que espero que ilustre el punto más claramente:
- La barra lateral se encuentra debajo del encabezado.
- A medida que se desplaza hacia abajo, la barra lateral permanece nivelada con el contenido de la página para que pueda desplazarse por la barra lateral y el contenido.
- Llegue a la parte inferior de la barra lateral, la barra lateral se adhiere a la parte inferior de la ventana gráfica (la mayoría de los complementos solo permiten adherirse a la parte superior, algunos que permiten adherirse a la parte inferior no permiten ambas).
- Llega a la parte inferior, la barra lateral se encuentra sobre el pie de página.
- A medida que se desplaza hacia arriba, la barra lateral permanece nivelada con el contenido para que pueda desplazarse por el contenido y la barra lateral nuevamente.
- Llegue a la parte superior de la barra lateral, la barra lateral se adhiere a la parte superior de la ventana gráfica.
- Llega a la parte superior y la barra lateral se ubica debajo del encabezado.
Espero que esta sea suficiente información. He creado un jsfiddle para probar cualquier complemento / script, que he restablecido para esta pregunta: http://jsfiddle.net/jslucas/yr9gV/2/ .
Gracias por el gran gráfico. ¡También estaba buscando una solución a este desafío!
Desafortunadamente, la otra respuesta publicada aquí no aborda el requisito n. ° 5 que estipula la capacidad de desplazarse hacia atrás por la barra lateral sin problemas.
Creé un violín que implementa todos los requisitos: http://jsfiddle.net/bN4qu/5/
La lógica central que debe implementarse es:
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
En el violín, uso la transformación CSS3 para mover el elemento de destino, por lo que no funcionará, por ejemplo, en IE <9. Sin embargo, la lógica es sólida para usar un enfoque diferente.
Además, modifiqué tu violín para que la barra lateral adhesiva tenga un fondo degradado. Esto ayuda a mostrar que se está exhibiendo el comportamiento adecuado.
¡Espero que esto sea útil para alguien!
fuente
$.css
función enrequestAnimationFrame
ay agregué una función de destrucción / desvinculación para su uso en marcos frontend modernos como vue / react. ¡El rendimiento no es un problema en absoluto después de eso!Aquí hay un ejemplo de cómo implementar esto:
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%; }
Demostración: http://jsfiddle.net/ryanmaxwell/25QaE/
Esto funciona como se esperaba en todos los escenarios y también es compatible con IE.
fuente
Estaba buscando exactamente lo mismo. Aparentemente, necesitaba buscar algunos términos oscuros solo para encontrar una pregunta similar con el gráfico. Resulta que es exactamente lo que estaba buscando. No pude encontrar ningún complemento, así que decidí hacerlo yo mismo. Con suerte, alguien verá esto y lo perfeccionará.
Aquí hay una muestra rápida y sucia de HTML que estoy usando.
<div id="main"> <div class="col-1"> </div> <div class="col-2"> <div class="side-wrapper"> sidebar content </div> </div> </div>
Aquí está el jQuery que hice:
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(); }); }
Algunas notas:
Si alguien puede refinar esto un poco más, sería genial.
fuente
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");
Ejemplo de trabajo: https://jsfiddle.net/L7xoopst/6/
fuente
Hay un complemento relativamente desconocido en el repositorio de Wordpress conocido como WP Sticky Sidebar. El complemento hace exactamente lo que usted quería (barra lateral adhesiva: adhiérase a la parte inferior cuando se desplaza hacia abajo, arriba cuando se desplaza hacia arriba) WP Sticky Sidebar Wordpress Repository Link: https://wordpress.org/plugins/mystickysidebar/
fuente