126 votes

Barre latérale adhésive : reste en bas lors du défilement vers le bas, en haut lors du défilement vers le haut.

Cela fait un certain temps que je cherche une solution à mon problème de barre latérale adhésive. J'ai une idée précise de la façon dont j'aimerais qu'elle agisse ; en fait, j'aimerais qu'elle reste en bas lorsque vous faites défiler le site vers le bas, puis qu'elle revienne en haut dès que vous faites défiler le site vers le haut, dans un mouvement fluide (sans saut). Je n'ai pas trouvé d'exemple de ce que j'essaie d'obtenir, j'ai donc créé une image qui, je l'espère, illustrera mieux mon propos :

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

  1. La barre latérale se trouve sous l'en-tête.
  2. Lorsque vous faites défiler la page, la barre latérale reste au même niveau que le contenu de la page, de sorte que vous pouvez faire défiler à la fois la barre latérale et le contenu.
  3. Atteindre le bas de la barre latérale, la barre latérale se colle au bas de la fenêtre d'affichage (la plupart des plugins ne permettent que de se coller au haut, certains qui permettent de se coller au bas ne permettent pas les deux).
  4. En bas, la barre latérale se trouve au-dessus du pied de page.
  5. Lorsque vous faites défiler la page vers le haut, la barre latérale reste au même niveau que le contenu, de sorte que vous pouvez à nouveau faire défiler le contenu et la barre latérale.
  6. Atteindre le haut de la barre latérale, la barre latérale se colle au haut de la fenêtre d'affichage.
  7. Atteignez le sommet et la barre latérale se retrouve en dessous de l'en-tête.

J'espère que ces informations sont suffisantes. J'ai créé un jsfiddle pour tester les éventuels plugins/scripts, que j'ai réinitialisé pour cette question : http://jsfiddle.net/jslucas/yr9gV/2/ .

3voto

JakePowell Points 80

Option Vanilla JS !

Après avoir voulu faire cela avec Vanilla JS pendant un certain temps, j'ai finalement réussi à le faire. Il y aurait certainement besoin d'un peu de rangement, mais ça marche !

  const sidebar = document.querySelector('#sidebar');

  let lastScrollTop = 0;
  let scrollingDown;
  let isAbsolute = false;

  let absolutePosition = 0;
  let windowTop;
  let sidebarTop;
  let windowBottom;
  let sidebarBottom;

  function checkScrollDirection() {
    if (lastScrollTop <= window.scrollY) {
      scrollingDown = true
    } else {
      scrollingDown = false
    }
    lastScrollTop = window.scrollY;
  }      

  function fixit(pos,top,bottom,isAb) {

    sidebar.style.position = pos;
    sidebar.style.top = top;
    sidebar.style.bottom = bottom;
    isAbsolute = isAb;
  }

  function scrolling() {
    //optional width check
    if (window.innerHeight <= sidebar.offsetHeight && window.innerWidth > 996) {
      checkScrollDirection();
      windowTop = window.scrollY;
      sidebarTop = sidebar.offsetTop;
      windowBottom = window.scrollY + window.innerHeight;
      sidebarBottom = sidebar.offsetHeight + sidebar.offsetTop;

      if(!scrollingDown && windowTop <= sidebarTop) {
        //fixToTop
        fixit("fixed",0,"unset",false)
      }

      if(scrollingDown && windowBottom >= sidebarBottom) {
        //fixToBottom
        fixit("fixed","unset",0,false)
      }

      if((!isAbsolute && windowTop > sidebarTop) || !isAbsolute && windowBottom < sidebarBottom) {
        //fixInPlace
        let absolutePosition = (windowTop + sidebar.offsetTop) + "px";
        fixit("absolute",absolutePosition,"unset",true)
      }
    }
  }

  window.addEventListener('scroll', scrolling);

1voto

Manju Talluri Points 81

Il existe un plugin relativement inconnu dans le dépôt de Wordpress, connu sous le nom de WP Sticky Sidebar. Le plugin fait exactement ce que vous vouliez (Sticky sidebar : reste en bas lors du défilement vers le bas, en haut lors du défilement vers le haut) WP Sticky Sidebar Wordpress repository Link : https://wordpress.org/plugins/mystickysidebar/

0voto

callmeforsox Points 11

Je cherchais exactement la même chose. Apparemment, j'ai dû chercher des termes obscurs pour trouver une question similaire avec le graphique. Il s'avère que c'est exactement ce que je cherchais. Je n'ai pas pu trouver de plugins, alors j'ai décidé de le faire moi-même. J'espère que quelqu'un le verra et l'améliorera.

Voici un exemple de code html rapide et sale que j'utilise.

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

Voici le jQuery que j'ai fait :

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();

    });
}

Quelques notes :

  • .rectbtfad est l'élément le plus bas de ma barre latérale.
  • J'utilise la hauteur de mon #masthead parce qu'il s'agit d'un en-tête autocollant et qu'il doit donc compenser cela
  • Il y a une vérification pour la colonne 2 flottante car j'utilise un design réactif et je ne veux pas que cela s'active sur les petits écrans.

Si quelqu'un peut l'affiner un peu plus, ce serait formidable.

0voto

SezginOnline Points 9
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");

Exemple de travail : https://jsfiddle.net/L7xoopst/6/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X