I am building a blog post layout which requires some metadata to sit on one side and stay in place as the content scrolls, using position: sticky
.
This works fine but some types of content stretch to 100% width, so collide with the metadata as they scroll by. I am looking to run an event listener on scroll which compares the position of both and adds a class to the sticky element, giving it opacity:0
as the other passes over it.
This works fine when there is only one full width (.fw
) element on the page:
window.addEventListener('scroll', function() {
var a = document.querySelector('.postmeta-sticky').getBoundingClientRect(),
b = document.querySelector('.fw').getBoundingClientRect();
if((b.top <= (a.top a.height)) && ((b.top b.height) > a.top)) {
$(".postmeta-wrap").addClass("overlap");
} else {
$(".postmeta-wrap").removeClass("overlap");
}
});
However, the post content is created dynamically and there may be more than one .fw
per page. I am therefore trying to gather all instances using querySelectorAll
for my second variable, but I cannot get this to work.
I am this far in:
window.addEventListener('scroll', function(){
var a = document.querySelector(".postmeta-sticky").getBoundingClientRect(),
objects = document.querySelectorAll(".fw");
objects.forEach(function(object) {
b = object.getBoundingClientRect();
if ((b.top <= (a.top a.height)) && ((b.top b.height) > a.top)) {
$(".postmeta-wrap").addClass("overlap");
} else {
$(".postmeta-wrap").removeClass("overlap");
}
});
});
But it just isn't working. Doubtless I have made some obvious error or omission.
First instance only working in situ: https://hba.matmartin.studio/henry-v-donmar-warehouse/
Simplified codepen: https://codepen.io/MMS_/pen/VwQvvpm
With thanks to anyone who can help.
jQuery(document).ready(function($) {
window.addEventListener('scroll', function() {
var a = document.querySelector(".sticky-content").getBoundingClientRect(),
objects = document.querySelectorAll(".fw");
objects.forEach(function(object) {
b = object.getBoundingClientRect();
if ((b.top <= (a.top a.height)) && ((b.top b.height) > a.top)) {
$(".sticky-wrap").addClass("overlap");
} else {
$(".sticky-wrap").removeClass("overlap");
}
});
});
});
.content {
box-sizing: border-box;
position: relative;
}
.sticky-wrap {
position: absolute;
height: 100%;
width: 33%;
z-index: 0;
}
.sticky-wrap.overlap {
opacity: 0;
}
.sticky-content {
position: sticky;
top: 0;
left: 0;
width: 100%;
height: 112px;
padding: 24px 0;
background: #e9e9e9;
}
.scrolling-content {
width: 100%;
position: relative;
z-index: 1;
}
.scrolling-element {
width: 66%;
height: 160px;
background: #d56d56;
margin: 0 0 48px auto;
}
.scrolling-element.fw {
width: 100%;
background: #9dc9dc;
opacity: 0.5;
}
.page-head {
width: 100%;
height: 72px;
background: #F6F6F6;
}
.page-end {
width: 100%;
height: 480px;
background: #383838;
}
<div ></div>
<div >
<div >
<div >
<ul>
<li>This info</li>
<li>sticks around</li>
<li>for a bit</li>
</ul>
</div>
</div>
<div >
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
</div>
</div>
<div ></div>
<script src="https://code.jquery.com/jquery-1.12.3.js" integrity="sha256-1XMpEtA4eKXNNpXcJ1pmMPs8JV nwLdEqwiJeCQEkyc=" crossorigin="anonymous"></script>
CodePudding user response:
The code below should achieve the behavior you're looking for. The problem was that the later .fw
elements in the list were updating the visibility of the meta element.
I changed the loop to a for...of
format and added a break to stop the loop when it is hidden, and did a bit of refactoring.
Hope this works!
window.addEventListener('scroll', function(){
var sticky = document.querySelector(".sticky-content");
var a = sticky.getBoundingClientRect();
var objects = document.querySelectorAll(".fw");
for (object of objects) {
b = object.getBoundingClientRect();
if ((b.top <= (a.top a.height)) && ((b.top b.height) > a.top)) {
sticky.parentNode.classList.add("overlap");
break;
} else {
sticky.parentNode.classList.remove("overlap");
}
}
});