Creating an Infinite Scrolling VERTICAL background - css

There are tons of horizontal scrolling backgrounds but that isn't my issue. Any time I create a vertical scroll using keyframes, the background image itself runs out, or it glitches out completely and starts the scroll effect over. That is not what I need. I need a seamless VERTICAL scrolling background that takes up the full width of the screen. There will be a container with the overflow hidden and it's background needs to scroll slowly upwards with a series of images that never glitches out, runs out etc. It needs to look like the one million examples of horizontal scrolling but vertically.
In the CSS is the actual dimensions of the image I am using. I am using a placeholder to start this conversation. Notice, even with the placeholder, the image just eventually stops.
Why does it do this with vertical scrolling, but typically not with horizontal? It doesn't make sense to me and there aren't many resources out there about vertical infinite scrolls of a background image, believe it or not.
If anyone has any recommendations, I will take it. JS or CSS whatever it is I am willing to listen and learn and understand why the f*** I can't figure this out. Thanks.
<div class="container">
<div class="sliding-background"></div>
</div>
.container {
overflow: hidden;
height: 600px;
}
.sliding-background {
background: url("https://images.fineartamerica.com/images/artworkimages/mediumlarge/2/a-dramatic-image-of-a-tall-tree-sitting-against-moody-skies-in-the-background-with-blue-and-yellow-tones-chris-cook.jpg") repeat-y;
height: 4980px;
width: 1440px;
animation: slide 30s linear infinite;
}
#keyframes slide{
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, -100%, 0);
}
}
<div class="container">
<div class="sliding-background"></div>
</div>

If you know the exact height of the image, this solution should work:
body {
margin: 0;
}
.container {
overflow: hidden;
height: 600px;
}
.sliding-background {
--imageHeight: 900px;
background: url("https://images.fineartamerica.com/images/artworkimages/mediumlarge/2/a-dramatic-image-of-a-tall-tree-sitting-against-moody-skies-in-the-background-with-blue-and-yellow-tones-chris-cook.jpg") repeat-y;
height: calc(var(--imageHeight) * 2);
animation: slide 4s linear infinite;
}
#keyframes slide {
from {
transform: translateY(0px);
}
to {
transform: translateY(calc(var(--imageHeight) * -1));
}
}
<div class="container">
<div class="sliding-background"></div>
</div>

If there is any confusion about the image height:
body {
margin: 0;
}
.container {
overflow: hidden;
height: 600px;
}
.sliding-background {
background: url("https://images.fineartamerica.com/images/artworkimages/mediumlarge/2/a-dramatic-image-of-a-tall-tree-sitting-against-moody-skies-in-the-background-with-blue-and-yellow-tones-chris-cook.jpg") repeat-y;
-webkit-animation: bgScroll 600s linear infinite;
animation: bgScroll 600s linear infinite;
height: 100%;
background-size: cover;
position: relative;
}
#keyframes bgScroll{
0% {
background-position: 0 0;
}
100% {
background-position: 0 10000%;
}
}
<div class="container">
<div class="sliding-background"></div>
</div>

Related

Can I create a butterfly animation effect with translate3D (css), or another css animation on a single image or element?

I have an image of a butterfly, something like this.
I am trying to figure out if there is any way to make it look like its wings are opening and closing with a 3D CSS transform/translate or animation, but without having to split the image up into parts (it can be a background image of a div though if that helps).
Yes, using background applied to two elements where each one will show only one half and then you simply rotate both on the Y axis.
.box {
width:300px;
margin:20px;
display:flex;
perspective:500px;
}
.box::before,
.box::after{
content:"";
padding-top:56%; /* ratio based on your image */
flex:1; /* half the main element size */
background-image:url(https://i.imgur.com/DgMoHC5.jpg);
background-size:200% 100%; /* twice bigger than the pseudo element to get half the image*/
animation:left 1s linear infinite alternate;
transform-origin:right;
}
.box::after {
background-position:right; /* get the right part of the image */
animation-name:right;
transform-origin:left;
}
#keyframes left{
to {transform:rotateY(60deg)}
}
#keyframes right{
to {transform:rotateY(-60deg)}
}
<div class="box"></div>
A more realistic animation with some translation:
.box {
width: 300px;
margin: 20px;
display: flex;
perspective: 500px;
}
.box::before,
.box::after {
content: "";
padding-top: 56%;
flex: 1;
background-image: url(https://i.imgur.com/DgMoHC5.jpg);
background-size: 200% 100%;
animation: left 0.5s linear infinite alternate;
transform-origin: right;
}
.box::after {
background-position: right;
animation-name: right;
transform-origin: left;
}
#keyframes left {
from {
transform: translateZ(80px) rotateY(-30deg)
}
to {
transform:translateZ(0px) rotateY(50deg)
}
}
#keyframes right {
from {
transform: translateZ(80px) rotateY(30deg)
}
to {
transform:translateZ(0px) rotateY(-50deg)
}
}
<div class="box"></div>

How to infinite zoom in and out smoothly with background image in CSS

The background image isn't smooth when it comes to animate it (some kind of blink) and I can't make it zoom from the image center.
This is for my personnal website I'm trying to make.
*{margin: 0;padding: 0;}
body
{
background-color: #0C090A;
background-image: url(../abstract-bg.png);
animation: zoom 30s infinite;
-webkit-animation: zoom 30s infinite;
}
#keyframes zoom {
0% {
background-size: 100%;
}
50% {
background-size: 105%;
}
100% {
background-size: 100%;
}
}
I would like to get the background image (which is 1920*1080) zoom slowly to 105% of it's original size (or something like that), and then go back to 100%. Also, if it's possible, make it zoom from the center, and not the top left corner. Thanks for those who can help.
yes of course you can :)
just add
background-position:center center;
background-repeat:no-repeat;
in the body css
and add
html{
height: 100%;
}
full css code:
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
}
body {
background-color: #0C090A;
background-image: url(https://images.pexels.com/photos/556416/pexels-photo-556416.jpeg);
animation: zoom 30s infinite;
-webkit-animation: zoom 30s infinite;
background-position: center center;
background-repeat: no-repeat;
}
#keyframes zoom {
0% {
background-size: 100%;
}
50% {
background-size: 150%;
}
100% {
background-size: 100%;
}
}
you can test the code:
https://playcode.io/358401
It's choppy because the animation duration is too long for 5% of the width of the image. either increase the size or decrease the duration of the animation or use a bigger image.
Or you can use scale() which make use of the GPU i believe, However this time we won't be using the image as a background.
body{
overflow-x:hidden;
}
img {
transform-origin: center center;
animation: zoom 30s infinite;
max-width: 100%;
}
#keyframes zoom {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
/* equals 105% */
}
100% {
transform: scale(1);
}
}
<img src="https://picsum.photos/id/238/1920/1080">

Long CSS animation easing (background-position)

I'm trying to animate a background image position smoothly with CSS over a longer period, let's say 60 seconds:
#movingbackground {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Bigsurflowers.jpg/1280px-Bigsurflowers.jpg');
overflow: hidden;
background-position: left center;
animation: zoomin 60s ease-in infinite;
}
#-webkit-keyframes zoomin {
0% { background-position: 0% center; transform: scale(1.0); }
50% {background-position: 100% center; transform: scale(1.2); }
100% { background-position: 0% center; transform: scale(1.0); }
}
#keyframes zoomin {
0% { background-position: 0% center; transform: scale(1.0); }
50% {background-position: 100% center; transform: scale(1.2); }
100% { background-position: 0% center; transform: scale(1.0); }
}
<div id="movingbackground"></div>
The small movements in the beginning and end are "jumping" a few pixel every second instead of moving slowly (may depend on screen size).
The reason for that is probably that there is not enough movement to fill the required number of frames, especially when the animation is eased. As I think I have seen this effect working smoothly somewhere I wonder how to work around this.
Here's a Fiddle as well.
Animation of background-position makes browser to do layout, paint and composite.
Re-layout and re-paint are heavy on CPU and cause "jumping".
Instead of that, you might apply your background to pseudo-element (or use <img> in your HTML) and animate its transform property using 3d transformation.
It will make browser to use GPU for the animation and animation will run in composition phase pretty smoothly.
See the snippet below:
html,
body {
margin: 0;
padding: 0
}
#movingbackground {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
#movingbackground:before {
content: '';
position: absolute;
top: 0; left: 0; z-index: -1;
height: 100%;
width: 200%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Bigsurflowers.jpg/1280px-Bigsurflowers.jpg) 0 50% / cover;
animation: zoomin 60s ease-in infinite;
}
#keyframes zoomin {
50% {
transform: translateX(-50%) scale(1.2)
}
}
<div id="movingbackground"></div>
I did some testing and came to the conclusion that it's probably impossible. (At least with transitions or animations)
The problem is the way browsers render images on a screen. The pixels of the image apparently get lined up with those of your screen.
So the picture always "jumps" exactly one pixel at a time.
That means, that the more pixels you have in your image, the more steps it will make. But when using ease-in it will always stutter in the beginning.
As I think I have seen this effect working smoothly somewhere
That was probably not realized with css.

Infinite top-to-bottom pure CSS Photo Banner, stack on first image

I'm trying to make a pure css top to bottom infinite photo banner (without any margins) with ability to use scrsets for larger displays and zooming (css background url is not an option for this case).
I can't figure it out how to calculate all the numbers that is necessary for the animation, can someone explain it to me, please?
1.1. What do I have to change if I add more images to the div?
The first frame is not moving (second frame suddenly "eats" the first one), why is it happening and how to fix it?
What am I doing wrong?
This is what I'm done so far:
#container {
width: auto;
height: auto;
overflow: hidden;
background: white;
margin: 0;
}
.photobanner {
height: 466px;
width: 350px;
margin-bottom: 0;
background-color: blue;
}
.photobanner img{
display: block;
}
.first {
-webkit-animation: bannermove 30s linear infinite;
-moz-animation: bannermove 30s linear infinite;
-ms-animation: bannermove 30s linear infinite;
-o-animation: bannermove 30s linear infinite;
animation: bannermove 30s linear infinite;
}
#keyframes "bannermove" {
0% {
margin-bottom: 0px;
}
100% {
margin-bottom: -466px;
}
}
#-moz-keyframes bannermove {
0% {
margin-bottom: 0px;
}
100% {
margin-bottom: -466px;
}
}
#-webkit-keyframes "bannermove" {
0% {
margin-bottom: 0px;
}
100% {
margin-bottom: -466px;
}
}
#-ms-keyframes "bannermove" {
0% {
margin-bottom: 0px;
}
100% {
margin-bottom: -466px;
}
}
#-o-keyframes "bannermove" {
0% {
margin-bottom: 0px;
}
100% {
margin-bottom: -466px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="container">
<!-- Each image is 350px by 233px -->
<div class="photobanner">
<img class="first" src="https://dummyimage.com/350x233/000/fff.png&text=1" alt="" />
<img src="https://dummyimage.com/350x233/000/fff.png&text=1" alt="" />
<img src="https://dummyimage.com/350x233/000/fff.png&text=2" alt="" />
<img src="https://dummyimage.com/350x233/000/fff.png&text=1" alt="" />
</div>
</div>
</body>
</html>
Take a look at this example I have created. I am using 3 separate images.
For this to work, I used images which are all of the same size.
Each image is 350 x 150 so from that I can determine the height/width ratio to be 0.4285
The ratio value can be used as padding to specify the height of the carousel - This trick can be used to create a responsive carousel:
.carousel {
height: 0;
overflow: hidden;
padding-bottom: 43%;
}
This will allow the carousel to scale in proportion with the images.
Since we want the carousel to be infinite scrolling, it needs to have a duplicate of the first slide at the bottom. This will allow the animation to continue seamlessly.
The animation itself is manipulating the transform value between 0% and 75%. I am using 75 here because there are a total of 4 images in the carousel and we want the animation to loop at the 3rd quarter of the progression.
If we have 3 images, we would need to change this value to 66.66%

How can I place image just left outside visible part of page before animation start?

I want to place my image left outside of page how to do it?
+-------------------+
| visible page part |
image -> | |
+-------------------+
Finally I want to move image inside page.
+-------------------+
| visible page part |
| image inside page |
+-------------------+
You can use either negative margin or translateX transform to achieve this. The below snippet has an example for both approaches.
One thing to note is that the two methods work a bit differently even though their end output is similar. While translateX(-100%) moves element to the left (on the X-axis) by as many pixels as the width of the image, margin-left: -100% moves the image by as many pixels as the width of the container of the image. So, if the emphasis is on just left outside the visible part then using translateX(-100%) is more suitable.
/* using negative margins */
.margin {
margin-left: -100%;
animation: marginmove 1s 3s forwards;
}
#keyframes marginmove {
from {
margin-left: -100%;
}
to {
margin-left: 0%;
}
}
/* using translate transforms */
.translate {
transform: translateX(-100%);
animation: translatemove 2s 3s forwards;
}
#keyframes translatemove {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0%);
}
}
/* Just for demo */
body {
max-width: 300px;
margin: 0 auto;
padding: 0;
border: 1px solid;
}
html,
body {
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div>Test content</div>
<img src="http://lorempixel.com/100/100/nature/1" class="margin" />
<div>Test content</div>
<img src="http://lorempixel.com/100/100/nature/2" class="translate" />
Note: As mentioned in comments, if there is a chance that the page's width can become lesser than the viewport's width then it would be imperative to add overflow: hidden to the root/parent element (as applicable) to prevent the image from showing up outside the page's left border.
You can adapt the above answer to work even when the image is part of a centered column which has equal margins on either sides. Below is a sample snippet to help you:
/* using negative margins */
.margin {
margin-left: -100%;
margin-right: 0%;
animation: marginmove 1s 3s forwards;
}
#keyframes marginmove {
from {
margin-left: -100%;
}
to {
margin-left: 0%;
}
}
/* using translate transforms */
.translate {
transform: translateX(-100%);
animation: translatemove 1s 3s forwards;
}
#keyframes translatemove {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0%);
}
}
/* Just for demo */
.container {
width: 300px;
margin: 0 auto;
border: 1px solid;
overflow: hidden;
}
.container > div{
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='container'>
<div>Centered column</div>
<img src="http://lorempixel.com/300/100/nature/1" class="margin" />
</div>
<div class='container'>
<div>Centered column</div>
<img src="http://lorempixel.com/300/100/nature/2" class="translate" />
</div>

Resources