Search code examples
javascripthtmlcssoverlappingintersection-observer

Intersection Observer makes text overlap with header


Good day everyone,

I have tried to create a scrolling animation for text to appear when visible to atleast 50%. The only code I have is an animated Header with Onscroll Event and the Intersection Observer for the Text. It works just fine, the only thing I can't figure out is, when you scroll fast up and down, the Text will randomly scroll through the header and appear on top of everything...

I've added borders so you can see them overlapping with the header. Can someone help me figure out how to make the Text stay behind the header at all time?

Thank you very much!

Greetings Marcel

var navbar = document.getElementById("navbar");
var nav = document.getElementById("nav");
var placeholder = document.getElementById("navbar_placeholder");
var sticky = navbar.offsetTop;

window.onscroll = function() {myFunction()};
function myFunction() {
    if (window.pageYOffset > sticky) {
        navbar.classList.add("sticky");
        // placeholder.classList.add("display");
        nav.classList.add("shrink");
    } else {
        navbar.classList.remove("sticky");
        // placeholder.classList.remove("display");
        nav.classList.remove("shrink");
    }
}
const options = {threshold: 0.5};

const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
        console.log(entry)
        if (entry.isIntersecting) {
            entry.target.classList.add('show');
        } else {
            entry.target.classList.remove('show');
        }
    });
}, options);

const hiddenElements = document.querySelectorAll('.hidden');
hiddenElements.forEach((el) => observer.observe(el));
:root{
    --background-color: #001728;
    --darker-background-color: #000000;
    --accent-color: #20cc5b;
    --text-color: #FFFFFF;
    --navbar-height: 80px;
}
html{
    height: 100%;
}
body{
    height: 100%;
    background-color: var(--background-color);
}
nav{
    height: var(--navbar-height);
    background-color: red;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 4px solid var(--accent-color);
    transition-property: height;
    transition-duration: 0.5s;
}
.navbar {
  position:absolute;
  left:0;
  right:0;
  top:0;
}
.navbar-placeholder {
    position:relative;
    height:80px;
    transition: height 0.5s;
}
.text1{
    padding: 30px;
  color: white;
}
.sticky {
    position: fixed;
    top: 0;
    width: 100%;
}
.disappear {
    opacity: 0%;
    transition-duration: 0.5s;

}
.shrink {
    height: 40px;
    transition-property: height;
    transition-duration: 0.5s;
}
.display {
    display: block;
    height: var(--navbar-height);
}
h1, p{
  font-size: 50px;
  color: white;
}
section {
    display: grid;
    place-items: center;
    align-content: center;
    min-height: 100vh;
    border: 5px solid white;
}
.hidden {
    opacity: 0;
    transition: all 1s;
}

.show {
    opacity: 1;
    transition: all 1s;
}
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WeSoDev</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
<div id="navbar_placeholder" class="navbar-placeholder">
<div id="navbar">
    <nav id="nav">
      <h2 id="header">header</h2>
    </nav>
</div>  
</div>
      <section class="hidden">
        <h1>Test</h1>
        <p>Hello</p>
    </section>
    <section class="hidden">
        <h1>Test</h1>
        <p>Hello</p>
    </section>
    <section class="hidden">
        <h1>Test</h1>
        <p>Hello</p>
    </section>

    <script src="index.js"></script>
</body>
</html>


Solution

  • var navbar = document.getElementById("navbar");
    var nav = document.getElementById("nav");
    var placeholder = document.getElementById("navbar_placeholder");
    var sticky = navbar.offsetTop;
    
    window.onscroll = function() {myFunction()};
    function myFunction() {
        if (window.pageYOffset > sticky) {
            navbar.classList.add("sticky");
            // placeholder.classList.add("display");
            nav.classList.add("shrink");
        } else {
            navbar.classList.remove("sticky");
            // placeholder.classList.remove("display");
            nav.classList.remove("shrink");
        }
    }
    const options = {threshold: 0.5};
    
    const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
            console.log(entry)
            if (entry.isIntersecting) {
                entry.target.classList.add('show');
            } else {
                entry.target.classList.remove('show');
            }
        });
    }, options);
    
    const hiddenElements = document.querySelectorAll('.hidden');
    hiddenElements.forEach((el) => observer.observe(el));
    :root{
        --background-color: #001728;
        --darker-background-color: #000000;
        --accent-color: #20cc5b;
        --text-color: #FFFFFF;
        --navbar-height: 80px;
    }
    html{
        height: 100%;
    }
    body{
        height: 100%;
        background-color: var(--background-color);
    }
    nav{
        height: var(--navbar-height);
        background-color: red;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 4px solid var(--accent-color);
        transition-property: height;
        transition-duration: 0.5s;
    }
    .navbar {
      position:absolute;
      left:0;
      right:0;
      top:0;
    }
    .navbar-placeholder {
        position:relative;
        height:80px;
        transition: height 0.5s;
    }
    .text1{
        padding: 30px;
      color: white;
    }
    .sticky {
        position: fixed;
        top: 0;
        width: 100%;
        z-index: 2;
    }
    .disappear {
        opacity: 0%;
        transition-duration: 0.5s;
    
    }
    .shrink {
        height: 40px;
        transition-property: height;
        transition-duration: 0.5s;
    }
    .display {
        display: block;
        height: var(--navbar-height);
    }
    h1, p{
      font-size: 50px;
      color: white;
    }
    section {
        display: grid;
        place-items: center;
        align-content: center;
        min-height: 100vh;
        border: 5px solid white;
    }
    .hidden {
        opacity: 0;
        transition: all 1s;
    }
    
    .show {
        opacity: 1;
        transition: all 1s;
    }
    <!DOCTYPE html>
    <html lang="de">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>WeSoDev</title>
        <link rel="stylesheet" href="index.css">
    </head>
    <body>
    <div id="navbar_placeholder" class="navbar-placeholder">
    <div id="navbar">
        <nav id="nav">
          <h2 id="header">header</h2>
        </nav>
    </div>  
    </div>
          <section class="hidden">
            <h1>Test</h1>
            <p>Hello</p>
        </section>
        <section class="hidden">
            <h1>Test</h1>
            <p>Hello</p>
        </section>
        <section class="hidden">
            <h1>Test</h1>
            <p>Hello</p>
        </section>
    
        <script src="index.js"></script>
    </body>
    </html>

    Read about z-index. You can just put z-index: 2; onto the .sticky class and you should be fine :)