Reputation: 786
I have a container thisSticks
that I have to fix
in another container stickInContainer
on scroll. Basically, replicate CSS sticky
behaviour. I could have just used sticky
, but it doesn't work in all browsers. So I am making it in pure javascript.
Current Behaviour: In the demo below, grey container should never overlap with blue footer
container, but it does.
Expected Behaviour: When the bottom of thisSticks
hits top of footer
, it should stay there and when user scrolls back up and reaches top of thisSticks
, it should stick back to top of stickInContainer
till it reaches its initial position.
I can think of incrementing stickyDiv.style.bottom
on every scroll after thisSticks
bottom hits top of footer
.
How will this work, Is there another approach?
window.onscroll = function() {
myFunction();
}
const stickyDiv = document.getElementById('thisSticks');
const stickyDivHeight = stickyDiv.offsetTop;
function myFunction() {
if (window.pageYOffset > stickyDivHeight) {
stickyDiv.style.position = 'fixed';
stickyDiv.style.top = 0;
} else {
stickyDiv.style.position = 'initial';
}
}
#topSection {
height: 100px;
}
#stickInContainer {
height: 800px;
}
#thisSticks {
width: 100%;
height: 40px;
opacity: 0.7;
background-color: grey;
}
#footer {
width: 100%;
background-color: blue;
height: 500px;
}
<div id='topSection'>Top Section</div>
<div id='stickInContainer'>
<div id='thisSticks'></div>
</div>
<div id='footer' />
Upvotes: 3
Views: 815
Reputation: 272842
You can add another condition to test when the footer reach the top minus the height of the sticky element. If it's the case you change the top
differently:
window.onscroll = function() {
myFunction();
}
const stickyDiv = document.getElementById('thisSticks');
const footer = document.getElementById('footer');
const stickyDivHeight = stickyDiv.offsetTop;
const Height = stickyDiv.clientHeight; /*height of the sticky element*/
const footerHeight = footer.offsetTop; /*footer offset*/
function myFunction() {
if (window.pageYOffset > stickyDivHeight ) {
stickyDiv.style.position = 'fixed';
stickyDiv.style.top = 0;
} else {
stickyDiv.style.position = 'initial';
}
/*Here the sticky will touch the footer and top will be negative*/
if(window.pageYOffset>(footerHeight - Height)) {
stickyDiv.style.top = (footerHeight - Height)-window.pageYOffset + "px";
}
}
#topSection {
height: 100px;
}
#stickInContainer {
height: 800px;
}
#thisSticks {
left:0;
right:0;
height: 40px;
opacity: 0.7;
background-color: grey;
}
#footer {
background-color: blue;
height: 500px;
}
body {
margin:0;
}
<div id='topSection'>Top Section</div>
<div id='stickInContainer'>
<div id='thisSticks'></div>
</div>
<div id='footer' ></div>
Upvotes: 1
Reputation: 532
You need another condition to check if it hit the bottom of your stickInContainer
. You can achieve this in different ways, you can check style bottom as you mentioned or footer top maybe, but since you have a container, I have prefered the approach below.
I edited code your a little by defining a limit that points to your container's bottom
var stickyLimit = stickyDivContainer.offsetHeight + stickyDivContainer.offsetTop - stickyDiv.offsetHeight
and added a condition to your into your if block to make stickyDiv
stop and wait there.
else if(window.pageYOffset>=stickyLimit ){
stickyDiv.style.position = 'static';
stickyDiv.style.top = stickyLimit;
}
I hope this is what you are looking for, i also suggest making some transition effect to stickyDiv
where it changes its position behaviour, because checking scrolls from offset values and making changes to position style doesn't feel smooth.
window.onscroll = function() {
myFunction();
}
const stickyDiv = document.getElementById('thisSticks');
const stickyDivContainer = document.getElementById('stickInContainer');
const stickyDivHeight = stickyDiv.offsetTop;
function myFunction() {
var stickyDivBottom = stickyDiv.scrollTop + stickyDiv.offsetHeight;
var stickyLimit = stickyDivContainer.offsetHeight + stickyDivContainer.offsetTop - stickyDiv.offsetHeight;
if (window.pageYOffset > stickyDivHeight && window.pageYOffset<stickyLimit ) {
stickyDiv.style.position = 'fixed';
stickyDiv.style.top = 0;
}else if(window.pageYOffset>=stickyLimit ){
stickyDiv.style.position = 'static';
stickyDiv.style.top = stickyLimit;
}else {
stickyDiv.style.position = 'initial';
}
}
#topSection {
height: 100px;
}
#stickInContainer {
height: 800px;
}
#thisSticks {
width: 100%;
height: 40px;
opacity: 0.7;
background-color: grey;
}
#footer {
width: 100%;
background-color: blue;
height: 500px;
}
<div id='topSection'>Top Section</div>
<div id='stickInContainer'>
<div id='thisSticks'></div>
</div>
<div id='footer' />
Upvotes: 0