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/ .

35voto

gmo Points 2156

+1 à l'image très belle et illustrative.

Je sais qu'il s'agit d'une vieille question, mais j'ai trouvé par hasard la même question que vous avez postée en forum.jquery.com et une réponse ici (par@tucker973) Il a suggéré une belle bibliothèque pour faire cela et a voulu la partager ici.

Cela s'appelle kit de collage por @leafo

Vous avez ici le code d'un exemple très basique que j'ai préparé et une démo fonctionnelle pour voir le résultat.

/*!
 * 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>

Bien sûr, tous les crédits vont au créateur du plugin, j'ai seulement fait cet exemple pour le montrer ici. J'ai besoin d'obtenir le même résultat que vous et j'ai trouvé ce plugin très utile.

16voto

Devin Points 21

Merci pour ce super graphique. Je cherchais aussi une solution à ce défi !

Malheureusement, l'autre réponse publiée ici ne répond pas à l'exigence n° 5, qui stipule la possibilité de faire défiler la barre latérale en arrière de manière fluide.

J'ai créé un violon qui met en œuvre toutes les exigences : http://jsfiddle.net/bN4qu/5/

La logique de base qui doit être mise en œuvre est la suivante :

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

Dans le bidule, j'utilise la transformation CSS3 pour déplacer l'élément cible, ce qui ne fonctionnera pas dans IE<9, par exemple. La logique est cependant saine pour utiliser une approche différente.

J'ai également modifié votre truc pour que la barre latérale adhésive ait un fond dégradé. Cela permet de montrer que l'on adopte le bon comportement.

J'espère que cela sera utile à quelqu'un !

14voto

Anoop Naik Points 301

Voici un exemple de mise en œuvre :

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%;
}

Démonstration : http://jsfiddle.net/ryanmaxwell/25QaE/

Cela fonctionne comme prévu dans tous les scénarios et est bien pris en charge dans IE également.

12voto

Krzysztof AN Points 346

Exemple de barre latérale autocollante à deux directions.

Si quelqu'un a besoin d'une solution légère non basée sur jQuery, je vous invite à vous familiariser avec ce code : Barre latérale adhésive bidirectionnelle sur GitHub .

//aside selector
const aside = document.querySelector('[data-sticky="true"]'), 
//varibles
startScroll = 0;
var endScroll = window.innerHeight - aside.offsetHeight -500,
currPos = window.scrollY;
screenHeight = window.innerHeight,
asideHeight = aside.offsetHeight;
aside.style.top = startScroll + 'px';
//check height screen and aside on resize
window.addEventListener('resize', ()=>{
    screenHeight = window.innerHeight;
    asideHeight = aside.offsetHeight;
});
//main function
document.addEventListener('scroll', () => {
    endScroll = window.innerHeight - aside.offsetHeight;
    let asideTop = parseInt(aside.style.top.replace('px;', ''));
    if(asideHeight>screenHeight){
        if (window.scrollY < currPos) {
            //scroll up
            if (asideTop < startScroll) {
                aside.style.top = (asideTop + currPos - window.scrollY) + 'px';
            } else if (asideTop >= startScroll && asideTop != startScroll) {
                aside.style.top = startScroll + 'px';
            }
        } else {
            //scroll down
            if (asideTop > endScroll) {
                aside.style.top = (asideTop + currPos - window.scrollY) + 'px';
            } else if (asideTop < (endScroll) && asideTop != endScroll) {
                aside.style.top = endScroll + 'px';
            }
        }
    }
    currPos = window.scrollY;
}, {
    capture: true,
    passive: true
});

body{
  padding: 0 20px;
}
#content {
  height: 2000px;
}
header {
  width: 100%;
  height: 150px;
  background: #aaa;
}
main {
  float: left;
  width: 65%;
  height: 100%;
  background: #444;
}
aside {
  float: right;
  width: 30%;
  position: sticky;
  top: 0px;
  background: #777;
}
li {
  height: 50px;
}
footer {
  width: 100%;
  height: 300px;
  background: #555;
  position: relative;
  bottom: 0;
}

<!DOCTYPE html>
    <head>
        <link href="http://stackoverflow.com/src/style.css" rel="preload" as="style"/>
    </head>
    <body>
        <header>Header</header>
            <div id="content">
            <main>Content</main>
            <aside data-sticky="true">
              <lu>
                <li>Top</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>sidebar</li>
                <li>Bottom</li>
              </lu>
            </aside>
            </div>
        <footer>Footer</footer>
        <script src='/src/script.js' async></script>
    </body>
</html>

4voto

Rishi Malviya Points 67

Vous pouvez également utiliser Barre latérale adhésive Plugin JS pour le même effet que celui que vous recherchez. Il dispose d'une petite documentation simple sur le "mode d'emploi". J'ai également voulu un effet de défilement similaire et cela a bien fonctionné.

https://abouolia.github.io/sticky-sidebar/

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