Search code examples
javascripthtmlcsscss-animationswebkit-animation

Trigger a webkit animation to scroll when in viewport?


I've been scouring the internet and StackOverflow for quite some time to find a solution to my problem but nothing is working. So figured I'd just make my own post to throw into the ring of questions about triggering animations when scrolling in viewport. I have read CSS3-Animate elements if visible in viewport (Page Scroll) and I've tried adapting every single solution on that answer and it does not fix the issue. My question uses webkit and the solutions in that question similar to mine do not work even if adapted to my code.

I'm trying to highlight some text using a webkit animation. The HTML/CSS works well! I'm just trying to get it to trigger when the text enters the viewport rather than when the page loads. Preferably using only JavaScript since I want the page to load very quickly.

HTML

I don't have any JS to include because I've tried a ton of solutions and it's just not working for the formatting of the code with webkit animation. I'm very new to JS so any help is appreciated.

<h1>
    <ol>
        <li>Highlight <mark>this text</mark> upon scrolling.</li>
    </ol>
</h1>

CSS

mark {
  -webkit-animation: 1s highlight 1s 1 normal forwards;
          animation: 1s highlight 1s 1 normal forwards;
  background-color: none;
  background: linear-gradient(90deg, #C7A4D8 50%, rgba(255, 255, 255, 0) 50%);
  background-size: 200% 100%;
  background-position: 100% 0;
}

@-webkit-keyframes highlight {
  to {
    background-position: 0 0;
  }
}

@keyframes highlight {
  to {
    background-position: 0 0;
  }
}

Thanks for your help.


Solution

  • You can do as follows.

    CSS

    In the css file add 2 classes. One called "hidden" and the other one called "show". The hidden class will be the default class, which is how the element is positioned when it's not in the viewport. The show class will be used for the trasition when the element will enter the viewport.

    In my case, when the element is not in the viewport, it's not visible (opacity: 0), it's positioned on the right with some blur.

    .hidden {
        opacity: 0;
        filter: blur(5px);
        transform: translateX(50%);
        transition: all 1s;
    }
    
    .show {
        opacity: 1;
        filter: blur(0);
        transform: translateX(0);
    }

    HTML

    In the HTML code you will need to add the hidden class to any element you want to keep hidden when out of the viewport.

    <!DOCTYPE html>
    
    <html lang="en">
        <body>
            <h1 class="hidden">My title</h1>
        </body>
    </html>

    JavaScript

    In the JavaScript file you will need to add the following code. This code will monitor each element with the "hidden" class and when any of these enter the viewport the "show" class will be added to it. The "show" class will then be removed when it exits the viewport (if you don't want that to happen, and therefore want to play the animation only once remove the else block).

    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')
            }
        })
    })
    
    const hiddenElements = document.querySelectorAll('.hidden');
    hiddenElements.forEach((element) => observer.observe(element));