I found posts and online articles on how to do something like this but most examples are not in plain JavaScript. So this script works almost perfectly if all the sections are the same height for example 220px. So I thought I was getting closer in having this script working how I want it to work like overtime but then I realize
it had flaws when I decided to change the sections height and play around with the code more to see if it had any flaws that I was unaware of so basically this script is designed to output the name
of the sections that are visible but it is not showing the correct output for example if section 1 is the only one that is visible in the div it will say section-1 if multiple sections are visible it will say for example section-1,section-2 etc. Basically it should work like this regardless of the sections height


I know I have to change the code or altered it but I'm getting more confused the more I play around with it so how can I pull this off so I can always have the correct output? If I have to change my code completely to be able to do this then I don't mind.
This is my code
document.addEventListener('DOMContentLoaded',function(){
document.querySelector('#building').addEventListener('scroll',whichSectionsAreInSight);
function whichSectionsAreInSight(){
var building= document.querySelector('#building');
var top = building.scrollTop;
var bottom = top+building.offsetHeight;
var arr = [];
Array.prototype.forEach.call(
building.querySelectorAll('#building .sections'),
function(sections){
if ((sections.offsetTop < top && top <sections.offsetTop+sections.offsetHeight) || (sections.offsetTop < bottom && bottom < sections.offsetTop+sections.offsetHeight)){
arr.push(sections.id);
}
}
);
document.querySelector('#status').innerHTML = arr.join(',')
}
whichSectionsAreInSight();
});
h1{
margin: 0;
text-align: center;
}
#building{
background-color: gray;
height: 200px;
width: 200px;
overflow: auto;
}
.sections{
height: 80px;
width: 100%;
}
#section-1{
background-color: dodgerblue;
}
#section-2{
background-color: gold;
}
#section-3{
background-color: red;
}
#section-4{
background-color: gray;
height: 220px;
}
<p id='status'></p>
<div id='building'>
<div id='section-1' class='sections'><h1>Section 1</h1></div>
<div id='section-2' class='sections'><h1>Section 2</h1></div>
<div id='section-3' class='sections'><h1>Section 3</h1></div>
<div id='section-4' class='sections'><h1>Section 4</h1></div>
</div>
You were pretty close!
First off, you need to set the parent element to position:relative otherwise the parent that is being measured against is the document.
Also, the algorithm is simpler than what you had. Just make sure that the top of the element is less than the bottom of the parent, and the bottom of the element is greater than the top of the parent.
In your case this is offsetTop < bottom and offsetTop + offsetHeight > top
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#building').addEventListener('scroll', whichSectionsAreInSight);
function whichSectionsAreInSight() {
var building = document.querySelector('#building');
var top = building.scrollTop;
var bottom = top + building.offsetHeight;
var arr = [];
Array.prototype.forEach.call(
building.querySelectorAll('#building .sections'),
function(section) {
if (section.offsetTop < bottom && section.offsetTop + section.offsetHeight > top) {
arr.push(section.id);
}
}
);
document.querySelector('#status').innerHTML = arr.join(',')
}
whichSectionsAreInSight();
});
h1 {
margin: 0;
text-align: center;
}
#building {
background-color: gray;
height: 200px;
width: 200px;
overflow: auto;
position: relative;
}
.sections {
height: 80px;
width: 100%;
}
#section-1 {
background-color: dodgerblue;
}
#section-2 {
background-color: gold;
}
#section-3 {
background-color: red;
}
#section-4 {
background-color: gray;
height: 220px;
}
<p id='status'></p>
<div id='building'>
<div id='section-1' class='sections'>
<h1>Section 1</h1>
</div>
<div id='section-2' class='sections'>
<h1>Section 2</h1>
</div>
<div id='section-3' class='sections'>
<h1>Section 3</h1>
</div>
<div id='section-4' class='sections'>
<h1>Section 4</h1>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With