I’ve taken jnns answer and updated it so that it is smooth between scrolls like sticky kit may have been. The only issue is that it required a magic number for a containing div s.t. the container maintains it’s size while the div is absolutely positioned – this might be solved in your code by a css variable.
window.onscroll = function (e) {
if (window.scrollY < this.prevScrollY) {
// Track position state of nav
// 1 == stuck to top
// 0 == absolute positioning
// -1 == stuck to bottom
this.stick_pos = scrollUpwards(this.stick_pos);
} else {
this.stick_pos = scrollDownwards(this.stick_pos);
}
this.prevScrollY = window.scrollY;
}
function scrollUpwards(stick_pos) {
// If the element is already stuck to the top then we are fine
if(stick_pos === 1) return stick_pos;
// Figure out where the new window will be after scroll
let aside = $("aside").get(0);
let aboveAside = aside.getBoundingClientRect().top > 0;
// If we are going above the element then we know we must stick
// it to the top
if (aboveAside){
$("aside").css("position", "sticky")
.css("top", 0)
.css("bottom", '')
.css("align-self", "flex-start");
return 1;
}
// If it will still be below the top of the element, then we
// must absolutely position it to its current position - if it already is absolutely positioned then we do nothing
if (stick_pos == 0) return stick_pos;
// Undo the stick to the bottom
// First get the current position
$("aside")
.css("top", aside.offsetTop)
.css("position", "absolute")
.css("bottom", '')
.css("align-self", "");
return 0;
}
function scrollDownwards(stick_pos) {
/*
let aside = $("aside").get(0);
let aboveAside = aside.offsetTop >= window.scrollY;
let browser_bottom = window.scrollY + window.innerHeight;
let aside_bottom = aside.offsetTop + aside.offsetHeight;
let belowAside = browser_bottom >= aside_bottom;
if (aboveAside) {
//console.log("stick to bottom");
$("aside").css("top", '');
$("aside").css("bottom", 0);
$("aside").css("align-self", "flex-end");
}
*/
// If the element is already stuck to the bottom then we are fine
if(stick_pos === -1) return stick_pos;
// Figure out where the new window will be after scroll
let aside = $("aside").get(0);
let browser_bottom = window.innerHeight;
let aside_bottom = aside.getBoundingClientRect().top + aside.offsetHeight;
let belowAside = browser_bottom > aside_bottom;
// If we are going below the element then we know we must stick
// it to the bottom.
if (belowAside){
$("aside").css("position", "sticky")
.css("top", '')
.css("bottom", 0)
.css("align-self", "flex-end");
return -1;
}
// If it will still be above the bottom of the element, then we
// must absolutely position it to its current position - if it already is absolutely positioned then we do nothing
if (stick_pos == 0) return stick_pos;
// Undo the stick to the top
// First get the current position
// $("aside").css("position", "absolute")
// .css("top", aside.offsetTop);
$("aside")
.css("top", aside.offsetTop)
.css("position", "absolute")
.css("bottom", '')
.css("align-self", "");
return 0;
}
div#section {
/* begin: irrelevant styling */
margin: 5em auto;
padding: 0.625rem;
max-width: 300px;
font-family: sans-serif;
font-size: 18px;
line-height: 1.5em;
text-align: justify;
background-color: #dbe4ee;
/* end: irrelevant styling */
display: flex;
justify-content: space-around;
}
div#section div#nav-container {
position: relative;
display: flex;
min-width: 2em;
}
div#section div#nav-container aside {
position: sticky;
align-self: flex-start;
/* begin: irrelevant styling */
background-color: #81a4cd;
color: white;
text-align: center;
width: 2em;
}
div#section div#nav-container aside div {
padding: 0 .3em;
}
div#section article {
margin-left: 0.5em;
}
div#section article p {
margin: 0;
}
div#section article p + p {
margin-top: 1.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='section'>
<div id='nav-container'>
<aside>
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
<div>H</div>
<div>I</div>
<div>J</div>
<div>K</div>
<div>L</div>
<div>M</div>
<div>N</div>
<div>O</div>
<div>P</div>
<div>Q</div>
<div>R</div>
<div>S</div>
<div>T</div>
<div>U</div>
<div>V</div>
<div>W</div>
<div>X</div>
<div>Y</div>
<div>Z</div>
</aside>
</div>
<article>
<p>Perferendis ut iusto voluptatem ex temporibus aut autem amet. Sit vero in soluta. Est officia asperiores tenetur vel quam nostrum eum facere. Sed totam quasi libero at facilis doloremque. Non aut velit odio. Tempora dolore sunt recusandae sed quia
sunt.</p>
<p>Voluptatem optio asperiores dolorem voluptatem. Ipsa alias perspiciatis doloribus est nisi ut. Fuga aut et vitae consequatur dolor corrupti aut minima.</p>
<p>Facilis et ut eligendi. Excepturi labore asperiores vero. Perferendis porro sunt molestiae. In sit dolorem eum esse sit inventore est. Atque perspiciatis commodi nihil.</p>
<p>Consequatur ipsa id repellendus voluptatem perspiciatis temporibus. Praesentium eveniet nemo laudantium inventore similique impedit nihil esse. Maiores iste commodi molestiae quas odit nihil ex corrupti. Illum id amet non vero.</p>
<p>Voluptas soluta itaque et. Aperiam quasi sint eos ullam. Assumenda facilis omnis alias numquam. Odio quia esse vel et minima soluta architecto. Qui saepe consequatur aut rerum. Et et aut voluptatibus inventore.</p>
<p>Perferendis ut iusto voluptatem ex temporibus aut autem amet. Sit vero in soluta. Est officia asperiores tenetur vel quam nostrum eum facere. Sed totam quasi libero at facilis doloremque. Non aut velit odio. Tempora dolore sunt recusandae sed quia sunt.</p>
<p>Voluptatem optio asperiores dolorem voluptatem. Ipsa alias perspiciatis doloribus est nisi ut. Fuga aut et vitae consequatur dolor corrupti aut minima.</p>
<p>Facilis et ut eligendi. Excepturi labore asperiores vero. Perferendis porro sunt molestiae. In sit dolorem eum esse sit inventore est. Atque perspiciatis commodi nihil.</p>
<p>Consequatur ipsa id repellendus voluptatem perspiciatis temporibus. Praesentium eveniet nemo laudantium inventore similique impedit nihil esse. Maiores iste commodi molestiae quas odit nihil ex corrupti. Illum id amet non vero.</p>
<p>Voluptas soluta itaque et. Aperiam quasi sint eos ullam. Assumenda facilis omnis alias numquam. Odio quia esse vel et minima soluta architecto. Qui saepe consequatur aut rerum. Et et aut voluptatibus inventore.</p>
</div>