JSFiddle - React, Tailwind, and code Playground
HTML
<div class=background>
<div class="example-header">Menus and Stuff</div>
<div class="example-container">
<div class="background-filler"></div>
</div>
<div class="example-footer">Links and contact info</div>
<div class="background-filler"></div>
</div>
<div class=foreground>
<!--followers-->
<div class="follower small">♪ I will follow you</div>
<div class="follower offset">I stop at the header and the footer</div>
<div class="follower large">
<div class="top">I'm too big for the screen...</div>
<div class="bottom">...so I scroll with you.</div>
</div>
</div>
CSS
.follower {
position: sticky;
top: 0;
}
.follower.large {
max-height: 100vh;
max-height: 100dvh; /* iOS dynamic viewport height */
overflow-y: auto;
}
.bottom {
margin-top: 110vh;
}
body {
position: relative;
}
.foreground {
position: absolute;
top: 0;
height: 100%;
-z-index: 1;
}
.background-filler {
background-color: #ADD8E6;
color: #00008B;
padding: 5px;
}
.example-footer, .example-header{
background-color: darkblue;
color: #FFF;
font-weight: bold;
height: 40px;
text-align: center;
}
.follower {
box-sizing: border-box;
padding: 20px;
width: 150px;
color: #FFF;
}
.follower.small {
background-color: #008000;
}
.follower.offset {
background-color: red;
margin-left: 175px;
}
.follower.large {
background-color: #5C0080;
border: 5px solid #BB3E99;
margin-left: 350px;
}
JavaScript
/**
* Makes the element follow the screen (within the element's parent
* or nearest ancestor having a position) as the user scrolls up and down
* a page. Optionally, you can specify stopping points within the parent
* where the element will cease following (e.g. at a header or footer).
*/
/*/
(function( $ ){
function _pegToScreenTop($element){
$element.css({
'top':0,
'bottom':''
});
};
function _pegToScreenBottom($element){
$element.css({
'top':'',
'bottom':0
});
};
function _pegToFollowTop($element, followTop, screenTop){
$element.css({
'top': followTop - screenTop,
'bottom':''
});
};
function _pegToFollowBottom($element, followBottom, screenBottom){
$element.css({
'top':'',
'bottom': screenBottom - followBottom
});
};
function _scrollEl($element, distance){
var oldTop = $element.offset().top - $(window).scrollTop();
$element.css({
'top': oldTop - (distance || 0),
'bottom':''
});
}
function follow(event){
var $window = $(window),
settings = event.data.settings,
$element = event.data.follower,
elHeight = $element.outerHeight(),
elTop = $element.offset().top,
elBottom = elTop + elHeight,
isShorterThanScreen = elHeight < $window.height(),
screenTop = $window.scrollTop(),
screenBottom = screenTop + $window.height(),
isFollowTopPxVisible = screenTop - settings.topPixel <= 0,
isFollowBottomPxVisible = settings.bottomPixel - screenBottom <= 0,
prevScreenTop = ($element.data('followScreen') || 0),
scrollDistance = screenTop - prevScreenTop;
if(elHeight < settings.bottomPixel - settings.topPixel){ //El is capable of scrolling
if( isShorterThanScreen ){
if( isFollowTopPxVisible ){
_pegToFollowTop($element, settings.topPixel, screenTop);
} else if( isFollowBottomPxVisible && (settings.bottomPixel - screenTop < elHeight)){
_pegToFollowBottom($element, settings.bottomPixel, screenBottom);
} else...