I've created a sticky sidebar for my blog, but now I need the sticky element to stop scrolling when I reach the footer. The reason is because the sidebar is overlapping the elements in the footer. How can I solve this?
Working fiddle with overlapping problem:
https://jsfiddle.net/j7x5hLy3/
This is EXACTLY what I'm trying to achieve:
https://abouolia.github.io/sticky-sidebar/examples/basic.html
Look what happens when the sidebar reaches the bottom. I AM NOT TRYING TO USE Z-INDEX. I'm saying this because in some other questions people are posting "solutions" that uses z-index. I'm not trying to hide anything, I'm trying to make it stop scrolling when it reaches the footer.
jQuery(document).ready(function($) {
function isScrolledTo(elem) {
var docViewTop = $(window).scrollTop(); //num of pixels hidden above current screen
var docViewBottom = docViewTop $(window).height();
var elemTop = $(elem).offset().top; //num of pixels above the elem
var elemBottom = elemTop $(elem).height();
return ((elemTop <= docViewTop));
}
var catcher = $('#bannernormal');
var sticky = $('#bannerfixo');
if ($(window).width() >= 100) {
$(window).scroll(function() {
if (isScrolledTo(sticky)) {
sticky.css('position', 'fixed');
sticky.css('top', '0px');
}
var stopHeight = catcher.offset().top catcher.height();
if (stopHeight > sticky.offset().top) {
sticky.css('position', 'absolute');
sticky.css('top', stopHeight);
}
});
} else {
$(window).unbind('scroll');
}
});
#bannernormal {
margin: auto;
display: table;
width: 200px;
height: 400px;
border: 1px solid #000;
margin: 5px;
}
#bannerfixo {
margin: 5px;
width: 200px;
height: 400px;
border: 1px solid #000;
margin: 5px;
}
#sidebar {
float: left;
}
#content {
float: right;
}
#footer {
display: block;
clear: both;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div id="content">
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
</div>
<div id="sidebar">
<div id="bannernormal">
This is the "catcher" <code>div</code>
</div>
<div id="bannerfixo" style="position: absolute; top: 413px;">
This is the "sticky" <code>div</code>
</div>
</div>
<div id="footer">Everything should stop before this part.
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
</div>
CodePudding user response:
In an effort to keep it simple, here are three nested divs.
The root div represents the root of you document (usually <body
)
The content can be any div, as long as it has position: relative
The div <div id="relativeTop">
should have position: absolute
. relativeTop
will now position itself inside the parent, but you can position it explicitly using top, right, bottom and left. If the parent is not relative
, it's children will be free to leave it's bounds and therefor will position it's children relative to the window instead.
In javascript, I listen to the scroll event
document.addEventListener('scroll', (e) => {
This is were you can set the top or bottom value. Look at the check:
if (window.scrollY rect.height > parentRect.height) {
If true, you'll know the div would en up outside of the parent, and you can set top: 0px
to have it stick to the bottom of it's parent.
Otherwise, you set the top value to the scroll position of the document:
el.style.top = window.scrollY "px";
document.addEventListener('scroll', (e) => {
const el = document.getElementById("relativeTop");
const parent = el.parentNode;
const parentRect = parent.getBoundingClientRect();
const rect = el.getBoundingClientRect();
if (window.scrollY rect.height > parentRect.height) {
el.style.bottom = "0px";
} else {
el.style.top = window.scrollY "px";
}
});
#body {
border: 1px dotted yellow;
height: 1500px;
}
#content {
position: relative;
border: 1px dotted red;
height: 1000px;
margin: 10px;
width: 2000px;
}
#relativeTop {
border: 1px dotted blue;
position: absolute;
left: 0;
width: 200px;
height: 100px;
}
<div id="body">
<div id="content">
<div id="relativeTop">
</div>
</div>
</div>
CodePudding user response:
.container {
display: flex;
margin-bottom: 10px;
}
.section {
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
.sidebar {
width: 180px;
height: 160px;
background: green;
margin-right: 10px;
}
.normal {
background: yellow;
margin-bottom: 10px;
}
.sticky {
background: red;
position: sticky;
top: 0;
}
.content {
width: 100%;
background: lightgray;
}
.footer {
background: pink;
height: 800px;
}
<div>
<div class="container">
<div>
<div class="sidebar normal section">
Normal
</div>
<div class="sidebar sticky section">
Sticky
</div>
</div>
<div class="content">
Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
</div>
</div>
<div class="footer section">
Footer
</div>
</div>