THE AIM
Obtain a smoother transition between images. At the moment I have a white background between images for a few milliseconds.
THE PROBLEM
Apparently I cannot properly replicate this part of my code as I don't think you can use links in background-image: url(...). In my actual code, I'm using relative paths.
The problem is the white background between picture transition when they first load and are not save in the cache. When starting again the slider, the transition is smoother, i.e. the white background is not shown.
SUMMARY
I would like to obtain a smoother transition between pictures when they first load and are not save in the cache. How could this be done? (jQuery is also welcomed)
h1 {
display: flex;
justify-content: center;
margin: 20vh 0;
background-color: lightblue;
padding: 50px;
}
#keyframes slide {
0% {
background-image: url("https://s.ftcdn.net/v2013/pics/all/curated/RKyaEDwp8J7JKeZWQPuOVWvkUjGQfpCx_cover_580.jpg?r=1a0fc22192d0c808b8bb2b9bcfbf4a45b1793687");
}
25% {
background-image: url("https://s.ftcdn.net/v2013/pics/all/curated/RKyaEDwp8J7JKeZWQPuOVWvkUjGQfpCx_cover_580.jpg?r=1a0fc22192d0c808b8bb2b9bcfbf4a45b1793687");
}
25.01% {
background-image: url("https://image.shutterstock.com/image-photo/micro-peacock-feather-hd-imagebest-260nw-1127238584.jpg");
}
50% {
background-image: url("https://image.shutterstock.com/image-photo/micro-peacock-feather-hd-imagebest-260nw-1127238584.jpg");
}
50.1% {
background-image: url("https://images.pexels.com/photos/326055/pexels-photo-326055.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500");
}
75% {
background-image: url("https://images.pexels.com/photos/326055/pexels-photo-326055.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500");
}
75.1% {
background-image: url("https://media3.s-nbcnews.com/j/newscms/2019_41/3047866/191010-japan-stalker-mc-1121_06b4c20bbf96a51dc8663f334404a899.fit-760w.JPG");
}
100% {
background-image: url("https://media3.s-nbcnews.com/j/newscms/2019_41/3047866/191010-japan-stalker-mc-1121_06b4c20bbf96a51dc8663f334404a899.fit-760w.JPG");
}
}
.slider {
background-image: url("https://s.ftcdn.net/v2013/pics/all/curated/RKyaEDwp8J7JKeZWQPuOVWvkUjGQfpCx_cover_580.jpg?r=1a0fc22192d0c808b8bb2b9bcfbf4a45b1793687");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
animation: slide 30s infinite;
}
.load {
animation: slide 2s;
}
<div class="slider"></div>
<div class="load"></div>
<h1>SOME CONTENT</h1>
UPDATE
The images are now shown as <div class="slider"></div> was missing before. This was pointed out in the first answer below. However, the white background between images is still there.
Your slider and load divs didn't show because there was nothing in them to begin with and no default height specified in the css. I have given the slider a height of 30vh and a width of 100% (I went with that one for demo purposes). I reduced the margin/padding around the h1 (there's a lot!) just so you could see the images better in the snippet. Still might be viewed better full screen.
I added an animation timing (ease-in-out) to the css to make the start and end of the animation slower to make the transition seem a little easier on the eye. The default is ease which makes it fast in the middle; by changing the transition speed, your animation may appear a little smoother.
Hope this helps
h1 {
display: flex;
justify-content: center;
margin: 2vh 0;
background-color: lightblue;
padding: 15px;
}
#keyframes slide {
0% {
background-image: url("https://s.ftcdn.net/v2013/pics/all/curated/RKyaEDwp8J7JKeZWQPuOVWvkUjGQfpCx_cover_580.jpg?r=1a0fc22192d0c808b8bb2b9bcfbf4a45b1793687");
}
25% {
background-image: url("https://s.ftcdn.net/v2013/pics/all/curated/RKyaEDwp8J7JKeZWQPuOVWvkUjGQfpCx_cover_580.jpg?r=1a0fc22192d0c808b8bb2b9bcfbf4a45b1793687");
}
25.01% {
background-image: url("https://image.shutterstock.com/image-photo/micro-peacock-feather-hd-imagebest-260nw-1127238584.jpg");
}
50% {
background-image: url("https://image.shutterstock.com/image-photo/micro-peacock-feather-hd-imagebest-260nw-1127238584.jpg");
}
50.1% {
background-image: url("https://images.pexels.com/photos/326055/pexels-photo-326055.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500");
}
75% {
background-image: url("https://images.pexels.com/photos/326055/pexels-photo-326055.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500");
}
75.1% {
background-image: url("https://media3.s-nbcnews.com/j/newscms/2019_41/3047866/191010-japan-stalker-mc-1121_06b4c20bbf96a51dc8663f334404a899.fit-760w.JPG");
}
100% {
background-image: url("https://media3.s-nbcnews.com/j/newscms/2019_41/3047866/191010-japan-stalker-mc-1121_06b4c20bbf96a51dc8663f334404a899.fit-760w.JPG");
}
}
.slider {
display:inline-block;
background-image: url("https://s.ftcdn.net/v2013/pics/all/curated/RKyaEDwp8J7JKeZWQPuOVWvkUjGQfpCx_cover_580.jpg?r=1a0fc22192d0c808b8bb2b9bcfbf4a45b1793687");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
animation: slide 5s ease-in-out infinite;
height:30vh;
width:100%;
}
.load {
animation: slide 5s infinite;
}
<h1>SOME CONTENT</h1>
<div class="slider"></div>
Related
Why this isn't working? What am I doing wrong?
CSS
#-webkit-keyframes test {
0% {
background-image: url('frame-01.png');
}
20% {
background-image: url('frame-02.png');
}
40% {
background-image: url('frame-03.png');
}
60% {
background-image: url('frame-04.png');
}
80% {
background-image: url('frame-05.png');
}
100% {
background-image: url('frame-06.png');
}
}
div {
float: left;
width: 200px;
height: 200px;
-webkit-animation-name: test;
-webkit-animation-duration: 10s;
-webkit-animation-iteration-count: 2;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
}
DEMO
http://jsfiddle.net/hAGKv/
Updated for 2020: Yes, it can be done! Here's how.
Snippet demo:
#mydiv{ animation: changeBg 1s infinite; width:143px; height:100px; }
#keyframes changeBg{
0%,100% {background-image: url("https://i.stack.imgur.com/YdrqG.png");}
25% {background-image: url("https://i.stack.imgur.com/2wKWi.png");}
50% {background-image: url("https://i.stack.imgur.com/HobHO.png");}
75% {background-image: url("https://i.stack.imgur.com/3hiHO.png");}
}
<div id='mydiv'></div>
Background image [isn't a property that can be animated][1] - you can't tween the property.
Original Answer: (still a good alternative)
Instead, try laying out all the images on top of each other using position:absolute, then animate the opacity of all of them to 0 except the one you want repeatedly.
It works in Chrome 19.0.1084.41 beta!
So at some point in the future, keyframes could really be... frames!
You are living in the future ;)
Works for me.
Notice the use of background-image for transition.
#poster-img {
background-repeat: no-repeat;
background-position: center;
position: absolute;
overflow: hidden;
-webkit-transition: background-image 1s ease-in-out;
transition: background-image 1s ease-in-out;
}
This is really fast and dirty, but it gets the job done: jsFiddle
#img1, #img2, #img3, #img4 {
width:100%;
height:100%;
position:fixed;
z-index:-1;
animation-name: test;
animation-duration: 5s;
opacity:0;
}
#img2 {
animation-delay:5s;
-webkit-animation-delay:5s
}
#img3 {
animation-delay:10s;
-webkit-animation-delay:10s
}
#img4 {
animation-delay:15s;
-webkit-animation-delay:15s
}
#-webkit-keyframes test {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
}
}
#keyframes test {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
}
}
I'm working on something similar for my site using jQuery, but the transition is triggered when the user scrolls down the page - jsFiddle
I needed to do the same thing as you and landed on your question. I ended up taking finding about the steps function which I read about from here.
JSFiddle of my solution in action (Note it currently works in Firefox, I'll let you add the crossbrowser lines, trying to keep the solution clean of clutter)
First I created a sprite sheet that had two frames. Then I created the div and put that as the background, but my div is only the size of my sprite (100px).
<div id="cyclist"></div>
#cyclist {
animation: cyclist 1s infinite steps(2);
display: block;
width: 100px;
height: 100px;
background-image: url('../images/cyclist-test.png');
background-repeat: no-repeat;
background-position: top left;
}
The animation is set to have 2 steps and have the whole process take 1 second.
#keyframes cyclist {
0% {
background-position: 0 0;
}
100% {
background-position: 0 -202px; //this should be cleaned up, my sprite sheet is 202px by accident, it should be 200px
}
}
Thiago above mentioned the steps function but I thought I'd elaborate more on it. Pretty simple and awesome stuff.
Your code can work well with some adaptations :
div {
background-position: 50% 100%;
background-repeat: no-repeat;
background-size: contain;
animation: animateSectionBackground infinite 240s;
}
#keyframes animateSectionBackground {
00%, 11% { background-image: url(/assets/images/bg-1.jpg); }
12%, 24% { background-image: url(/assets/images/bg-2.jpg); }
25%, 36% { background-image: url(/assets/images/bg-3.jpg); }
37%, 49% { background-image: url(/assets/images/bg-4.jpg); }
50%, 61% { background-image: url(/assets/images/bg-5.jpg); }
62%, 74% { background-image: url(/assets/images/bg-6.jpg); }
75%, 86% { background-image: url(/assets/images/bg-7.jpg); }
87%, 99% { background-image: url(/assets/images/bg-8.jpg); }
}
Here is the explanation of the percentage to suit your situation:
First you need to calculate the "chunks". If you had 8 differents background, you need to do :
100% / 8 = 12.5% (to simplify you can let fall the decimals) => 12%
After that you obtain that :
#keyframes animateSectionBackground {
00% { background-image: url(/assets/images/bg-1.jpg); }
12% { background-image: url(/assets/images/bg-2.jpg); }
25% { background-image: url(/assets/images/bg-3.jpg); }
37% { background-image: url(/assets/images/bg-4.jpg); }
50% { background-image: url(/assets/images/bg-5.jpg); }
62% { background-image: url(/assets/images/bg-6.jpg); }
75% { background-image: url(/assets/images/bg-7.jpg); }
87% { background-image: url(/assets/images/bg-8.jpg); }
}
If you execute this code, you will see the transition will be permanantly. If you want the backgrounds stay fixed while a moment, you can do like this :
#keyframes animateSectionBackground {
00%, 11% { background-image: url(/assets/images/bg-1.jpg); }
12%, 24% { background-image: url(/assets/images/bg-2.jpg); }
25%, 36% { background-image: url(/assets/images/bg-3.jpg); }
37%, 49% { background-image: url(/assets/images/bg-4.jpg); }
50%, 61% { background-image: url(/assets/images/bg-5.jpg); }
62%, 74% { background-image: url(/assets/images/bg-6.jpg); }
75%, 86% { background-image: url(/assets/images/bg-7.jpg); }
87%, 99% { background-image: url(/assets/images/bg-8.jpg); }
}
That mean you want :
bg-1 stay fixed from 00% to 11%
bg-2 stay fixed from 12% to 24%
etc
By putting 11%, the transtion duration will be 1% (12% - 11% = 1%).
1% of 240s (total duration) => 2.4 seconds.
You can adapt according to your needs.
The linear timing function will animate the defined properties linearly. For the background-image it seems to have this fade/resize effect while changing the frames of you animation (not sure if it is standard behavior, I would go with #Chukie B's approach).
If you use the steps function, it will animate discretely. See the timing function documentation on MDN for more detail. For you case, do like this:
-webkit-animation-timing-function: steps(1,end);
animation-timing-function: steps(1,end);
See this jsFiddle.
I'm not sure if it is standard behavior either, but when you say that there will be only one step, it allows you to change the starting point in the #keyframes section. This way you can define each frame of you animation.
Like the above stated, you can't change the background images in the animation. I've found the best solution to be to put your images into one sprite sheet, and then animate by changing the background position, but if you're building for mobile, your sprite sheets are limited to less than 1900x1900 px.
I needed to do the same thing recently. Here's a simple implementation
#wrapper { width:100%; height:100%; position:relative; }
#wrapper img { position:absolute; top:0; left:0; width:100%; height:auto; display:block; }
#wrapper .top { animation:fadeOut 2s ease-in-out; animation-fill-mode:forwards; }
#keyframes fadeOut {
0% { opacity:1; }
100% { opacity:0; }
}
<div id="wrapper">
<img src="img1.jpg" class="top" style="z-index:2;">
<img src="img2.jpg" style="z-index:1;">
</div>
You can use animated background-position property and sprite image.
You can follow by this code:
#cd{
position: relative;
margin: 0 auto;
height: 281px;
width: 450px;
}
#cf img{
left: 0;
position: absolute;
-moz-transition: opacity 1s ease-in-out;
transition: opacity 1s ease-in-out;
}
#cf img.top:hover{
opacity: 0;
}
<div id="cf">
<img class="button" src="Birdman.jpg" />
<img src="Turtle.jpg" class="top" />
</div>
You can use the jquery-backstretch image which allows for animated slideshows as your background-images!
https://github.com/jquery-backstretch/jquery-backstretch
Scroll down to setup and all of the documentation is there.
Well I can change them in chrome. Its simple and works fine in Chrome using -webkit css properties.
Ok, maybe stackoverflow can help? :)
I'm trying, without any luck, to create a page transition effect with an svg image.
When the user clicks on a link in Page 1, a diamond shaped svg fades in like a portal into Page 2.
The basic idea is to recreate the space travel in the intro of the Alphaville - Forever Young video: https://www.youtube.com/watch?v=t1TcDHrkQYg
:)
Maybe the diamond also fades in from blue to transparent (but that is the next step).
Diamond svg: https://www.onlinewebfonts.com/icon/413
I suggest you use clip-path instead of a svg since animating an svg that big will be really slow and really laggy. You can change the clip path to show what you want. Bennet Feely created a nice generator that helps with this.
For the animation itself you can increase the width and height to fit your screen. Then fill the remainder by animating the Z axes.
Animation looks better in fullscreen then in the smaller preview
const links = document.querySelectorAll(".page-transition");
const overlay = document.querySelector(".overlay__diamond");
for(const link of links) {
link.addEventListener("click", (event) => {
event.preventDefault();
overlay.classList.add("overlay__diamond--animate");
setTimeout(() => window.location.reload(), 1000);
// This one is correct, one above is for the demo
// setTimeout(() => (window.location.href = link.href), 1000); // Same time as animation duration
});
}
.page {
background: green;
/* For demontrational purposes only, just to increase page size */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.overlay {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
pointer-events: none;
perspective: 500px; /* Needed for translateZ to work */
}
.overlay__diamond {
width: 100%;
height: 100%;
background: blue;
animation: fadeout 1s linear forwards;
}
.overlay__diamond--animate {
animation: zoom 1s linear forwards;
clip-path: polygon(50% 0%, 75% 50%, 50% 100%, 25% 50%);
}
#keyframes fadeout {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes zoom {
0% {
width: 0;
height: 0;
transform: translateZ(0);
}
100% {
width: 100%;
height: 100%;
transform: translateZ(400px); /* Can't go higher then the perspective */
}
}
<div class="page">
<!-- Replace #link with your actual urls -->
<a class="page-transition" href="#link">Link</a>
<a class="page-transition" href="#link">Link</a>
<a class="page-transition" href="#link">Link</a>
<div class="overlay">
<div class="overlay__diamond"></div>
</div>
</div>
I am trying to mimic the CSS animations from a website here: https://stanographer.com/
I want to copy the way the site:
starts by showing a full screen black div sliding away to the right
"loads" the black background (div tags) behind text (as in "Hi, I'm Stanley Sakai"), expanding left to right and
"loads" the text over the black background div, expanding left to right.
Now you might ask, "Why not just inspect the page, look at the classes on the divs and text, then inspect the CSS sheet in the network tab?" And I've tried that. The CSS looks weird. My friend said it is pre-processed by SASS, whatever that means. Anyway, I cannot decipher the code.
I've been to a few different StackOverflow pages (here's one) & over a dozen different pages on Google. I learned about using keyframes but I haven't figured out how to recreate the effect on Stanographer.com. My friend, who owns the website, also provided this example, but I don't get how to apply it to individual divs. He said something about using the z-index but I just don't see it.
I know that to make the page start with a full black screen & then slide out, I have to trigger a class change using JavaScript. I have:
let blackStuff = document.getElementById("blackness");
window.addEventListener("load", () => {
console.log("loaded");
blackStuff.setAttribute("class", "black-box-out");
},
false
);
.black-box {
position: fixed;
float: left;
top: 0;
width: 100%;
height: 100%;
bottom: 0;
background-color: #000;
z-index: 999999;
-webkit-animation: powerslide 0.5s forwards;
-webkit-animation-delay: 2s;
animation: powerslide 0.5s forwards;
animation-delay: 2s;
}
#-webkit-keyframes powerslide {
100% {
left: 0;
}
}
#keyframes powerslide {
100% {
left: 0;
}
}
.black-box-out {
margin-left: 100%;
animation: slide 0.5s forwards;
-webkit-transition: slide 0.5s forwards;
transition: slide 0.5s forwards;
}
<div id="blackness" class="black-box"></div>
But this just makes the "blackness" div disappear instantly on page load. I want it to slide out. Clearly, I don't get how to use CSS animations.
If you are interested in seeing more of what doesn't work, read on. Otherwise, you can skip this section: it only shows my failed trials.
I've learned how to make a CSS animation expand horizontally from 0:
.wrapper {
position: relative;
overflow: hidden;
width: 500px;
height: 50px;
border: 1px solid black;
}
.slide-custom {
width: 500px;
height: 50px;
background: cyan;
position: relative;
-webkit-animation: slideIn 2s forwards;
animation: slideIn 2s forwards;
}
/* moz and webkit keyframes excluded for space */
#keyframes slideIn {
0% {
transform: scaleX(0);
}
100% {
transform: scaleX(1);
}
}
<div class="wrapper slide-custom">
<h1 class="slide-custom">
<span>MEET ROLY POLY.</span>
<!-- expands horizontally from 0 width to 100% width -->
</h1>
</div>
And I've learned to make text "slide in" from the left, though it starts at 100% width when I want it to start at 0% width:
/* CSS */
.test-slide {
animation-duration: 3s;
animation-name: testSlide;
}
#keyframes testSlide {
from {
margin-left: 0%;
width: 50%;
}
to {
margin-left: 100%;
width: 100%;
}
}
<div class="test-slide">
<h1><span>ABOUT.</span></h1>
<!-- will slide in from the left -->
</div>
There's more -- unfortunately none of it mimics the website I'm trying to copy.
Explanation
There are multiple ways to achieve what you want actually. I did not opt to animate width. The first few frames of the animation will be not as expected.
So instead, we can use clip-path. What clip-path basically does is masking. You can "crop" a div such that only a part of it is visible. We will utilise clip-path and ::before or ::after pseudo-element (either is fine) to create this animation. What we need to do:
Create the pseudo-element and position it such that it covers (is on top) the whole animatable element (position: absolute)
Set the pseudo-element's background to black
Using clip-path, mask the animatable element to display no parts of the element (this will also cause the pseudo-element to not be displayed as it is part of the element). The direction of the clipping is important. The direction here is from the right side to the left side.
Using animation and #keyframes, unmask the previously masked div. This will reveal it slowly from the left side to the right side (because initially, we masked it from the right to left; upon unmasking, the reverse direction happens)
Upon unmasking the element, the pseudo-element will be on top of the text we want to display
After a short while later, mask the pseudo-element (not the whole element) from the right direction to the left direction, again using clip-path so that the text seems revealed slowly
It works! However, I recommend reading about clip-path. Also, one really handy clip-path CSS generator I really like to use is this (if you want to clip from the right to left, you should drag the points from the right to left). I also highly recommend reading about CSS positioning (a staple in good CSS animations). You needn't be using z-index: 9999; you generally want to keep track of the z-index you use.
Solution
Here's a working solution using the described method. Try running it.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Helvetica;
}
body,
html {
width: 100%;
height: 100%;
}
#wrapper {
background: #555555;
width: 100%;
height: 100%;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#wrapper * {
margin: 5px;
}
.heading {
font-size: 3em;
padding: 10px 5px;
}
.caption {
font-size: 1em;
padding: 5px;
font-family: Courier;
}
.animatable {
position: relative;
clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
animation: .75s cubic-bezier(1,-0.01,.12,.8) 1s 1 reveal forwards;
}
.animatable::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #20262b;
padding: inherit;
animation: .75s cubic-bezier(1,-0.01,.12,.8) 1.75s 1 hideBlack forwards;
}
#keyframes reveal {
from { clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%); }
to { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
}
#keyframes hideBlack {
from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
to { clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%); }
}
<div id="wrapper">
<div class="heading animatable">Hi, I am Richard!</div>
<div class="caption animatable">I am a person.</div>
</div>
Although the simple animation you wanted can be created using merely CSS, I still suggest you read about how to make animations using JavaScript and the various libraries it has in making animations. This is because once there are many animations and transitions going on, it becomes hard to keep track of animations (especially when you want animations to start after another animation ends). A good library is anime.js (do explore more options before settling on one). Furthermore, notice how the animations only appear upon scrolling down in the website you provided? That's doable only with JS (one such method is using IntersectionObserver API provided by most browsers).
Here you have some CSS3 animations, you trigger that animation when the .entrance-animation gets the .active class.
You'll need an observer to watch when the item gets into view and, when the item is visible, you add the .active class to it.
Hope it helps!
setTimeout(() =>
{
let animate = document.querySelectorAll('.entrance-animation');
animate.forEach(item => item.classList.add('active'));
}
,1000);
.entrance-animation
{
position: relative;
color: blueviolet;
white-space: nowrap;
font-size: 24px;
width: 0;
overflow: hidden;
transition: width 0.5s ease;
}
.entrance-animation::before
{
content: '';
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 100%;
background-color: black;
z-index: 10;
transition: width 0.5s ease;
transition-delay: 0.5s;
}
.entrance-animation.active
{
width: 100%;
}
.entrance-animation.active::before
{
width: 0%;
}
<p class="entrance-animation">
Hello
</p>
<p class = "entrance-animation">
Here we are
</p>
You can use CSS3 transitions or maybe CSS3 animations to slide in an element.
For browser support: http://caniuse.com/
I made two quick examples just to show you how I mean.
CSS transition (on hover)
Demo One
Relevant Code
.wrapper:hover #slide {
transition: 1s;
left: 0;
}
In this case, Im just transitioning the position from left: -100px; to 0; with a 1s. duration. It's also possible to move the element using transform: translate();
CSS animation
Demo Two
#slide {
position: absolute;
left: -100px;
width: 100px;
height: 100px;
background: blue;
-webkit-animation: slide 0.5s forwards;
-webkit-animation-delay: 2s;
animation: slide 0.5s forwards;
animation-delay: 2s;
}
#-webkit-keyframes slide {
100% { left: 0; }
}
#keyframes slide {
100% { left: 0; }
}
Same principle as above (Demo One), but the animation starts automatically after 2s, and in this case I've set animation-fill-mode to forwards, which will persist the end state, keeping the div visible when the animation ends.
Like I said, two quick example to show you how it could be done.
EDIT: For details regarding CSS Animations and Transitions see:
Animations
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations
Transitions
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
Hope this helped.
I am creating an interactive touchscreen display using a program called Intuiface and have created some background tiles/squares that I want to make look 'alive' by transitioning slowly between colours.
I have used a linear-gradient transition in CSS to do it but the problem is that the transition looks choppy. The program is running 12 visible tiles (it is a very large touchscreen).
I have tried using fewer colours and running on more powerful GPUs (I think it is CPU run anyway) but this hasn't helped.
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s ease infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
At the moment the animations are noticeably choppy. I would like the transition to be much smoother. Does anyone know how I can achieve this?
Here is the code snippet.
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s ease infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body>
</body>
</html>
Animating background-* properties can be resource intensive - you can try animating transform for relatively better performance - see demo below using traslate for the animation:
body {
margin: 0;
}
div {
height: 100vh;
overflow: hidden;
}
div:after {
content: '';
display: block;
width: 400vw;
height: 400vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
animation: gradient 15s ease infinite;
}
#keyframes gradient {
50% {
transform: translate(-300vw, -300vh);
}
}
<div></div>
Since your animation lasts 15 seconds, trying to run it at full 60fps would mean calculating 15*60 = 900 frames.
Since the difference between a frame and the next is quite small, you can make the CPU work quite less asking for a stepped animation, for instance with steps(75)
It could be also good to set slight delays between animations, so that they don't execute at the same time
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s infinite steps(75);
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body>
</body>
</html>
We need to create a screensaver where image should roll over again and again continuously to the left. We coded as shown below.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<style>
.animator {
background-image: url(https://upload.wikimedia.org/wikipedia/commons/3/33/Jordansallotments.jpg);
animation: move-background 2s linear infinite;
position: absolute;
width: 100%;
height: 100%;
}
html,
body {
position: relative;
width: 100%;
height: 100%;
}
#keyframes move-background {
0% {
background-position: 0%, 0%;
}
100% {
background-position: 100%, 0%;
}
}
</style>
</head>
<body>
<div class="animator"></div>
</body>
</html>
The image is rolling over again and again as expected but every 2seconds, we are getting flickering effect. Please see the demo here.
As a fiddle
Can any one please help me to fix this or is there any way to achieve the effect of rolling one image over and over continuously using javascript?
I tried with javascript as below.
<script type="text/javascript">
var bdg_img = document.getElementById('bdgimg');
var animate;
function moveRight()
{
bdg_img.style.left = bdg_img.style.left || 0;
bdg_img.style.left = parseInt(bdg_img.style.left) + 10 + 'px';
animate = setTimeout(moveRight,40); // call moveRight in 20msec
}
moveRight();
</script>
But this is only moving the image to right. The image is not rolling over.
The percentage value in background-position: xxx% is relative to the element's size, not to your actual image's.
So if you want to keep the original background-image-size, you will have to set this background-position relative to your media's size:
.animator {
background-image: url(https://upload.wikimedia.org/wikipedia/commons/3/33/Jordansallotments.jpg);
background-position: 0% 50%;
animation: move-background 2s linear infinite;
width: 100vw;
height: 100vh;
}
#keyframes move-background {
to {
/* the image is 1225*800px */
background-position: -1225px 50%;
}
}
<div class="animator"></div>
Also note that when you do
background-position: 100%, 0%;
You are actually setting two background-position rules, which would be used only if you did set two background-image rules, and is indeed a short-hand for :
background-position-x: 100%, 0%;
background-position-y: 100%, 0%;
you can use very long animation time and repeat background to produce the effect.
*this animation play more than 10day (and may flicker once), but you can make it longer if you want.
*of course you can do the same thing (modify the style) in javascript by setInterval or alike. and have real infinity duration (at least until it reach numeric limit).
.canvas{
width: 300px;
height: 100px;
background-image: url(https://upload.wikimedia.org/wikipedia/commons/3/33/Jordansallotments.jpg);
background-size: auto 100%;
background-repeat: repeat-x;
animation: move-background 1000000s linear infinite;
}
#keyframes move-background {
0% {
background-position: 0 0;
}
100% {
background-position: -20000000px 0;
}
}
<div class="canvas"></div>