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

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
andbamnan
  • 1,285
  • 2
  • 11
  • 8
  • 1
    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 `top` – Jules Colle May 21 '21 at 12:36
  • Can't edit my original comment anymore. But here's the code that made this possible in the WP admin interface: https://core.trac.wordpress.org/changeset/26125 (related track ticket: https://core.trac.wordpress.org/ticket/19994) – Jules Colle May 21 '21 at 12:46
  • Is there a 2021 solution to this problem? – user5185370 Nov 15 '21 at 17:22

9 Answers9

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.

Emre Erkan
  • 8,433
  • 3
  • 48
  • 53
gmo
  • 8,860
  • 3
  • 40
  • 51
  • 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 ? – VijayRana Jan 10 '18 at 19:16
  • Hi @gmo ! 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... – Igor Laszlo Nov 11 '19 at 20:39
  • Project seems to be abandoned. Even the demo page is no longer working. – Jules Colle May 21 '21 at 13:20
  • 1
    @JulesColle - yes, even the demos are not working. There's another project - https://abouolia.github.io/sticky-sidebar/ Try this out. – Anoop Naik Sep 24 '21 at 11:11
  • @AnoopNaik looks nice. I guess this answer needs some more upvotes: https://stackoverflow.com/a/68115705/296430 – Jules Colle Sep 28 '21 at 08:01
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!

Travis Kriplean
  • 426
  • 5
  • 10
  • 2
    To anyone searching for an answer, this one by Travis is the most flawless that I've found so far. Thanks man. – marcovega Sep 04 '15 at 07:24
  • 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. – jClark Apr 20 '16 at 00:49
  • 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! – Christophe Marois Mar 20 '17 at 21:06
  • @Cristophe Marois can you provide an example on jsfiddle please? – Darme Jul 07 '19 at 10:21
  • thanks, but this code not work for small sidebar that shorter of viewport (height of viewport) – Seyed Abbas Seyedi Oct 10 '19 at 06:00
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.

Anoop Naik
  • 335
  • 7
  • 15
  • see this answer and explain http://stackoverflow.com/questions/28428327/how-use-sidebar-position-when-scoll-up – theinlwin Feb 10 '15 at 10:59
  • @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 ? – Igor Laszlo Nov 11 '19 at 21:28
  • 1
    @IgorLaszlo sure, gimme some time, will update you in some time... – Anoop Naik Nov 11 '19 at 21:32
  • 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 (https://stackoverflow.com/questions/47618271/position-sticky-scrollable-when-longer-than-viewport) – Igor Laszlo Nov 12 '19 at 13:31
  • @Anoop Naik ! Thanks for your effort but let it please, I found Sticky jquery plugin to resolve my problem : https://abouolia.github.io/sticky-sidebar/ Thank you again ! – Igor Laszlo Nov 12 '19 at 14:17
  • 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. @AnoopNaik – Maëlle Jan 08 '20 at 12:30
  • 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. – peppy Aug 02 '22 at 01:33
7

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

Dharman
  • 30,962
  • 25
  • 85
  • 135
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);
JakePowell
  • 90
  • 6
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/

  • Thanks for the info! Worked perfectly. It's funny that behavior illustration graphic is the same for plugin featured image :) – Oksana Romaniv Oct 03 '18 at 12:06
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.

0

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;
        }
    });
}
Max
  • 46
  • 1
  • 5