0

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.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
shoobydoo
  • 3
  • 2
  • You can use the IntersectionObserver API. This API allows you to monitor elements on the page and execute a callback function when they intersect with a specified element or viewport. https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API – DanTe Dec 30 '22 at 19:00
  • @DanTe I've been trying to integrate the IntersectionObserver API for a few days but it doesn't seem to be working for my code. – shoobydoo Dec 31 '22 at 20:38

1 Answers1

0

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));
TermoPollo
  • 268
  • 1
  • 9
  • Thank you! The hidden class removes the text completely rather than just the highlight, is there a way to turn that off? Also, for some reason the hidden property isn't changing to show when the text enters the viewport. I'm getting an 'unexpected console statement' error for the javascript code, does that have something to do with it? – shoobydoo Dec 31 '22 at 20:37
  • @shoobydoo In the "hidden" class I put `opacity: 0` so the text or any other element will be "invisible". If you don't want to make opacity transitions just remove it. I don't know exactly how you want the result to be so I put some properties to my liking. You just need to understand that the hidden class is the first starting point, while the show class is the last point (like you do when you use `:hover`). For JavaScript instead, did you import it into the HTML code? – TermoPollo Dec 31 '22 at 22:34
  • Thank you for the clarification! I verified that the javascript is imported into the HTML properly. Not really sure why there's a `no-console` error, but it's being given at this line: `console.log(entry)`. Checked on multiple browsers as well, same issue. EDIT: I solved the console error by just putting the script directly in the HTML. Unfortunately the animation still isn't triggering for some reason. I feel like I'm missing something! – shoobydoo Jan 01 '23 at 22:46
  • @shoobydoo The `console.log()` is a line for debugging, I understand why it doesn't work for you. I forgot to tell you that to import the script into the HTML code you must use the "defer" attribute: ``. This is because the script to find all elements with class "hidden" has to wait for the page to finish parsing: [link](https://www.w3schools.com/tags/att_script_defer.asp) – TermoPollo Jan 02 '23 at 12:55
  • That totally solved the problem! Thank you so much, you're a lifesaver. – shoobydoo Jan 02 '23 at 14:58