Site logo

Archived topic

Underline Text Animation Once User Scrolls

12 replies · Started by jm1991 on February 24, 2023

Viewing posts 1–13 of 13

Hello!

I'd like the underline under the heading tags to appear once a user scrolls and the heading tag is visible in the viewport.

The current CSS I'm using is as below:

.underline-heading {
    display: inline-block;
    background-repeat: no-repeat;
    background-image: linear-gradient(180deg,#ff0000 0%,#ff0000 100%);
    background-position: 0 89%;
    background-size: 100% 10%!important;
    transition-delay: .4s!important;
    background-size 0.8s ease-in-out
}

However, I can't figure out how to animate the underlines once a user scrolls. I've linked to my site in the submission box.

Thanks!

Hi there,

so you can't do that with just CSS.
It requires Javascript.

1. Create a new GP Element -> Hook.
1.1 in the text area, add this script:

<script>
function toggleActiveClassOnInView() {
    const activeClass = 'active';
    const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
            const targetElement = entry.target;
            if (entry.isIntersecting) {
                targetElement.classList.add(activeClass);
            } else {
                targetElement.classList.remove(activeClass);
            }
        });
    });
    const targetElements = document.querySelectorAll('.underline-heading');
    targetElements.forEach(targetElement => observer.observe(targetElement));
}

toggleActiveClassOnInView()
</script>

3. set the Hook to wp_footer
4. set the Display Rules -> Location to Entire Site or the specific pages you want the effect.
5. Publish the hook.

What this will do is: if an element with the underline-heading scrolls into the viewport, it toggles the active class.

Then for your CSS you could use a box-shadow inset for your underline which can be shown when the active class is present:

.underline-heading {
    display: inline-block;
    position: relative;
}
.underline-heading:before {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    height: 2px;
    width: 0;
    background-color: #f00;
}
.underline-heading.active:before {
    width: 100%;
    transition-delay: 1s;
    transition: width 2s ease;
}

Hey David,

Thanks for the insight.

I've added the script and CSS, but the underline is still static and doesn't only render when scrolled into the viewport.

I updated the javascript above to fix an error.
Can you try that.

Hi there!

Just checking back on this.

Thanks!

Edit: I think we must have replied at the same time! I'll try the fix now. Thanks again

Hey David,

I updated the script, but the underlines are still static.

Thanks.

argh... having one of those days.
Updated JS above and updated the CSS too to make the effect more notiecable.

Hi David,

You're a star. That code tweak has got the desired animation effect. Perfect.

However, I think the CSS now overrides the original CSS used for the heading tags

This is the CSS I use to apply margin to headings:

 h1,h2,h3,h4,h5;
    margin-top: 50px;
    margin-bottom: 20px;

When I try to nest the same CSS within the CSS you provided, the underline goes awry.

Not sure if you could help out with that?

Cheers.

I updated the CSS above, ie. this changed to inline-block

.underline-heading {
    display: inline-block;
    position: relative;
}

Give that a shot

Hi David,

Very nearly there...

I'm wondering if there would be a way to prevent spillage of the underline stretching across the container when a heading is more than 1 line. You'll see an example of this in the second heading. Ideally, the heading would stop when the ellipses would stop, so that it doesn't stretch the entire width of the container and only underlines up until the point where the text ends.

I've tried playing around the with code by adding a unique CSS class and targeting that CSS class in the JS you provided, but I haven't had much luck, even when using ChatGPT.

Thanks

Ok, so the issue is:

you need the block to be inline to keep the length constrained to the wrapped text.
But in doing so you will lose bottom margins....

Instead of:

.underline-heading {
    display: inline-block;
    position: relative;
}

try:


.underline-heading {
    display: inline;
    position: relative;
}
.underline-heading + * {
    margin-top: 20px;
}

This is great. Thank you.

Glad to be of help

This archived topic is closed to new replies.