CSS Spritesheet animation keeps moving towards the left - css

I have a spritesheet (9170px x 350px) that has 70 frames of a single character. Here's my code.
#-webkit-keyframes play {
100% {
background-position: -9170px;
}
}
#keyframes play {
100% {
background-position: -9170px;
}
}
.character-one {
width: 131px;
height: 350px;
border: 1px solid #ddd;
margin-left: 20px;
background: url('http://i.imgur.com/gK3C2VZ.png') left center;
-webkit-animation: play 2s steps(70) infinite;
animation: play 2s steps(70) infinite;
}
<div class="character-one"></div>
When I open it in the browser, I see the character getting animated, but the spritesheet moves from right to left inside the div that's there. What could the reason be? I figured that normally happens when the steps() are fewer than the number of frames, but in my case everything seems to be OK. Could it be that the frames are not evenly spaced?
Here's the link to the JSFiddle

Though your actual sprite-sheet is 9170px wide, the individual sprites within it actually have a margin on either side. This is what is causing the sliding effect.
As per your code, there are 70 steps and the background moves by 9170px (which is 131px for each step). But each 131px of the sprite don't seem to exactly overlap one another. In the below image, we can see how the first 131px of the spritesheet and the last 131px look like (background added just for visual distinction).
Changing the background-position like in the below snippet seems to produce a much better output.
#-webkit-keyframes play {
100% {
background-position: -9144px;
}
}
#keyframes play {
100% {
background-position: -9144px;
}
}
.character-one {
width: 131px;
height: 350px;
border: 1px solid #ddd;
margin-left: 20px;
background: url('http://i.imgur.com/gK3C2VZ.png');
background-position: -28px center;
-webkit-animation: play 2s steps(70) infinite;
animation: play 2s steps(70) infinite;
}
<div class="character-one"></div>
In the below sprite-sheet, we can see how there is equal spacing on all sides for each sprite image. It is taken from the Tree House blog on CSS Sprite Sheet Animations.

Sprite images are wrong sliced, distance is vary in all images. Please update sprite images then problem is solved.

Related

changing of background image when rotating not working in css [firefox] [duplicate]

I have several animations on my site that I just realized do not even show up in Firefox or Internet Explorer. I have the background-image within the keyframes. I do this because I have different images in different percentages with the animation.
Why doesn't the background-image display within the keyframes in Firefox and Internet Explorer and is there a way to make this work?
As per the specs, background-image is not an animatable or a transitionable property. But it does not seem to say anything about what or how the handling should be when it is used as part of transition or animation. Because of this, each browser seem to be handling it differently. While Chrome (Webkit) is displaying the background image, Firefox and IE seem to do nothing.
The below quote found in an article at oli.jp provides some interesting information:
While CSS Backgrounds and Borders Module Level 3 Editor’s Draft says “Animatable: no” for background-image at the time of writing, support for crossfading images in CSS appeared in Chrome 19 Canary. Until widespread support arrives this can be faked via image sprites and background-position or opacity. To animate gradients they must be the same type.
On the face of it, it looks like Firefox and IE are handling it correctly while Chrome is not. But, it is not so simple. Firefox seems to contradict itself when it comes to how it handles transition on background image as opposed to animation. While transitioning background-image, it shows up the second image immediately (hover the first div in the snippet) whereas while animating, the second image doesn't get displayed at all (hover the second div in the snippet).
So, conclusion is that it is better to not set background-image inside keyframes. Instead, we have to use background-position or opacity like specified # oli.jp.
div {
background-image: url(https://placehold.it/100x100);
height: 100px;
width: 100px;
margin: 10px;
border: 1px solid;
}
div:nth-of-type(1) {
transition: background-image 1s ease;
}
div:nth-of-type(1):hover {
background-image: url(https://placehold.it/100/123456/ffffff);
}
div:nth-of-type(2):hover {
animation: show-img 1s ease forwards;
}
#keyframes show-img {
to {
background-image: url(https://placehold.it/100/123456/ffffff);
}
}
<div></div>
<div></div>
If you have multiple images that should be shown at different percentages within the keyframe then it would be a better idea to add all those images on the element at start and animate their position like in the below snippet. This works the same way in Firefox, Chrome and IE.
div {
background-image: url(https://placehold.it/100x100), url(https://placehold.it/100/123456/ffffff);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: 0px 0px, 100px 0px;
height: 100px;
width: 100px;
margin: 10px;
border: 1px solid;
}
div:hover {
animation: show-img 1s steps(1) forwards;
}
#keyframes show-img {
to {
background-position: -100px 0px, 0px 0px;
}
}
<div></div>
Or, like in the below snippet. Basically each image is the same size as the container as background-size is set as 100% 100% but only one image is shown at any given time because of them being the same size as container. Between 0% to 50% the first image is shown because it is at 0px,0px (left-top) whereas the second image is at 100px,0px (outside the right border). At 50.1%, the first image is at -100px,0px (outside left border) and second image is at 0px,0px and so it is visible.
div {
background-image: url(https://picsum.photos/id/0/367/267), url(https://picsum.photos/id/1/367/267);
background-size: 100% 100%; /* each image will be 100px x 100px */
background-repeat: no-repeat;
background-position: 0px 0px, 100px 0px;
height: 100px;
width: 100px;
margin: 10px;
border: 1px solid;
animation: show-img 5s ease forwards;
}
#keyframes show-img {
0%, 50%{
background-position: 0px 0px, 100px 0px; /* initially 1st image will be shown as it it as 0px 0px */
}
50.1%, 100% {
background-position: -100px 0px, 0px 0px; /* at 50.1% 2nd image will be shown as it it as 0px 0px */
}
}
<div></div>

Make CSS sprite animation work

Im new to css animation, so I got this sequence movements picture online and want to make it walks. I follow a tutorial but it doesn't work in this case. I'm trying to make it moves. I don't know how to properly do that so I start with the first row of image. Its dimensions are 832x228.
and this is CSS code:
.sprite {
width: 130px;
height: 130px;
display: block;
background: transparent url(http://i.stack.imgur.com/UOPXb.png) 0 0 no-repeat;
animation: walker 1s steps(8) infinite;
}
#keyframes walker {
0% {
background-position: 0 0;
}
100% {
background-position: 832px 0px;
}
}
<div class="sprite"></div>
You are on the right path but the background-position is wrong within the keyframes. Sprite images should move from the right to the left in order to produce a moving animation and so the background position should go from 0 0 to -832px 0.
.sprite {
width: 114px;
height: 114px;
display: block;
background: transparent url(http://i.stack.imgur.com/UOPXb.png) 0 0 no-repeat;
animation: walker 1s steps(8) infinite;
/* image size is 832x228, so height is set as half of it */
}
#keyframes walker {
0% {
background-position: 0 0;
}
100% {
background-position: -832px 0px;
}
}
<div class='sprite'></div>
As mentioned in Robert C's answer, this will still not get the second row of images to show up. This is because the Y part of background-position doesn't change within the keyframes. The below snippet kindly contributed by Mishko Vladimir is one way to get them to display but problem is that if the no. of steps is increased to 16 (so as to show all sprites) then the animation doesn't work properly anymore.
Also, there will be a blink at the point where Y position changes. So, my recommendation would be to put all 16 sprites in the same row instead of two.
.sprite {
width: 114px;
height: 114px;
display: block;
background: transparent url(http://i.stack.imgur.com/UOPXb.png) 0 0 no-repeat;
animation: walker 1s steps(8) infinite;
/*832x228*/
}
#keyframes walker {
0% {
background-position: 0 0;
}
50% {
background-position: -832px 0px;
}
51% {
background-position: 0 -114px;
}
100% {
background-position: -832px -114px;
}
}
<div class='sprite'></div>
Looks like you have the wrong background-position, it should be -832px rather than 832px. Note that with the above image you're also only going to get the top 8 frames, you'll need to edit the file to get the bottom 8 for a longer transition.
You may also want to adjust the time in your animation down to a fraction (I had a smoother walk with 0.9), and you'll want to shrink your width and height down to around 115px to avoid seeing some of the other frames.

CSS animation infinite not working

I have the following code:
.dangerous_b {
width: 636px;
height: 72px;
background-image: url('/media/anim.png');
float: left;
background-color: black;
animation: bganim 100ms steps(1, start) infinite;
}
#keyframes bganim {
from { background-position: 0px 0px; }
to { background-position: 0px -72px; }
}
But the animation is only playing once. What am I doing wrong?
EDIT: Note that the animation plays out once, so there is a visual difference. But I want the animation to loop.
Btw: Here is the picture I used: http://i.imgur.com/fA80qQc.png
2nd EDIT: Here is the code snippet
.dangerous_b {
width: 636px;
height: 72px;
background-image: url('http://i.imgur.com/fA80qQc.png');
float: left;
background-color: black;
animation: bganim 100ms steps(1, start) infinite;
}
#keyframes bganim {
from { background-position: 0px 0px; }
to { background-position: 0px -72px; }
}
<div class="dangerous_b"></div>
3rd EDIT: It's working now with the following code:
.dangerous_b {
width: 636px;
height: 72px;
background-image: url('http://i.imgur.com/fA80qQc.png');
float: left;
background-color: black;
animation: bganim 100ms steps(1, start) infinite;
}
#keyframes bganim {
50% { background-position: 0px -72px; }
}
Reason:
Problem is because of the animation-timing-function. A value of steps(1,start) means that the animation has only one step and it happens right at the start of the animation itself.
As per MDN (picked from definition for step-start but it is same as steps(1, start)):
Using this timing function, the animation jumps immediately to the end state and stay in that position until the end of the animation.
First step of the first iteration happens as soon as the page is loaded (or class is added) and due to it, the background image immediately moves to the position indicated inside the to frame. For the 2nd iteration, the move back to its original position (from frame) and then to the final position (to frame) again happens instantaneously meaning that you don't get to see any visual difference and it looks as though the element is staying at its place without any animation.
.dangerous_b {
width: 636px;
height: 72px;
background-image: url('http://i.imgur.com/fA80qQc.png');
float: left;
background-color: black;
animation: bganim 1s steps(1, start) infinite;
}
#keyframes bganim {
from {
background-position: 0px 0px;
}
to {
background-position: 0px -72px;
}
}
<div class='dangerous_b'></div>
The same behavior can be seen in this fiddle also. This is not my creation but is an adaptation of the demo present as designmodo. The first car never actually moves (or is never actually seen to move) because the step happens right at the start.
Solution 1: Use two steps and double the ending background position
When the no. of steps is set to two, the animation happens as a two step process where the first step again happens at the start of the animation (because of start parameter). This means:
During the first step, the background moves to half distance between the start and the end state.
Since 1st step happens right at the start, background-position is never 0px 0px. (Do note that, I have doubled the end background-position).
In the 2nd step, the background moves to the final position. Because the background images are repeated, 0px -144px is equal to 0px 0px. This creates an illusion of the background moving to its original position.
.dangerous_b {
width: 636px;
height: 72px;
background-image: url('http://i.imgur.com/fA80qQc.png');
float: left;
background-color: black;
animation: bganim 1s steps(2, start) infinite;
}
#keyframes bganim {
from {
background-position: 0px 0px;
}
to {
background-position: 0px -144px;
}
}
<div class='dangerous_b'></div>
Solution 2: Use just one step but change the end position to half way
For some reason, this seems to mimic a two step animation.
In the first half, the background moves to the position indicated within 50% frame.
During second half, it seems to go back to the original position (or 100% position, both of which are the same). Thus when next iteration starts and the image jumps, it moves from 0% or 100% position to 50% position and ends up producing the required animation effect.
.dangerous_b {
width: 636px;
height: 72px;
background-image: url('http://i.imgur.com/fA80qQc.png');
float: left;
background-color: black;
animation: bganim 1s steps(1, start) infinite;
}
#keyframes bganim {
0% {
background-position: 0px 0px;
}
50% {
background-position: 0px -72px;
}
100% {
background-position: 0px 0px;
}
}
<div class='dangerous_b'></div>
If I understand it correctly, it now takes 1 frame to run your animation.
Since your background image is moving out of sight, you won't see it.
https://developer.mozilla.org/nl/docs/Web/CSS/timing-function#The_steps()_class_of_timing-functions

CSS3 transform rotate a nested background image

I have a background which exists of 3 images in total. However the middle background image (wrapper2) is visually 'between' two background images (wrapper1 and wrapper2).
When I try to rotate that middle image (wrapper2), the top-most image (wrapper3) also moves.
How can I prevent this, so that only the middle background-image (wrapper2) can rotate and not also the other one (wrapper3)?
<div id="wrapper1">
<div id="wrapper2">
<div id="wrapper3">
<!-- blabla -->
</div>
</div>
</div>
#wrapper1 {
background-image: url("../media/bg1.png");
background-size: 300px 200px;
background-repeat: no-repeat;
}
#wrapper2 {
background-image: url("../media/bg2.png");
background-size: 300px 200px;
background-repeat: no-repeat;
}
#wrapper3 {
background-image: url("../media/bg3.png");
background-size: 300px 200px;
background-repeat: no-repeat;
}
#wrapper2:hover
{
animation: TestAnim;
animation-iteration-count: infinite;
animation-duration: 10s;
}
#keyframes TestAnim
{
0% { transform:rotate(0deg); }
25% { transform:rotate(-4deg); }
100% { transform:rotate(0deg); }
}
}
ok, wasn't possible the way I worked.
I could either position the divs (absolute/relative) and make them siblings instead of childs.
But i've choosen to create a sprite image of all the rotations that I wanted and using an css3 animation.
In the CSS keyframes animation I move the background position every time:
0% { background-position: 0 0; width: 300px; height: 200px; }
1% { background-position: 0 -200px; width: 300px; height: 200px; }
...
Important is that you have to define the step-start!
animation-timing-function: step-start;
This step-start works fine in Internet Explorer 10.
Remark: For older browsers, the animation will not work (CSS3 is not known or step-start is not known) and your first sprite will be displayed, so make sure your first sprite is your initial state.
For your information: I used The GIMP to create my animation and used a plugin called CSS WebSprites to automatically generate my sprites and CSS code:
The GIMP CSS WebSprites plugin

CSS3 transition: tilt/rotate slightly while moving, then restore to horizontal

Is it possible, using CSS transitions, to tilt (rotate) an element slightly off-horizontal during the first half of its movement--and tilt it back to horizontal during the second half, as it reaches the end of its movement? I don't want a 360-degree spin. Just a slight tilt, then tilt back again.
Here's a picture of the beginning, middle, and end of the transition I have in mind:
This question is best demonstrated by watching it. Here's a fiddle that shows what I would like to achieve--but I'd like to achieve it with CSS transitions, not JavaScript:
http://jsfiddle.net/bmorearty/S5Us6/22/
When you run this, watch the gray box closely. It tilts a bit during motion, then reverses its tilt halfway through--so when it comes to rest, it is no longer tilted.
I would like whole motion this to happen in a single transition from one state to another simply by adding a class to an element--not in two transitions, because that would require me to time the end of one with the beginning of the next.
I suspect the answer would incorporate transition-delay and/or #keyframes.
Thanks.
this would be the css for it:
#card {
padding: 2em;
border: 1px solid gray;
display: inline-block;
position: relative;
background-color: #eee;
/*instead of infinite you can add a number of times you want it running*/
animation: moving infinite 6s;
}
#keyframes moving {
0%{
margin: 0;
}
50% {
-webkit-transform: rotate(45deg);
}
100% {
margin: 50px;
}
}
You could do something like this.
http://cdpn.io/sIxFA
Obviously, you could smooth out the rotation as you please, and add the rotate class on click.
I got it!
The solution is to use a CSS animation with a keyframe that transforms the rotation (e.g., to about 8deg) when it is 50% of the way through, but returns the rotation to 0deg at the end. It's pretty sweet.
Here's a demo on JSBin:
http://jsbin.com/ogiqad/4/edit
(The code below uses -webkit but you can add all the other browser variations to make it work on more browsers.)
#-webkit-keyframes tilt-and-move {
0% {
left: 0;
top: 0;
}
50% {
-webkit-transform: rotate(8deg);
}
100% {
left: 100px;
top: 100px;
}
}
#card {
position: relative;
}
#card.moved {
left: 100px;
top: 100px;
-webkit-animation-duration: 0.4s;
-webkit-animation-name: tilt-and-move;
}

Resources