1

I'm trying to create a script that will match div ids that scroll into view with the corresponding children in a gallery. I don't want to have to create individual scrollTop codes for each div id—so needing some kind of variable for the index of each div id? I've struggled to find anything close online.

This is the simple scrollTop code I am using as an example. When the "in-view" class is applied, the corresponding gallery items change their opacity.

<script>
$(function(){
    $(document).scroll(function(){
        if($(this).scrollTop() >= $("#item-1").offset().top - 250) {
            $(".sticky-gallery .image-item:nth-child(1)").addClass("in-view");
        } else {
            $(".sticky-gallery .image-item:nth-child(1)").removeClass("in-view");
        }
    });
});
</script>

I'm hoping there's a way to create something that can flexibly work for #item-1 with nth-child(1), #item-2 with nth-child(2), etc...

Thank you for any guidance.

Cs238975
  • 31
  • 7

1 Answers1

1

I think you can do this very simply by pairing off an array of the div elements with an array of the gallery elements. See the code below for a basic example.

This satisfies the requirements:

  • matching scrolling divs with gallery items
  • changing gallery item's styling when matching div in view
  • no ids required on divs, and indeed no ids equired on gallery items

var sections;
var galleryItems;
function getViewScrollingElements() {
    sections = document.getElementsByClassName("section");
    galleryItems = document.getElementsByClassName("item");
    //  Do first check before a scroll could have occured
    checkInView();
}

function checkInView () {
    var boundingRect;
    for ( var i = 0; i < sections.length; i++ ) {
        //  Get the extremities of the div
        boundingRect = sections[i].getBoundingClientRect();
        //  Are the div's extremities in view
        if ( boundingRect.top < window.innerHeight && boundingRect.bottom >= 0 ) {
            galleryItems[i].style.opacity = "1";
        } else {
            galleryItems[i].style.opacity = "0.2";
        }
    }
}
/*  The gallery */

.gallery {
    position: fixed;
    top: 2vh;
    background: none;
    border: 2px solid red;
}

.item {
    opacity: 0.2;
    display: inline-block;
    border: 2px solid black;
    padding: 2px;
    margin: 2px;
}


/* The scrolling items */

.section {
    height: 40vh;
}

/* Make sections stand out.*/

.scroll_container > div:nth-of-type(odd).section {
    background: pink;
}

.scroll_container > div:nth-of-type(even).section {
    background: wheat;
}
<body onLoad="getViewScrollingElements()" onScroll="checkInView()">

<div class="gallery">
    <div class="item">
        <p>Item 1</p>
    </div>
    <div class="item">
        <p>Item 2</p>
    </div>
    <div class="item">
        <p>Item 3</p>
    </div>
    <div class="item">
        <p>Item 4</p>
    </div>
    <div class="item">
        <p>Item 5</p>
    </div>
    <div class="item">
        <p>Item 6</p>
    </div>
    <div class="item">
        <p>Item 7</p>
    </div>
    <div class="item">
        <p>Item 8</p>
    </div>
    <div class="item">
        <p>Item 9</p>
    </div>
    <div class="item">
        <p>Item 10</p>
    </div>
    <div class="item">
        <p>Item 11</p>
    </div>
    <div class="item">
        <p>Item 12</p>
    </div>
    <div class="item">
        <p>Item 13</p>
    </div>
    <div class="item">
        <p>Item 14</p>
    </div>
    <div class="item">
        <p>Item 15</p>
    </div>
    <div class="item">
        <p>Item 16</p>
    </div>
    <div class="item">
        <p>Item 17</p>
    </div>
    <div class="item">
        <p>Item 18</p>
    </div>
</div>

<div class="scroll_container">
    <div class="section">
        <p>Section 1</p>
    </div>
    <div class="section">
        <p>Section 2</p>
    </div>
    <div class="section">
        <p>Section 3</p>
    </div>
    <div class="section">
        <p>Section 4</p>
    </div>
    <div class="section">
        <p>Section 5</p>
    </div>
    <div class="section">
        <p>Section 6</p>
    </div>
    <div class="section">
        <p>Section 7</p>
    </div>
    <div class="section">
        <p>Section 8</p>
    </div>
    <div class="section">
        <p>Section 9</p>
    </div>
    <div class="section">
        <p>Section 10</p>
    </div>
    <div class="section">
        <p>Section 11</p>
    </div>
    <div class="section">
        <p>Section 12</p>
    </div>
    <div class="section">
        <p>Section 13</p>
    </div>
    <div class="section">
        <p>Section 14</p>
    </div>
    <div class="section">
        <p>Section 15</p>
    </div>
    <div class="section">
        <p>Section 16</p>
    </div>
    <div class="section">
        <p>Section 17</p>
    </div>
    <div class="section">
        <p>Section 18</p>
    </div>
</div>

</body>
petern0691
  • 868
  • 4
  • 11
  • 1
    I was able to get this working perfectly for what I needed! I wanted to add an offset so I updated it to be if ( boundingRect.top < window.innerHeight - 400 && boundingRect.bottom >= 0 ) { — it seems like that works, but is that the right way to do it? Thanks for your reply! – Cs238975 Sep 29 '22 at 20:48
  • Yes. Depending on exactly when you want the div to be considered "in view" you adjust the arithmetic of the comaprison operators accordingly. – petern0691 Sep 29 '22 at 22:39
  • See also the second answer here: https://stackoverflow.com/questions/487073/how-to-check-if-element-is-visible-after-scrolling – petern0691 Sep 30 '22 at 13:41