The animation is moving linearly from left to right but starts abruptly once the animation time is over. Tried with reducing to 1s and increasing the time to 15s. And even increased the keyframes but still doesn't work. Please help:
.grid-item-2 {
grid-column: 1 / span 2;
grid-row: 1;
background-image: url(Building_1.png);
margin-left: 100px;
margin-top: 53px;
width: 90%;
background-repeat: repeat-x;
animation: Buildings 2s linear infinite;
}
#keyframes Buildings {
0% { background-position: 0% 100%; }
25% { background-position: 25% 75%; }
50% { background-position: 50% 50%; }
75% { background-position: 75% 25%; }
100% { background-position: 100% 0; }
}
<div class="grid-item grid-item-2"></div>
The problem with the jumping is that you need to adapt the background image to the size of the div element, which can be hard if you want to have a responsive site. The code below is the best I can come up with, where I loop between -100% and 200%, making the image start outside the element and then end outside the other side of the element, creating the illusion that it continues. I would honestly replace repeat-x with just repeat.
I added a background color just to make the element more visible.
.grid-item-2 {
grid-column: 1 / span 2;
grid-row: 1;
background-image: url("https://picsum.photos/id/737/300/200.jpg");
/* margin-left: 100px;
margin-top: 53px; */
width: 90%;
background-repeat: repeat-x;
background-size: 50% 50%;
animation: Buildings 3s linear infinite;
background-color: #000; /* just to show case the element better */
height: 90vh;
}
#keyframes Buildings {
0% { background-position: -100% 200%; }
100% { background-position: 200% -100%; }
}
<div class="grid-item-2">
</div>
Getting rid of the intermediary keyframes would make it smoother. You only need the frames at 0% and 100%. When you set the animation timing function to linear, it will automatically make sure that all the keyframes that you defined are met. The animation should look something like this...
#keyframes Buildings {
0% {
background-position: 0% 100%;
}
100% {
background-position: 100% 0;
}
}
Related
This question already has an answer here:
How can I apply css transitions to a background image change?
(1 answer)
Closed 3 months ago.
I created a CSS keyframes animation with 5 frames where the background image would fade and change to the next image. The animation works like its supposed to in all cycles except during the first cycle where it glitches before each transition. How to fix this?
HTML:
<div class="container"></div>
CSS:
#keyframes animation1 {
0%, 15%{background-image: url("https://i.imgur.com/IzY1cRC.jpeg");}
20%, 35%{background-image: url("https://i.imgur.com/Bq4PJjC.jpeg");}
40%, 55%{background-image: url("https://i.imgur.com/43idGF1.jpg");}
60%, 75%{background-image: url("https://i.imgur.com/OMa9YYH.jpg");}
80%, 95%{background-image: url("https://i.imgur.com/CTLFd8t.jpg");}
100%{background-image: url("https://i.imgur.com/IzY1cRC.jpeg");}
}
.container{
height: 300px;
width: 550px;
background-image: url("https://i.imgur.com/IzY1cRC.jpeg");
background-position: center center;
background-repeat: no-repeat;
background-size: 100% 100%;
animation-name: animation1;
animation-duration: 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
Extremely grateful for any help this has been hindering a couple of projects for a good time.
The first time the animation plays, images will not be loaded yet, the browser will fetch only when they're actually needed.
While the image is loading, the default background will be displayed (in this case, transparent, which will ultimately show the white background of the body)
You can 'pre-load' the images. So the browser already had the image data in cache when it's needed for the animation. There's different techniques for pre-loading. A straightforward way is to add an invisible element that requires all the images used in the animation.
In the example below, we add an 'invisible' :after element that loads all images.
.container::after {
position: absolute;
width: 0;
height: 0;
overflow: hidden;
z-index: -1;
content: url(https://i.imgur.com/IzY1cRC.jpeg) url(https://i.imgur.com/Bq4PJjC.jpeg) url(https://i.imgur.com/43idGF1.jpg) url(https://i.imgur.com/OMa9YYH.jpg) url(https://i.imgur.com/CTLFd8t.jpg) url(https://i.imgur.com/IzY1cRC.jpeg);
}
#keyframes animation1 {
0%,
15% {
background-image: url("https://i.imgur.com/IzY1cRC.jpeg");
}
20%,
35% {
background-image: url("https://i.imgur.com/Bq4PJjC.jpeg");
}
40%,
55% {
background-image: url("https://i.imgur.com/43idGF1.jpg");
}
60%,
75% {
background-image: url("https://i.imgur.com/OMa9YYH.jpg");
}
80%,
95% {
background-image: url("https://i.imgur.com/CTLFd8t.jpg");
}
100% {
background-image: url("https://i.imgur.com/IzY1cRC.jpeg");
}
}
.container {
height: 300px;
width: 550px;
background-image: url("https://i.imgur.com/IzY1cRC.jpeg");
background-position: center center;
background-repeat: no-repeat;
background-size: 100% 100%;
animation-name: animation1;
animation-duration: 25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
<div class="container"></div>
in this code:
#p1 {
background-image: url(backimgs/first/1.jpg), url(backimgs/first/2.jpg);
background-color: #05080d;
background-position: left top, left bottom;
background-size: 100% 35%, 100% 65%;
}
I want when the page shows up, first show backimgs/first/1.jpg then after 1 sec show backimgs/first/2.jpg. how can I do it?
You can't animate background-images. You can change it, but there won't be any smooth transition:
#p1 {
background-image: url(backimgs/first/1.jpg), url(backimgs/first/2.jpg);
background-color: #05080d;
background-position: left top, left bottom;
background-size: 100% 35%, 100% 65%;
animation: change-bg;
animation-duration: 1s;
}
#keyframes change-bg {
0% {
background-image: url(backimgs/first/1.jpg), url(backimgs/first/2.jpg);
background-size: 100% 35%, 100% 65%;
}
100% {
background-image: url(backimgs/first/2.jpg), url(backimgs/first/1.jpg);
background-size: 100% 65%, 100% 35%;
}
}
If you want a smooth transition - you can use ::before and ::after with a background and animate the opacity of them. Let me know with a comment if you need more info on this aproach, I'll edit the post and show, how it's done.
You mention 'transition' in the title so you will need to control the two parts of the background separately.
To enable this, this snippet removes the backgrounds from the element itself, instead putting them onto two pseudo elements. The before pseudo element having the first image as background and the after pseudo element having the second one.
Separating the components in this way means we can animate the opacities, the first pseudo element going from opacity 0 to opacity 1 in the first second.
Note however that a little hack has been added to ths snippet. As the animation on the before pseudo element is to happen on load then there needs to be some method of waiting for the background image to load before the animation starts else there is a danger it will be part way through, or even finished, before the image is actually available.
I do not know the wider context of how you are testing for load being complete so have just put a delay in here for demo purposes. You'll need to decide what to do to avoid this inital load situation.
* {
margin: 0;
padding: 0;
}
#p1 {
/* added for this demo */
display: inline-block;
width: 100vw;
height: 100vh;
position: relative;
}
#p1::before,
#p1::after {
content: '';
position: absolute;
z-index: -1;
width: 100%;
left: 0;
display: inline-block;
background-color: #05080d;
background-size: cover;
background-repeat: no-repeat no-repeat;
background-position: center center;
animation: fadein 1s linear;
animation-fill-mode: forwards;
opacity: 0;
}
#p1::before {
top: 0;
height: 35%;
background-image: url(https://picsum.photos/id/1018/1024/768);
animation-delay: 1s;
/* a hack to ensure it is loaded before start the animation */
}
#p1::after {
bottom: 0;
height: 65%;
background-image: url(https://picsum.photos/id/1015/1024/768);
animation-delay: 2s;
}
#keyframes fadein {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<div id="p1"></div>
Could do with some help.
I need to slide a long image horizontally once and then back... I've followed a tutorial here https://css-tricks.com/creating-a-css-sliding-background-effect/ and its all working. My problem is I want the sliding image to be fullscreen (the image height needs to fit the browser viewpoint). Current image is 7676 x 3939. background-size: cover was an option but image is too large so it doesn't fit height-wise. So I'd like half the image (3838px - fullscreen) to show initially then slide to the other half and then back.
Would appreciate some assistance. Below is my code. Thanks.
.wrapper {
overflow: hidden;
}
.sliding-background {
background: url("long-image.jpg") center;
height: 100vh;
width: 7676px;
animation: slide 3s linear 1;
}
#keyframes slide {
0%{
transform: translate3d(0, 0, 0);
}
50%{
transform: translate3d(-3838px, 0, 0);
}
100%{
transform: translate3d(0, 0, 0);
}
}
Try add position relative or absolute to .sliding-background
You could also try animating the background position instead of the element itself. Then you should make your container full screen, like this:
body,
html {
margin: 0;
padding: 0;
}
#wrapper {
overflow: hidden;
}
.sliding-background {
background-image: url("https://upload.wikimedia.org/wikipedia/commons/9/93/Denali_National_Park_Polychrome_Mountains_Wide_17350px.jpg");
background-repeat: repeat-x;
background-size: cover;
height: 100vh;
width: 100vw;
animation: slide 45s linear infinite;
}
#keyframes slide {
0% {
background-position: 0 0;
}
50% {
background-position: 100% 0;
}
100% {
background-position: 0 0;
}
}
See: https://jsfiddle.net/9mLhdy4c/
I am trying to create a ken-burns like effect for image panning - and have seen multiple examples of how to do so. but my resultant code is not working on iOS and is choppy on windows larger screens.
I am using background position - and would like to use transfrom instead - which seems to work better on iOS browsers.
#-webkit-keyframes pan {
0% { background-position: 0% 0%; }
25% { background-position: 100% 100%; }
50% { background-position: 100% 0%; }
75% { background-position: 100% 100%; }
100% { background-position: 0 0; }
}
#keyframes pan {
0% { background-position: 0% 0%; }
25% { background-position: 100% 100%; }
50% { background-position: 100% 0%; }
75% { background-position: 100% 100%; }
100% { background-position: 0 0; }
}
.back {
background: url(big.png) no-repeat;
-webkit-animation: pan 80s ease-in 1s infinite;
animation: pan 80s ease-in 1s infinite;
}
The above works in general browser but is choppy. I have tried to increase the intervals etc. - but it also does not quite work on iOS.
how would I convert the above code to use transform or translate css-property instead ? I understand it is better/faster for performance and smoothness.
thanks
I wanted to ask, what is wrong with this CSS code? It is used to animate background image - zoom effect.
#media (min-width: 1000px) {
.anim-on {
background-size: 110% 110%;
background-position: center center;
animation: shrink 12s infinite alternate;
}
.anim-out {
background-size: 120% 120%;
background-position: center center;
animation: small 6s infinite alternate;
}
#keyframes shrink {
0% {
background-size: 110% 110%;
}
100% {
background-size: 100% 100%;
}
}
#keyframes small {
0% {
background-size: 100% 100%;
}
100% {
background-size: 110% 110%;
}
}
}
This code generates nice effect, but i saw, that on slower machines, affect is bad.
What is wrong? Or maybe someone has better idea, how create this effect, in better technique?
Background size is a visual property and so any change to its value would cause repainting to occur. Painting is a very expensive operation and is bound to have an impact on the performance in low end machines. One way to overcome this would be to use CSS transform (scale to be precise) instead of background-size change to produce the animation.
Snippet which will cause performance impact:
The below snippet uses the same animation as in the question. When you run this snippet and inspect it using Chrome Dev tools (by enabling "Show Paint Rects" option), you'd see that both images have a paint rect associated with them (green or red colored box) and that as the animation is happening the box keeps blinking (or stays as-is). This indicates that a repaint is happening often and thus it impacts performance.
.anim-on,
.anim-out {
height: 200px;
width: 200px;
background: url(http://lorempixel.com/200/200/nature/1);
}
.anim-on {
background-size: 110% 110%;
background-position: center center;
animation: shrink 12s infinite alternate;
}
.anim-out {
background-size: 120% 120%;
background-position: center center;
animation: small 6s infinite alternate;
}
#keyframes shrink {
0% {
background-size: 110% 110%;
}
100% {
background-size: 100% 100%;
}
}
#keyframes small {
0% {
background-size: 100% 100%;
}
100% {
background-size: 110% 110%;
}
}
/* Just for demo */
div {
float: left;
margin-right: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='anim-on'></div>
<div class='anim-out'></div>
Snippet which will cause lesser performance impact:
In the below snippet, I have added the background-image to a pseudo-element and then used scale transform on it to produce the zoom-in/out effect. The parent's overflow: hidden setting prevents the animation from affecting its size. If you inspect this with Chrome Dev tools you'd see that the green or red colored box appears only once when the page is loaded and goes away. This indicates that there is no further repaint is happening during the animation itself and hence it is better from a performance point of view. You'd also notice that this animation is more smoother than the earlier one.
.anim-on,
.anim-out {
position: relative;
height: 200px;
width: 200px;
overflow: hidden;
}
.anim-on:after,
.anim-out:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
top: 0px;
left: 0px;
background: url(http://lorempixel.com/200/200/nature/1);
}
.anim-on:after {
animation: shrink 12s infinite alternate;
}
.anim-out:after {
animation: small 6s infinite alternate;
}
#keyframes shrink {
0% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
#keyframes small {
0% {
transform: scale(1);
}
100% {
transform: scale(1.1);
}
}
/* Just for demo */
div {
float: left;
margin-right: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='anim-on'></div>
<div class='anim-out'></div>
You can find more information about the various CSS properties and how a change to their value will impact the rendering process in the CSS Triggers website.
You can find more information about the rendering process and how using transform (as opposed to few other properties) results in a performance improvement in the below articles/sites:
HTML5 Rocks - Accelerated Rendering in Chrome
GPU Accelerated Compositing in Chrome.
Google Developers - Rendering Performance.
I edited Henry code, now css is reusable, so user can add background image to element via CMS, and css code will do the rest:
.anim {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
**background-size: 0px!important;**
}
.anim:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
top: 0px;
left: 0px;
background-size: cover !important;
**background: inherit;**
z-index: -1;
}
.anim:after {
animation: shrink 12s infinite alternate;
}
#keyframes shrink {
0% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
#keyframes small {
0% {
transform: scale(1);
}
100% {
transform: scale(1.1);
}
}
<section class="anim" style="background: url('images/1.png');"></section>
Thanks * :)