DEV Community

Code_Jedi
Code_Jedi

Posted on • Updated on

Tired of people missing out on your CSS animations? jQuery is the answer...

You've probably been there... You've added a cool animation to one of your webpage's elements, but no-one sees it because the element is too far down the page, and by the time people scroll it into view, it's animation has already finished.
This can be easily solved using jQuery!


Let's take a simple webpage.

<!DOCTYPE html>
<html>
<head>
<style>
  @keyframes floatin {
    from { margin-left: 80% }
    to { margin-left: 10% }
  }
  h1{
    text-align: center;
  }
  p{
    margin-left: 20%;
    width: 60%;
  }
  .info{
    position: absolute;
    top: 1000px;
    font-size: 25px;
    margin-left: 80%;
  }
</style>
</head>
<body>
<h1>The top content</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis fringilla id justo ut tincidunt. Nullam in lectus ultrices, pretium velit sit amet, ullamcorper est. Suspendisse mattis ac diam sit amet convallis. Vivamus et sagittis justo. Praesent non commodo leo. Aenean pulvinar erat ac massa fermentum, vel aliquet mi consectetur. Proin et blandit neque, et porttitor tellus. Aliquam sollicitudin vehicula erat eu rutrum. Sed sit amet tortor quis tortor ullamcorper euismod. Donec eu vulputate sapien.
</p>
<div id="info">Hello there!</div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

As you can see, the animated ".info" element is too far down the webpage, and by the time you read the top content, it's animation would have long finished.

This can be solved using jQuery.
First, we have to make sure to add the jQuery script tag inside this webpage's head tag:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

Next, let's add the following code inside of a script tag to the bottom of the body tag.

function wait(){
  $h = $(document).height();
  $pos = $(".info").position();
  if($h > $pos.top){
    $(".info").animate({"margin-left": "10%"}, 2000);
  }
}
$(window).scroll(function(){
  wait();
});
Enter fullscreen mode Exit fullscreen mode

What does this jQuery code do?

  1. The "wait()" function first gets how much the user has scrolled down the page.
  2. It checks if that number is larger than the top position of the ".info" element.
  3. If it is, that element's "margin-left" property is changed from 80% to 10% in 2000 milliseconds(2 seconds) using jQuery's "animate()" function.
  4. The "$(window).scroll(function())" then runs the "wait()" function every-time the use scrolls this webpage.

Full code

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
  @keyframes floatin {
    from { margin-left: 80% }
    to { margin-left: 10% }
  }
  h1{
    text-align: center;
  }
  p{
    margin-left: 20%;
    width: 60%;
  }
  .info{
    position: absolute;
    top: 1000px;
    font-size: 25px;
    margin-left: 80%;
  }
</style>
</head>
<body>
<h1>The top content</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis fringilla id justo ut tincidunt. Nullam in lectus ultrices, pretium velit sit amet, ullamcorper est. Suspendisse mattis ac diam sit amet convallis. Vivamus et sagittis justo. Praesent non commodo leo. Aenean pulvinar erat ac massa fermentum, vel aliquet mi consectetur. Proin et blandit neque, et porttitor tellus. Aliquam sollicitudin vehicula erat eu rutrum. Sed sit amet tortor quis tortor ullamcorper euismod. Donec eu vulputate sapien.
</p>
<div class="info">Hello there!</div>
<script>
function wait(){
  $h = $(document).height();
  $pos = $(".info").position();
  if($h > $pos.top){
    $(".info").animate({"margin-left": "10%"}, 2000);
  }
}
$(window).scroll(function(){
  wait();
});
</script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

As you can see, the ".info" element is now being animated only when it is scrolled into view.

Adding multiple animations

You can also add multiple animations to an element using jQuery.
Let's take the same code, but this time add another animation to the ".info" element.

function wait(){
  $h = $(document).height();
  $pos = $(".info").position();
  if($h > $pos.top){
    $(".info").animate({"margin-left": "10%"}, 2000).animate({"font-size": "40px"}, 2000);
  }
}
$(window).scroll(function(){
  wait();
});
Enter fullscreen mode Exit fullscreen mode

By adding animate() functions onto each other like shown in this code, you can add animations to an element on top of each other.


There it is, a simple yet useful web development trick.

If you're intrigued by jQuery and it's possibilities, I would highly recommend this jQuery course on educative.

Discussion (4)

Collapse
lukeshiru profile image
LUKESHIRU • Edited on

A few things I noticed:

  • If you really want to use jQuery, you should at least use modern syntax instead of the old one, so you shouldn't use methods like click or scroll, and instead you should use on.
  • You're declaring global variables with $h and $pos instead of being local.
  • Ideally you should use a class toggle instead of animate, and use CSS transitions/animations.
  • You should remove the listener once you reach the animation, and you should call wait once because maybe the animation is triggered in the first render.

Here's how the code would look like:

const $info = $(".info");
const $window = $(window);

const wait = () => {
    const height = $(document).height();
    const { top } = $info.position();

    if (height > top) {
        $info.addClass("in");
        $window.off("scroll", wait);
    }
};

$window.on("scroll", wait);
wait();
Enter fullscreen mode Exit fullscreen mode

Now, if you want to learn how to do this without bloating your site with jQuery, then you can do it using the IntersectionObserver API, like this:

<!DOCTYPE html>
<html>
    <head>
        <style>
            h1 {
                text-align: center;
            }
            p {
                margin-left: 20%;
                width: 60%;
            }
            .spacer {
                height: 1000px;
            }
            .info {
                font-size: 25px;
                margin-left: 80%;
                transition: margin-left 2s ease-out;
                will-change: margin-left;
            }
            .info.in {
                margin-left: 10%;
            }
        </style>
    </head>
    <body>
        <h1>The top content</h1>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis
            fringilla id justo ut tincidunt. Nullam in lectus ultrices, pretium
            velit sit amet, ullamcorper est. Suspendisse mattis ac diam sit amet
            convallis. Vivamus et sagittis justo. Praesent non commodo leo.
            Aenean pulvinar erat ac massa fermentum, vel aliquet mi consectetur.
            Proin et blandit neque, et porttitor tellus. Aliquam sollicitudin
            vehicula erat eu rutrum. Sed sit amet tortor quis tortor ullamcorper
            euismod. Donec eu vulputate sapien.
        </p>
        <div class="spacer"></div>
        <div class="info">Hello there!</div>
        <script>
            // We create a new observer to add the class "in"
            const inObserver = new IntersectionObserver(
                ([{ isIntersecting, target }]) => {
                    isIntersecting
                        ? (target.classList.add("in"),
                          inObserver.unobserve(target))
                        : undefined;
                },
                { threshold: [0] },
            );

            // We use the above observer in ".info"
            inObserver.observe(document.querySelector(".info"));
        </script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

And here you have it in action:

More info on the IntersectionObserver API, here. I guess jQuery isn't the answer 🤣

Cheers!

Collapse
jamesthomson profile image
James Thomson

Came here to say exactly this. Use IntersectionObserver, there's really no reason to use jQuery these days (except for those projects that are stuck with it).

Collapse
ogranada profile image
Andres Granada • Edited on

Even on this days know about what you can do with jQuery is good, however, make animations with Javascript is something that you need to think because it is a CPU intensive process. In this case use an intersection observer with CSS can be ideal because CSS prefer to use the GPU for animations (smashingmagazine.com/2016/12/gpu-a...).

Collapse
mate3 profile image
Mate

Or you could just use IntersectionObserver without loading whole jQuery lib for this functionality. Also if you need some advance animation GSAP and ScrollTrigger are way to go!