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

9

124

I have been looking for some time now for a solution to my sticky sidebar problem. I have a specific idea of how I would like it to act; effectively, I would like it to stick to the bottom as you scroll down, and then as soon as you scroll back up I would like it to stick to the top, in a fluid motion (no jumping). I am unable to find an example of what I am trying to achieve, so I have created an image that I hope will illustrate the point clearer:

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

  1. Sidebar sits under the header.
  2. As you scroll down the sidebar remains level with the content of the page so that you can scroll through both sidebar and content.
  3. Reach the bottom of the sidebar, the sidebar sticks to the bottom of the viewport (most plugins only allow for sticking to top, some that allow for sticking to bottom don't allow for both).
  4. Reach the bottom, sidebar sits above the footer.
  5. As you scroll back up, the sidebar stays level with the content so you can scroll through the content and sidebar again.
  6. Reach the top of the sidebar, the sidebar sticks to the top of the viewport.
  7. Reach the top and the sidebar sits back below the header.

I hope this is enough information. I have created a jsfiddle to test any plugins/scripts, which I have reset for this question: http://jsfiddle.net/jslucas/yr9gV/2/ .

Archaic answered 21/8, 2013 at 13:30 Comment(3)
This is a great question and good illustration. Just as a note (because I was looking for this with other search terms): This exact behaviour is implemented in the WordPress admin interface. I haven't gone trough the code, but on inspecting what happens. Is seems like the sidebar is set with postition:fixed. Then there's a JS scroll event listener that detects wheter the sidebar should scroll with the content, and switches it to position:absolute with a top set with javascript. Once the sidebar should stop scrolling, it's change to position:fixed again with the appropriate topProcopius
Can't edit my original comment anymore. But here's the code that made this possible in the WP admin interface: core.trac.wordpress.org/changeset/26125 (related track ticket: core.trac.wordpress.org/ticket/19994)Procopius
Is there a 2021 solution to this problem?Rufus
L
35

+1 to the very nice and ilustrative image.

I know it's an old question, but I casually found the same question posted by you in forum.jquery.com and one answer there (by@tucker973), suggested one nice library to make this and wanted to share it here.

It's called sticky-kit by @leafo

Here you have the code of a very basic example that I prepared and a working demo to see the result.

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

Of course, all credits go to the creator of the plugin, I only made this example to show it here. I need to accomplish the same result that you was after and found this plugin very useful.

Leucippus answered 5/12, 2014 at 12:45 Comment(5)
I use the this small plugin as you suggest, but the width change after it stick on the top. How can I make it unchanged ?Fernald
Hi @Leucippus ! I am looking for the same thing but it does not work (does not stick on top on scroll up) when the scrollbar longer than the viewport...Nonparous
Project seems to be abandoned. Even the demo page is no longer working.Procopius
@JulesColle - yes, even the demos are not working. There's another project - abouolia.github.io/sticky-sidebar Try this out.Deflection
@AnoopNaik looks nice. I guess this answer needs some more upvotes: https://mcmap.net/q/180207/-sticky-sidebar-stick-to-bottom-when-scrolling-down-top-when-scrolling-upProcopius
O
16

Thanks for the great graphic. I was also looking for a solution to this challenge!

Unfortunately, the other answer posted here doesn't address requirement #5 that stipulates the ability to scroll back through the sidebar smoothly.

I created a fiddle that implements all requirements: http://jsfiddle.net/bN4qu/5/

The core logic that needs to be implemented is:

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

In the fiddle I use CSS3 transform for moving the target element around, so it won't work in e.g. IE<9. The logic is sound though for using a different approach.

Also, I modified your fiddle so that the sticky sidebar has a gradient background. This helps to show that the proper behavior is being exhibited.

I hope this is useful to someone!

Orlan answered 29/7, 2014 at 21:43 Comment(5)
To anyone searching for an answer, this one by Travis is the most flawless that I've found so far. Thanks man.Divorce
A great attempt, it basically just worked when I dropped this in, which is more than I could say for other plugins :) Performance took a big hit, but I think that's pretty much a given with any non-native sticky implementation.Allaround
This was an excellent starting point! I wrapped the $.css function in a requestAnimationFrame and added a destroy/unbind function for usage in modern frontend frameworks like vue/react. Performance is absolutely not an issue after that!Rudiment
@Cristophe Marois can you provide an example on jsfiddle please?Tenfold
thanks, but this code not work for small sidebar that shorter of viewport (height of viewport)Drollery
D
14

Here's an example of how to implement this:

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

Demo: http://jsfiddle.net/ryanmaxwell/25QaE/

This works as expected in all scenarios and is well-supported in IE too.

Deflection answered 30/10, 2014 at 19:57 Comment(7)
see this answer and explain #28428827Coopery
@Anoop Naik - that is almost good what I am looking for... sticky-kit does not work for sidebars which are longer than the viewport, yours works. However I would like the opposite : when I scroll down, it sticks on the top, and in scrolling up, it sticks on the bottom... can you help me please with that small changing in a fiddle please ?Nonparous
@IgorLaszlo sure, gimme some time, will update you in some time...Deflection
This also explains my problem : "When element with position: sticky is "stuck" and is longer than viewport, you can only see its content after you scroll to the bottom of container. It would be cool, if the "stuck" element scrolled with the document and stopped, once it reaches its bottom edge. If user scrolled back, the same thing would happen again, but in reverse." - written by another person who has the same problem (#47618771)Nonparous
@Anoop Naik ! Thanks for your effort but let it please, I found Sticky jquery plugin to resolve my problem : abouolia.github.io/sticky-sidebar Thank you again !Nonparous
Hey, this is a great solution, thanks ! Could you help me make it work with a footer please ? Tried to change isPageAtBottom to $(document).height() - $('.footer').height() but it's probably not the only thing necessary. @AnoopNaikNuclease
Google Core Web Vitals will flag this as an error for very high CLS (Cumulative Layout Shift). This answer needs to be updated to use Transformations instead of "top" positioning changes. Otherwise pages will begin to suffer losses in Google search results.Flump
J
10

Two Direction Sticky Sidebar by Krzysztof Antosik.

enter image description here

If anyone needs a lightweight solution not based on jQuery, feel free to check out my code.

Using the script is trivial. Just place the JavaScript code at the end of the page, and then add the attribute: data-sticky ="true" to the side panel's tag.

Details can be found on github: Two-direction-Sticky-Sidebar on GitHub.

Or my website: Dwukierunkowy panel boczny – Two Direction Sticky Sidebar (only Polish language)

Try working demo: Two-direction-Sticky-Sidebar Demo.

/**
 * StickySidebar.js
 * A short JavaScript code that allows you to quickly and easily implement a Sticky Sidebar,
 * if the browser's viewport is too short, sidebar's contents will scroll in the direction
 * the user scrolls and sticks to either top or bottom of the screen when there's no more content. 
 * And everything with the use of pure JavaScript, 
 * thanks to which you we'll save redundant code and gain efficiency.
 * -- Krzysztof Antosik
 *
 *
 * @license The MIT License, https://github.com/Krzysztof-Antosik/Two-direction-Sticky-Sidebar/blob/main/LICENSE
 * @version 1.6
 * @author  Krzysztof Antosik, https://github.com/Krzysztof-Antosik/
 * @updated 2023-07-06
 * @link    https://github.com/Krzysztof-Antosik/Two-direction-Sticky-Sidebar/
 *
 *
 */


//Sticky element selector..
const stickyElement = document.querySelector(`[data-sticky="true"]`),

//..and other constant
startPosition = stickyElement.getBoundingClientRect().top;

//Varibles
var endScroll = window.innerHeight - stickyElement.offsetHeight - 500,
currPos = window.scrollY,
screenHeight = window.innerHeight,
stickyElementHeight = stickyElement.offsetHeight
topGap = 0,
bottomGap = 0;

//Set Gaps
setTimeout(() => {
    if (stickyElement.hasAttribute(`data-top-gap`)){
        const dataTopGap = stickyElement.getAttribute(`data-top-gap`);
        topGap = String(dataTopGap) == "auto" ? startPosition : parseInt(dataTopGap);
    }

    if (stickyElement.hasAttribute(`data-bottom-gap`)){
        bottomGap = parseInt(stickyElement.getAttribute(`data-bottom-gap`));
    }
}, 100);

//Add required style to sticky element
stickyElement.style.position = `sticky`;
stickyElement.style.top = topGap + `px`; 
stickyElement.style.height = "fit-content";

//Main function
function positionStickySidebar() {
    endScroll = window.innerHeight - stickyElement.offsetHeight - bottomGap;
    let stickyElementTop = parseInt(stickyElement.style.top.replace(`px;`, ``));
    if (stickyElementHeight+topGap+bottomGap>screenHeight) {
        if (window.scrollY < currPos) {

            //Scroll up
            if (stickyElementTop < topGap) {
                stickyElement.style.top = (stickyElementTop + currPos - window.scrollY) + `px`;
            } else if (stickyElementTop >= topGap && stickyElementTop != topGap) {
                stickyElement.style.top = topGap + `px`;
            }
        } else {

            //Scroll down
            if (stickyElementTop > endScroll) {
                stickyElement.style.top = (stickyElementTop + currPos - window.scrollY) + `px`;
            } else if (stickyElementTop < (endScroll) && stickyElementTop != endScroll) {
                stickyElement.style.top = endScroll + `px`;
            }
        }
    } else {
        stickyElement.style.top = topGap + `px`;
    }
    currPos = window.scrollY;
}
function stickyElementToMe(){
    stickyElement.style.top = topGap + `px`;
}
function updateSticky(){
    screenHeight = window.innerHeight;
    stickyElementHeight = stickyElement.offsetHeight;
    positionStickySidebar();
}
setTimeout(() => {
    //Check heights of the viewport and the sticky element on window resize and reapply positioning
    window.addEventListener(`resize`, ()=>{
        currPos = window.scrollY;
        updateSticky();
    });   
    //Follow the main function when scrolling
    document.addEventListener(`scroll`, updateSticky, {
        capture: true,
        passive: true
    }); 
}, 1000);
div {
  display: flex;
  align-items: flex-start;
}

h1 {
  margin: 0;
}

header {
  width: 100%;
  text-align: center;
  background: #1ABC9C;
}

main {
  width: 65%;
  padding: 0 5%;
  background: #95A5A6;
}

aside {
  width: 15%;
  background: #34495E;
  padding: 0 5%;
  text-align: center;
  position: sticky;
  top: 0;  
}

ul {
  list-style: none;
  padding: 0;
}

li {
  height: 40px;
}
<html>
  <body>
    <header>
      <h1>
      Two direction sticky sidebar
      </h1>
    </header>
    <div>
      <main>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Aliquet bibendum enim facilisis gravida neque convallis a. Maecenas sed enim ut sem viverra. Est ultricies integer quis auctor elit sed vulputate. Metus vulputate eu scelerisque felis imperdiet. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Suscipit tellus mauris a diam maecenas sed enim. In est ante in nibh mauris cursus. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Eu scelerisque felis imperdiet proin fermentum leo vel. Libero justo laoreet sit amet cursus sit amet dictum. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus. Tempor commodo ullamcorper a lacus vestibulum sed arcu. Nisl condimentum id venenatis a condimentum vitae. Morbi tincidunt augue interdum velit euismod.
        </p>
        <p>
        Sed enim ut sem viverra aliquet eget sit. Nisl pretium fusce id velit ut tortor pretium viverra. Ut consequat semper viverra nam libero justo laoreet sit. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. A diam sollicitudin tempor id eu nisl nunc mi. Tortor at risus viverra adipiscing at in tellus integer. Arcu non sodales neque sodales ut etiam sit amet nisl. Quisque non tellus orci ac auctor augue mauris augue. Urna neque viverra justo nec. Suspendisse ultrices gravida dictum fusce. Tempus imperdiet nulla malesuada pellentesque elit eget gravida.
        </p>
        <p>
        Non curabitur gravida arcu ac. Ac odio tempor orci dapibus ultrices in iaculis nunc sed. Cursus euismod quis viverra nibh cras pulvinar. Risus viverra adipiscing at in. Proin libero nunc consequat interdum varius. In fermentum posuere urna nec tincidunt praesent semper feugiat. Aliquam ut porttitor leo a diam sollicitudin tempor id eu. Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Convallis posuere morbi leo urna. Sit amet luctus venenatis lectus. Amet nisl purus in mollis nunc sed id semper risus. Facilisi etiam dignissim diam quis enim. Massa ultricies mi quis hendrerit dolor. Id leo in vitae turpis massa sed.
        </p>
        <p>
        Lorem ipsum dolor sit amet. Tortor vitae purus faucibus ornare suspendisse sed nisi. Magnis dis parturient montes nascetur ridiculus mus. Turpis in eu mi bibendum neque. Nibh mauris cursus mattis molestie. Diam phasellus vestibulum lorem sed risus ultricies. Nulla pellentesque dignissim enim sit amet venenatis urna. Habitant morbi tristique senectus et netus et malesuada. Feugiat in fermentum posuere urna nec tincidunt praesent. Velit scelerisque in dictum non. Et pharetra pharetra massa massa.
        </p>
        <p>
        Mauris in aliquam sem fringilla ut morbi tincidunt. Non blandit massa enim nec dui nunc. Arcu dictum varius duis at consectetur lorem donec massa. Ullamcorper velit sed ullamcorper morbi tincidunt. Tortor id aliquet lectus proin nibh. Lorem donec massa sapien faucibus et. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. Nibh sit amet commodo nulla facilisi nullam. Lectus nulla at volutpat diam ut venenatis tellus in metus. Blandit turpis cursus in hac habitasse platea. Nec feugiat nisl pretium fusce id velit ut tortor pretium. Vitae nunc sed velit dignissim sodales ut eu sem integer. Suspendisse potenti nullam ac tortor. Augue eget arcu dictum varius duis at consectetur lorem donec.
        </p>
        <p>
        Sed augue lacus viverra vitae. Vestibulum rhoncus est pellentesque elit. Egestas sed sed risus pretium quam vulputate dignissim. Ante metus dictum at tempor. Massa sapien faucibus et molestie ac feugiat sed lectus vestibulum. Vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra. Donec enim diam vulputate ut pharetra sit amet. Potenti nullam ac tortor vitae purus. Lacinia quis vel eros donec ac. Fames ac turpis egestas maecenas pharetra convallis. At ultrices mi tempus imperdiet nulla malesuada. Ut ornare lectus sit amet est placerat in egestas. Ultricies leo integer malesuada nunc vel. Congue quisque egestas diam in arcu cursus euismod quis.
        </p>
        <p>
        Parturient montes nascetur ridiculus mus mauris vitae ultricies leo. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Sollicitudin ac orci phasellus egestas tellus rutrum. Libero justo laoreet sit amet cursus sit amet dictum sit. Et odio pellentesque diam volutpat commodo sed. A lacus vestibulum sed arcu non odio euismod. Eget aliquet nibh praesent tristique. Luctus accumsan tortor posuere ac ut. Condimentum vitae sapien pellentesque habitant. Tincidunt augue interdum velit euismod. Tortor condimentum lacinia quis vel eros donec ac odio tempor. Accumsan sit amet nulla facilisi morbi. Ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Dui faucibus in ornare quam viverra. Gravida cum sociis natoque penatibus et. Pellentesque sit amet porttitor eget dolor. Libero nunc consequat interdum varius sit amet mattis vulputate enim. Turpis massa tincidunt dui ut ornare lectus sit.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Aliquet bibendum enim facilisis gravida neque convallis a. Maecenas sed enim ut sem viverra. Est ultricies integer quis auctor elit sed vulputate. Metus vulputate eu scelerisque felis imperdiet. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Suscipit tellus mauris a diam maecenas sed enim. In est ante in nibh mauris cursus. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Eu scelerisque felis imperdiet proin fermentum leo vel. Libero justo laoreet sit amet cursus sit amet dictum. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus. Tempor commodo ullamcorper a lacus vestibulum sed arcu. Nisl condimentum id venenatis a condimentum vitae. Morbi tincidunt augue interdum velit euismod.
        </p>
        <p>
        Sed enim ut sem viverra aliquet eget sit. Nisl pretium fusce id velit ut tortor pretium viverra. Ut consequat semper viverra nam libero justo laoreet sit. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. A diam sollicitudin tempor id eu nisl nunc mi. Tortor at risus viverra adipiscing at in tellus integer. Arcu non sodales neque sodales ut etiam sit amet nisl. Quisque non tellus orci ac auctor augue mauris augue. Urna neque viverra justo nec. Suspendisse ultrices gravida dictum fusce. Tempus imperdiet nulla malesuada pellentesque elit eget gravida.
        </p>
        <p>
        Non curabitur gravida arcu ac. Ac odio tempor orci dapibus ultrices in iaculis nunc sed. Cursus euismod quis viverra nibh cras pulvinar. Risus viverra adipiscing at in. Proin libero nunc consequat interdum varius. In fermentum posuere urna nec tincidunt praesent semper feugiat. Aliquam ut porttitor leo a diam sollicitudin tempor id eu. Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Convallis posuere morbi leo urna. Sit amet luctus venenatis lectus. Amet nisl purus in mollis nunc sed id semper risus. Facilisi etiam dignissim diam quis enim. Massa ultricies mi quis hendrerit dolor. Id leo in vitae turpis massa sed.
        </p>
        <p>
        Lorem ipsum dolor sit amet. Tortor vitae purus faucibus ornare suspendisse sed nisi. Magnis dis parturient montes nascetur ridiculus mus. Turpis in eu mi bibendum neque. Nibh mauris cursus mattis molestie. Diam phasellus vestibulum lorem sed risus ultricies. Nulla pellentesque dignissim enim sit amet venenatis urna. Habitant morbi tristique senectus et netus et malesuada. Feugiat in fermentum posuere urna nec tincidunt praesent. Velit scelerisque in dictum non. Et pharetra pharetra massa massa.
        </p>
        <p>
        Mauris in aliquam sem fringilla ut morbi tincidunt. Non blandit massa enim nec dui nunc. Arcu dictum varius duis at consectetur lorem donec massa. Ullamcorper velit sed ullamcorper morbi tincidunt. Tortor id aliquet lectus proin nibh. Lorem donec massa sapien faucibus et. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. Nibh sit amet commodo nulla facilisi nullam. Lectus nulla at volutpat diam ut venenatis tellus in metus. Blandit turpis cursus in hac habitasse platea. Nec feugiat nisl pretium fusce id velit ut tortor pretium. Vitae nunc sed velit dignissim sodales ut eu sem integer. Suspendisse potenti nullam ac tortor. Augue eget arcu dictum varius duis at consectetur lorem donec.
        </p>
        <p>
        Sed augue lacus viverra vitae. Vestibulum rhoncus est pellentesque elit. Egestas sed sed risus pretium quam vulputate dignissim. Ante metus dictum at tempor. Massa sapien faucibus et molestie ac feugiat sed lectus vestibulum. Vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra. Donec enim diam vulputate ut pharetra sit amet. Potenti nullam ac tortor vitae purus. Lacinia quis vel eros donec ac. Fames ac turpis egestas maecenas pharetra convallis. At ultrices mi tempus imperdiet nulla malesuada. Ut ornare lectus sit amet est placerat in egestas. Ultricies leo integer malesuada nunc vel. Congue quisque egestas diam in arcu cursus euismod quis.
        </p>
        <p>
        Parturient montes nascetur ridiculus mus mauris vitae ultricies leo. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Sollicitudin ac orci phasellus egestas tellus rutrum. Libero justo laoreet sit amet cursus sit amet dictum sit. Et odio pellentesque diam volutpat commodo sed. A lacus vestibulum sed arcu non odio euismod. Eget aliquet nibh praesent tristique. Luctus accumsan tortor posuere ac ut. Condimentum vitae sapien pellentesque habitant. Tincidunt augue interdum velit euismod. Tortor condimentum lacinia quis vel eros donec ac odio tempor. Accumsan sit amet nulla facilisi morbi. Ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Dui faucibus in ornare quam viverra. Gravida cum sociis natoque penatibus et. Pellentesque sit amet porttitor eget dolor. Libero nunc consequat interdum varius sit amet mattis vulputate enim. Turpis massa tincidunt dui ut ornare lectus sit.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Aliquet bibendum enim facilisis gravida neque convallis a. Maecenas sed enim ut sem viverra. Est ultricies integer quis auctor elit sed vulputate. Metus vulputate eu scelerisque felis imperdiet. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Suscipit tellus mauris a diam maecenas sed enim. In est ante in nibh mauris cursus. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Eu scelerisque felis imperdiet proin fermentum leo vel. Libero justo laoreet sit amet cursus sit amet dictum. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus. Tempor commodo ullamcorper a lacus vestibulum sed arcu. Nisl condimentum id venenatis a condimentum vitae. Morbi tincidunt augue interdum velit euismod.
        </p>
        <p>
        Sed enim ut sem viverra aliquet eget sit. Nisl pretium fusce id velit ut tortor pretium viverra. Ut consequat semper viverra nam libero justo laoreet sit. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. A diam sollicitudin tempor id eu nisl nunc mi. Tortor at risus viverra adipiscing at in tellus integer. Arcu non sodales neque sodales ut etiam sit amet nisl. Quisque non tellus orci ac auctor augue mauris augue. Urna neque viverra justo nec. Suspendisse ultrices gravida dictum fusce. Tempus imperdiet nulla malesuada pellentesque elit eget gravida.
        </p>
        <p>
        Non curabitur gravida arcu ac. Ac odio tempor orci dapibus ultrices in iaculis nunc sed. Cursus euismod quis viverra nibh cras pulvinar. Risus viverra adipiscing at in. Proin libero nunc consequat interdum varius. In fermentum posuere urna nec tincidunt praesent semper feugiat. Aliquam ut porttitor leo a diam sollicitudin tempor id eu. Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Convallis posuere morbi leo urna. Sit amet luctus venenatis lectus. Amet nisl purus in mollis nunc sed id semper risus. Facilisi etiam dignissim diam quis enim. Massa ultricies mi quis hendrerit dolor. Id leo in vitae turpis massa sed.
        </p>
        <p>
        Lorem ipsum dolor sit amet. Tortor vitae purus faucibus ornare suspendisse sed nisi. Magnis dis parturient montes nascetur ridiculus mus. Turpis in eu mi bibendum neque. Nibh mauris cursus mattis molestie. Diam phasellus vestibulum lorem sed risus ultricies. Nulla pellentesque dignissim enim sit amet venenatis urna. Habitant morbi tristique senectus et netus et malesuada. Feugiat in fermentum posuere urna nec tincidunt praesent. Velit scelerisque in dictum non. Et pharetra pharetra massa massa.
        </p>
        <p>
        Mauris in aliquam sem fringilla ut morbi tincidunt. Non blandit massa enim nec dui nunc. Arcu dictum varius duis at consectetur lorem donec massa. Ullamcorper velit sed ullamcorper morbi tincidunt. Tortor id aliquet lectus proin nibh. Lorem donec massa sapien faucibus et. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. Nibh sit amet commodo nulla facilisi nullam. Lectus nulla at volutpat diam ut venenatis tellus in metus. Blandit turpis cursus in hac habitasse platea. Nec feugiat nisl pretium fusce id velit ut tortor pretium. Vitae nunc sed velit dignissim sodales ut eu sem integer. Suspendisse potenti nullam ac tortor. Augue eget arcu dictum varius duis at consectetur lorem donec.
        </p>
        <p>
        Sed augue lacus viverra vitae. Vestibulum rhoncus est pellentesque elit. Egestas sed sed risus pretium quam vulputate dignissim. Ante metus dictum at tempor. Massa sapien faucibus et molestie ac feugiat sed lectus vestibulum. Vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra. Donec enim diam vulputate ut pharetra sit amet. Potenti nullam ac tortor vitae purus. Lacinia quis vel eros donec ac. Fames ac turpis egestas maecenas pharetra convallis. At ultrices mi tempus imperdiet nulla malesuada. Ut ornare lectus sit amet est placerat in egestas. Ultricies leo integer malesuada nunc vel. Congue quisque egestas diam in arcu cursus euismod quis.
        </p>
        <p>
        Parturient montes nascetur ridiculus mus mauris vitae ultricies leo. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Sollicitudin ac orci phasellus egestas tellus rutrum. Libero justo laoreet sit amet cursus sit amet dictum sit. Et odio pellentesque diam volutpat commodo sed. A lacus vestibulum sed arcu non odio euismod. Eget aliquet nibh praesent tristique. Luctus accumsan tortor posuere ac ut. Condimentum vitae sapien pellentesque habitant. Tincidunt augue interdum velit euismod. Tortor condimentum lacinia quis vel eros donec ac odio tempor. Accumsan sit amet nulla facilisi morbi. Ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Dui faucibus in ornare quam viverra. Gravida cum sociis natoque penatibus et. Pellentesque sit amet porttitor eget dolor. Libero nunc consequat interdum varius sit amet mattis vulputate enim. Turpis massa tincidunt dui ut ornare lectus sit.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Aliquet bibendum enim facilisis gravida neque convallis a. Maecenas sed enim ut sem viverra. Est ultricies integer quis auctor elit sed vulputate. Metus vulputate eu scelerisque felis imperdiet. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Suscipit tellus mauris a diam maecenas sed enim. In est ante in nibh mauris cursus. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Eu scelerisque felis imperdiet proin fermentum leo vel. Libero justo laoreet sit amet cursus sit amet dictum. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus. Tempor commodo ullamcorper a lacus vestibulum sed arcu. Nisl condimentum id venenatis a condimentum vitae. Morbi tincidunt augue interdum velit euismod.
        </p>
        <p>
        Sed enim ut sem viverra aliquet eget sit. Nisl pretium fusce id velit ut tortor pretium viverra. Ut consequat semper viverra nam libero justo laoreet sit. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. A diam sollicitudin tempor id eu nisl nunc mi. Tortor at risus viverra adipiscing at in tellus integer. Arcu non sodales neque sodales ut etiam sit amet nisl. Quisque non tellus orci ac auctor augue mauris augue. Urna neque viverra justo nec. Suspendisse ultrices gravida dictum fusce. Tempus imperdiet nulla malesuada pellentesque elit eget gravida.
        </p>
        <p>
        Non curabitur gravida arcu ac. Ac odio tempor orci dapibus ultrices in iaculis nunc sed. Cursus euismod quis viverra nibh cras pulvinar. Risus viverra adipiscing at in. Proin libero nunc consequat interdum varius. In fermentum posuere urna nec tincidunt praesent semper feugiat. Aliquam ut porttitor leo a diam sollicitudin tempor id eu. Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Convallis posuere morbi leo urna. Sit amet luctus venenatis lectus. Amet nisl purus in mollis nunc sed id semper risus. Facilisi etiam dignissim diam quis enim. Massa ultricies mi quis hendrerit dolor. Id leo in vitae turpis massa sed.
        </p>
        <p>
        Lorem ipsum dolor sit amet. Tortor vitae purus faucibus ornare suspendisse sed nisi. Magnis dis parturient montes nascetur ridiculus mus. Turpis in eu mi bibendum neque. Nibh mauris cursus mattis molestie. Diam phasellus vestibulum lorem sed risus ultricies. Nulla pellentesque dignissim enim sit amet venenatis urna. Habitant morbi tristique senectus et netus et malesuada. Feugiat in fermentum posuere urna nec tincidunt praesent. Velit scelerisque in dictum non. Et pharetra pharetra massa massa.
        </p>
        <p>
        Mauris in aliquam sem fringilla ut morbi tincidunt. Non blandit massa enim nec dui nunc. Arcu dictum varius duis at consectetur lorem donec massa. Ullamcorper velit sed ullamcorper morbi tincidunt. Tortor id aliquet lectus proin nibh. Lorem donec massa sapien faucibus et. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. Nibh sit amet commodo nulla facilisi nullam. Lectus nulla at volutpat diam ut venenatis tellus in metus. Blandit turpis cursus in hac habitasse platea. Nec feugiat nisl pretium fusce id velit ut tortor pretium. Vitae nunc sed velit dignissim sodales ut eu sem integer. Suspendisse potenti nullam ac tortor. Augue eget arcu dictum varius duis at consectetur lorem donec.
        </p>
        <p>
        Sed augue lacus viverra vitae. Vestibulum rhoncus est pellentesque elit. Egestas sed sed risus pretium quam vulputate dignissim. Ante metus dictum at tempor. Massa sapien faucibus et molestie ac feugiat sed lectus vestibulum. Vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra. Donec enim diam vulputate ut pharetra sit amet. Potenti nullam ac tortor vitae purus. Lacinia quis vel eros donec ac. Fames ac turpis egestas maecenas pharetra convallis. At ultrices mi tempus imperdiet nulla malesuada. Ut ornare lectus sit amet est placerat in egestas. Ultricies leo integer malesuada nunc vel. Congue quisque egestas diam in arcu cursus euismod quis.
        </p>
        <p>
        Parturient montes nascetur ridiculus mus mauris vitae ultricies leo. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Sollicitudin ac orci phasellus egestas tellus rutrum. Libero justo laoreet sit amet cursus sit amet dictum sit. Et odio pellentesque diam volutpat commodo sed. A lacus vestibulum sed arcu non odio euismod. Eget aliquet nibh praesent tristique. Luctus accumsan tortor posuere ac ut. Condimentum vitae sapien pellentesque habitant. Tincidunt augue interdum velit euismod. Tortor condimentum lacinia quis vel eros donec ac odio tempor. Accumsan sit amet nulla facilisi morbi. Ac tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Dui faucibus in ornare quam viverra. Gravida cum sociis natoque penatibus et. Pellentesque sit amet porttitor eget dolor. Libero nunc consequat interdum varius sit amet mattis vulputate enim. Turpis massa tincidunt dui ut ornare lectus sit.
        </p>
      </main>

      <aside data-sticky="true">
        <h2>Sidebar </h2>
        <ul>
          <li>Link 1</li>
          <li>Link 2</li>
          <li>Link 3</li>
          <li>Link 4</li>
          <li>Link 5</li>
          <li>Link 6</li>
          <li>Link 7</li>
          <li>Link 8</li>
          <li>Link 9</li>
          <li>Link 10</li>
          <li>Link 11</li>
          <li>Link 12</li>
          <li>Link 13</li>
          <li>Link 14</li>
          <li>Link 15</li>
          <li>Link 16</li>
          <li>Link 17</li>
          <li>Link 18</li>
          <li>Link 19</li>
          <li>Link 20</li>
        </ul>
      </aside>
    </div>
  </body>
</html>
Joo answered 4/1, 2021 at 16:12 Comment(4)
Worked like a charm! Thanks a lot, I was close ;)Catafalque
Thanks! I recommend checking out the GitHub version as it has some improvementsJoo
I think this is the most wonderful solution, and the code is so tiny 😄 💯Fissi
Magnifique! Works beautifully. Should be the accepted answer in 2024. Thanks so much for sharing this. 💋💋💋Banksia
V
4

You can also use Sticky Sidebar JS plugin for the same effect you are wanting . It has a small and simple documentation on "How to use". I also wanted the similar scrolling effect and it did work pretty nicely.

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

Ventage answered 24/6, 2021 at 12:23 Comment(0)
C
3

Vanilla JS option!

After a while of wanting to do this with Vanilla JS, I've finally cracked it. It definitely could do with some tidying up, but it works!

  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);
Cindicindie answered 13/7, 2021 at 8:52 Comment(0)
C
1

There is a relatively unknown plugin in Wordpress repository known as WP Sticky Sidebar. The plugin does exactly what you wanted (Sticky sidebar: stick to bottom when scrolling down, top when scrolling up) WP Sticky Sidebar Wordpress repository Link: https://wordpress.org/plugins/mystickysidebar/

Clatter answered 16/3, 2018 at 9:42 Comment(1)
Thanks for the info! Worked perfectly. It's funny that behavior illustration graphic is the same for plugin featured image :)Relief
B
1

Vanilla JS implementation of https://medium.com/ right sidebar.

Demo: JSFiddle

 function addThrottledScrollEventListener(element, callback) {
    let lastScrollPosition = 0;
    let isAnimationFrameRequested = false;
    element.addEventListener("scroll", function () {
        let beforeLastScrollPosition = lastScrollPosition;
        lastScrollPosition = element.scrollY;
        if (!isAnimationFrameRequested) {
            element.requestAnimationFrame(function () {
                callback(lastScrollPosition, beforeLastScrollPosition);
                isAnimationFrameRequested = false;
            });
            isAnimationFrameRequested = true;
        }
    });
}

function setupRightSidebarScroll(sidebar) {
    let isStickToTop = false;
    let isStickToBottom = false;
    addThrottledScrollEventListener(window, (currentScrollPosition, previousScrollPosition) => {
        let isScrollingDown = previousScrollPosition < currentScrollPosition;
        let isScrollingUp = !isScrollingDown;
        let scrollTop = window.scrollY;
        let scrollBottom = scrollTop + window.innerHeight;
        let sidebarBottom = sidebar.offsetTop + sidebar.offsetHeight;
        let isAlwaysSticky = sidebar.offsetHeight <= window.innerHeight;

        if (isStickToTop && isAlwaysSticky)
            return;
        if (!isStickToTop && isScrollingUp && scrollTop <= sidebar.offsetTop || isAlwaysSticky) {
            sidebar.style.position = "sticky";
            sidebar.style.marginTop = `0px`;
            sidebar.style.top = "0px";
            isStickToTop = true;
            return;
        }
        if (isScrollingDown && isStickToTop) {
            sidebar.style.position = "relative";
            sidebar.style.top = `0px`;
            sidebar.style.marginTop = `${scrollTop}px`;
            isStickToTop = false;
            return;
        }
        if (!isStickToBottom && isScrollingDown && scrollBottom >= sidebarBottom) {
            sidebar.style.position = "sticky";
            sidebar.style.marginTop = `0px`;
            sidebar.style.top = `${window.innerHeight - sidebar.offsetHeight}px`;
            isStickToBottom = true;
            return;
        }
        if (isScrollingUp && isStickToBottom) {
            sidebar.style.position = "relative";
            sidebar.style.marginTop = `${scrollBottom - sidebar.offsetHeight}px`;
            sidebar.style.top = `0px`;
            isStickToBottom = false;
            return;
        }
    });
}
Blueberry answered 15/1, 2023 at 20:8 Comment(0)
R
0

I was looking for the exact same thing. Apparently I needed to search for some obscure terms just to find a similar question with the graphic. Turns out it's exactly what I was looking for. I couldn't find any plugins so I decided to make it myself. Hopefully someone will see this and refine it.

Here's a quick and dirty sample html I'm using.

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

Here's the jQuery I made:

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

    });
}

Some notes:

  • .rectbtfad is the bottom most element in my sidebar
  • I'm using the height of my #masthead because it's a sticky header so it needs to compensate for it
  • There's a check for col-2 float since I'm using a responsive design and don't want this activating on smaller screens

If anyone can refine this a bit more that'd be great.

Reseat answered 12/2, 2014 at 4:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.