How to make a vertical infinite CSS background image loop?

803 views Asked by At

I've been trying to pull off this technique but with a vertical setting (method 1 in the link):

https://blog.logrocket.com/creating-infinite-css-background-image-loop/

However, it never seems to work. I want to have a logo at the center on top, and a gradient above the looping image.

- The problem: It doesn't scroll/run smooth, it's a little choppy. It is never infinite and instead, goes back to the top.

Here is a little preview of my current code:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>TEST</title>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        .background {
            background-image:url('https://i.pinimg.com/originals/a1/71/49/a17149990fa1bb216afa39e24901e90b.jpg');
            background-repeat: repeat-y;
            background-position: center top;
            background-size: cover;
            animation: scroll 20s linear infinite;
            height: 100vh;
            width: 100%;
            position: fixed;
            top: 0;
            left: 0;
            z-index: -1;
        }

        .gradient {
            background: linear-gradient(to top, #000000b3 60%, rgba(0,0,0,0));
            height: 100vh;
            width: 100%;
            position: fixed;
            top: 0;
            left: 0;
            z-index: 0;
        }

        .logo {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 1;
            max-width: 50%;
            max-height: 50%;
        }


        @keyframes scroll {
            from {background-position: center top;}
            to {background-position: center bottom;}
        }
    
    </style>
</head>
<body>
    <div class="background"></div>
    <div class="gradient"></div>
    <img src="https://www.citypng.com/public/uploads/small/116615720279wzwjyabcqvv4y6gzaozid8gaydhminycktgvrhn2mh5fqgvzropookgusxawpg1himbfjoeeneoaa9wt0clzsnjhk8vby4fxdur.png" alt="Logo" class="logo">
</body>
</html>

Cheers for help!

1

There are 1 answers

0
Noam On

The problem is that background-position: bottom or 100% means that the bottom of the image meets the bottom of the container, and that's not a full round.

If you want a full round, you need to take the image up some more, until the bottom of the image meets the top of the container. In other words, you need to subtract the height of the container from the position at 100%. This can be done with the CSS function calc():

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>TEST</title>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        .background {
            background-image:url('https://i.pinimg.com/originals/a1/71/49/a17149990fa1bb216afa39e24901e90b.jpg');
            background-repeat: repeat-y;
            background-position: center top;
            background-size: cover;
            animation: scroll 20s linear infinite;
            height: 100vh;
            width: 100%;
            position: fixed;
            top: 0;
            left: 0;
            z-index: -1;
        }

        .gradient {
            background: linear-gradient(to top, #000000b3 60%, rgba(0,0,0,0));
            height: 100vh;
            width: 100%;
            position: fixed;
            top: 0;
            left: 0;
            z-index: 0;
        }

        .logo {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 1;
            max-width: 50%;
            max-height: 50%;
        }


        @keyframes scroll {
            from {background-position: center 0;}
            to {background-position: center calc(100% - 100vh);}
        }
    
    </style>
</head>
<body>
    <div class="background"></div>
    <div class="gradient"></div>
    <img src="https://www.citypng.com/public/uploads/small/116615720279wzwjyabcqvv4y6gzaozid8gaydhminycktgvrhn2mh5fqgvzropookgusxawpg1himbfjoeeneoaa9wt0clzsnjhk8vby4fxdur.png" alt="Logo" class="logo">
</body>
</html>

In this case the height of the container is known as 100vh. If the height of the container isn't known but the rendered height of the image is known, you can get the same result by simply animating to to minus the image's height.

Unfortunately, I'm not aware of a method to solve that in case neigther the height of the container or the image is known.