Note: This question requests an explanation of CSS transform output on Chrome.
Description
I made a rhombus using css skew and rotate transforms.
I added :hover pseudo-class to that element and changed its skew angle.
The expected result was that on hovering the rhombus, the angle of the rhombus will change.
Here is the fiddle and
snippet :
div {
height: 200px;
width: 200px;
position: relative;
top: 140px;
left: 120px;
-webkit-transform: rotate(-45deg) skew(10deg, 10deg);
-moz-transform: rotate(-45deg) skew(10deg, 10deg);
transform: rotate(-45deg) skew(10deg, 10deg);
background: red;
transition: 0.8s linear all;
}
div:hover {
-webkit-transform: rotate(-45deg) skew(-30deg, -30deg);
-moz-transform: rotate(-45deg) skew(-30deg, -30deg);
transform: rotate(-45deg) skew(-30deg, -30deg);
transition: 0.8s linear all;
}
<div></div>
Problem
This is working fine on Firefox v35.0.1 and IE v10. See the output below :
But on Chrome 40.0.2214.115, the output seems to be different. The angle of the rhombus changes, but not evenly. And near the end of transition of transform property, the rhombus "step-ends" to the desired output, instead of transforming transitionally.
Its neither working with skewX(Xdeg) skewY(Ydeg) nor skew(Xdeg, Ydeg) : fiddle.
The GC output is below :
Question : Chrome seems to support the deprecated skew(Xdeg, Ydeg) but the output with transition is buggy. * What is causing this strange output with chrome?**
Note: This effect is achievable using scaleX transform too, but this is a deliberately made question.
You could try using clip-path: polygon() to achieve the same effect. Not yet supported in all browsers unfortunately.
div {
width: 200px;
height: 280px;
background: red;
-webkit-clip-path: polygon(50% 20%, 100% 50%, 50% 80%, 0% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
transition: all 0.5s ease;
}
div:hover {
-webkit-clip-path: polygon(50% 0%, 80% 50%, 50% 100%, 20% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
/* center */
html, body { height: 100%; }
body {
display: flex;
justify-content: center;
align-items: center;
}
<div></div>
I have been working with transitions now on chrome. I find using position tags like this.
div:hover {
position:relative; /*Desribes the type of position*/
left:40; /*X Coordinate*/
top:25; /*Y Coordinate*/
}
Make the transitions work on chrome.
Here are some resources
-https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
-http://blog.wercker.com/2013/10/02/Chrome-css-animation.html
Hope it helped :)
Related
Chromium version 75.0.3770.100 (Official Build) Arch Linux (64-bit).
Also observed on Android in Brave (also based on Chromium 75).
I'm making a spinning square filled with a white gradient:
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
backface-visibility: hidden;
}
#keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
<div class="spinning"></div>
This works fine on Firefox. However, on Chrome, I initially see a black square rather than a white one. It's as if Chrome forgot to render the element's layer. Also, the axis of rotation is slightly off center. When I right-click the square and choose "Inspect", it suddenly realizes the error of its ways and turns white.
It looks like I'm running into issue 966019, which appeared in Chrome 75 or maybe 74 and has been confirmed and assigned, but not yet fixed.
Worth noting:
A background-color in addition to the background-image makes the square turn that colour rather than black.
If I put some text inside the div, I get an invisible square rather than a black one.
Workarounds:
It doesn't happen with backface-visibility: visible. But I need it to be hidden because the square in my actual situation has two differently-coloured sides, created by two such spinning squares that are 180 degrees out of phase.
It doesn't happen with a plain background-color instead of the gradient. But the gradient is needed to fit in with the rest of the style.
It doesn't happen if I start the rotation at 0deg and go through 360deg. But then it would start at the same moment as the "front" side.
Since all of these have undesirable side effects, I'm looking for a better workaround.
Another solution is to consider pseudo element to create both sides and you won't have the bug and you can easily manage each side alone.
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
position: relative;
transform-style:preserve-3d;
}
.spinning:before,
.spinning:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
backface-visibility: hidden;
}
.spinning:before {
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
.spinning:after {
transform: rotateY(180deg);
background:rgba(255,0,0,0.5);
}
#keyframes spinning {
0% {
transform: rotate3d(1, -1, 0, -180deg);
}
100% {
transform: rotate3d(1, -1, 0, 180deg);
}
}
<div class="spinning"></div>
One other workaround is to trigger an animation on your element's pseudo-element content property:
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
backface-visibility: hidden;
animation-fill-mode: forwards;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
.spinning::after {
content: "";
animation: trigger-paint .1s forwards 1;
}
#keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
#keyframes trigger-paint {
0% {content: ""}
100% {content: none}
}
<div class="spinning"></div>
But since the trick here is that it forces a repaint, I fear this comes with huge performance impacts (according to my dev tools, it does restart the animation a whole lot of times, even though it's set to kick on once).
Finally resolved it by not relying on backface-visibility but rather just animating visibility myself:
.spinning {
animation-name: spinning, hide-backface;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear, step-start;
width: 100px;
height: 100px;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
#keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
#keyframes hide-backface {
0% { visibility: hidden; }
25% { visibility: hidden; }
75% { visibility: visible; }
100% { visibility: hidden; }
}
<div class="spinning"></div>
I've made a pie timer animation using only HTML/CSS. You can see it here:
https://jsfiddle.net/yisusans/why2wy5q/
.timer-container {
background: -webkit-linear-gradient(left, #677291 50%, #D8DAE5 50%);
border-radius: 100%;
height: 30px;
position: relative;
top: 5px;
left: 9px;
width: 30px;
-webkit-animation: time 20s linear 1;
animation: time 20s linear 1;
-webkit-transition-timing-function: ease-in;
transition-timing-function: ease-in;
-webkit-transition-duration: 1s;
transition-duration: 1s;
-moz-transform: translateZ(1) scale(1.0, 1.0);
-ms-transform: translateZ(1) scale(1.0, 1.0);
-o-transform: translateZ(1) scale(1.0, 1.0);
-webkit-transform: translateZ(1) scale(1.0, 1.0);
transform: translateZ(1) scale(1.0, 1.0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.timer {
border-radius: 100% 0 0 100% / 50% 0 0 50%;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 50%;
-webkit-animation: mask 20s linear 1;
-webkit-transform-origin: 100% 50%;
-webkit-transition-timing-function: ease-in;
-webkit-transition-duration: 1s;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
#-webkit-keyframes time {
100% {
-webkit-transform: rotate(360deg);
}
}
#-webkit-keyframes mask {
0% {
background: #D8DAE5;
-webkit-transform: rotate(0deg);
}
50% {
background: #D8DAE5;
-webkit-transform: rotate(-180deg);
}
50.01% {
background: #677291;
-webkit-transform: rotate(0deg);
}
100% {
background: #677291;
-webkit-transform: rotate(-180deg);
}
}
#keyframes time {
100% {
transform: rotate(360deg);
}
}
#keyframes mask {
0% {
background: #D8DAE5;
transform: rotate(0deg);
}
50% {
background: #D8DAE5;
transform: rotate(-180deg);
}
50.01% {
background: #677291;
transform: rotate(0deg);
}
100% {
background: #677291;
transform: rotate(-180deg);
}
}
<div class='timer-container'>
<div class='timer'></div>
</div>
It works but it's a bit shaky. Any tips to smooth out the animation would be amazing.
Thanks!
It's running very smoothly on my MacBook Pro in Safari, Chrome and Firefox, but CSS animations are subject to performance differences between devices and browsers. You might just be seeing the limitations of your device.
It's also likely to run more smoothly outside of jsfiddle.
I came across this post:
Improving CSS3 transition performance
It's been pretty informative in relation to animation performance. But I'd love to see if anyone else has any other insights.
firstly,
good job...
secondly,
It seems I am 4 years late for this answer. but, here goes...
Like #dave suggested in the above post... I also failed to recreate the shakiness issue you have with the animation. (even increasing the height and width property of the .timer-container selector and taking a closer look) It's running pretty smooth. And there seems to be nothing wrong with the code snippet you have provided.
But I will leave this answer for people who want a quick fix for common CSS animation shakiness that they might experience.
set
backface-visibility: hidden;
on the element, you are animating.
and only change opacity and transform property when animating.
Browsers are optimized for animating these properties and will ensure that you minimize any performance overhead.
Pretty much any animation you want can be achieved using transforms.
I'm trying to create a 3d navbar using pure CSS with transforms, transitions and perspective.
Here is my code:
.navbar-fixed-bottom {
background: transparent;
}
.navbar-perspective {
width: 100%;
height: 100%;
position: relative;
-webkit-perspective: 1100px;
-moz-perspective: 1100px;
perspective: 1100px;
-webkit-perspective-origin: 50% 0;
-moz-perspective-origin: 50% 0;
perspective-origin: 50% 0;
}
.navbar-perspective > div {
margin: 0 auto;
position: relative;
text-align: justify;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
height: 50px;
font-size:20px;
}
.navbar-primary {
background-color: #cccccc;
z-index: 2;
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
transform-origin: 0% 100%;
}
.navbar .navbar-secondary,
.navbar .navbar-tertiary {
background-color: #bfbfbf;
width: 100%;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
transform-origin: 0% 0%;
z-index: 1;
-webkit-transform: rotateX(-90deg);
-moz-transform: rotateX(-90deg);
transform: rotateX(-90deg);
-webkit-transition: top 0.5s;
-moz-transition: top 0.5s;
transition: top 0.5s;
position: absolute;
top: 0;
}
.navbar .navbar-tertiary {
background-color: #b3b3b3;
}
.navbar-rotate-primary {
height: 50px;
}
.navbar-rotate-primary .navbar-primary {
-webkit-transform: translateY(0%) rotateX(0deg);
-moz-transform: translateY(0%) rotateX(0deg);
transform: translateY(0%) rotateX(0deg);
}
.navbar-rotate-primary .navbar-secondary,
.navbar-rotate-primary .navbar-tertiary {
top: 100%;
-webkit-transition: -webkit-transform 0.5s;
-moz-transition: -moz-transform 0.5s;
transition: transform 0.5s;
-webkit-transform: rotateX(-90deg);
-moz-transform: rotateX(-90deg);
transform: rotateX(-90deg);
}
.navbar-rotate-secondary,
.navbar-rotate-tertiary {
height: 50px;
}
.navbar-rotate-secondary .navbar-primary,
.navbar-rotate-tertiary .navbar-primary {
-webkit-transform: translateY(-100%) rotateX(90deg);
-moz-transform: translateY(-100%) rotateX(90deg);
transform: translateY(-100%) rotateX(90deg);
}
.navbar-rotate-secondary .navbar-secondary,
.navbar-rotate-tertiary .navbar-secondary {
top: 100%;
-webkit-transition: -webkit-transform 0.5s;
-moz-transition: -moz-transform 0.5s;
transition: transform 0.5s;
-webkit-transform: rotateX(0deg) translateY(-100%);
-moz-transform: rotateX(0deg) translateY(-100%);
transform: rotateX(0deg) translateY(-100%);
}
.navbar-rotate-secondary-fallback .navbar-primary,
.navbar-rotate-tertiary-fallback .navbar-primary {
display: none;
}
.navbar-rotate-tertiary .navbar-secondary {
-webkit-transform: translateY(-100%) rotateX(90deg);
-moz-transform: translateY(-100%) rotateX(90deg);
transform: translateY(-100%) rotateX(90deg);
}
.navbar-rotate-tertiary .navbar-tertiary {
top: 100%;
-webkit-transition: -webkit-transform 0.5s;
-moz-transition: -moz-transform 0.5s;
transition: transform 0.5s;
-webkit-transform: rotateX(0deg) translateY(-100%);
-moz-transform: rotateX(0deg) translateY(-100%);
transform: rotateX(0deg) translateY(-100%);
}
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<nav id="navigation-bottom" class="navbar navbar-fixed-bottom">
<div class="navbar-perspective">
<div class="navbar-primary">
Rotate To Face 2
</div>
<div class="navbar-secondary">
Rotate To Face 3
</div>
<div class="navbar-tertiary">
Rotate Back To Face 1
</div>
</div>
</nav>
</body>
</html>
I've got the first two faces to rotate properly using a 3d effect, but the third face does not look right. You will notice as you rotate from second to third that the top does not rotate correctly and looks flat.
Any help is greatly appreciated.
Fiddle with a flipping box
This is vastly different from where you started, but let me post my CSS and show you the fiddle, and then I'll edit in a longer explanation of how and why this works:
HTML
<section class="container">
<nav id="nav-box" class="show-front">
<div class="front">
Show Bottom
</div>
<div class="bottom">
Show Back</div>
<div class="back">
Show Top</div>
<div class="top">
Show Front</div>
</nav>
</section>
CSS
.container {
position: relative;
perspective: 1000px;
transform: scale(0.95);
}
#nav-box {
width: 100%;
height: 50px;
position: absolute;
transform-origin: center center;
transform-style: preserve-3d;
transition: transform 0.5s;
}
#nav-box div {
width: 100%;
height: 50px;
display: block;
position: absolute;
transition: background-color 0.5s;
}
#nav-box .front { transform: rotateX( 0deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .back { transform: rotateX( 180deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .top { transform: rotateX( 90deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box .bottom { transform: rotateX( -90deg ) translateZ( 25px ); background-color: #ccc; }
#nav-box.show-front { transform: rotateY( 0deg ); }
#nav-box.show-front .bottom { background-color: #a0a0a0; }
#nav-box.show-front .top { background-color: #e0e0e0; }
#nav-box.show-back { transform: rotateX( -180deg ); }
#nav-box.show-back .bottom { background-color: #e0e0e0; }
#nav-box.show-back .top { background-color: #a0a0a0; }
#nav-box.show-top { transform: rotateX( -90deg ); }
#nav-box.show-top .front { background-color: #a0a0a0; }
#nav-box.show-top .back { background-color: #e0e0e0; }
#nav-box.show-bottom { transform: rotateX( 90deg ); }
#nav-box.show-bottom .front { background-color: #e0e0e0; }
#nav-box.show-bottom .back { background-color: #a0a0a0; }
Explanation of the HTML/CSS
Setting up our box
You started thinking about this the wrong way, I hate to say. You approached this as "How can I treat these four sides like a box" rather than "How can I make a box in CSS?"
So let's learn how to make a box.
First, we establish a box container. Since this is a navigation box, let's call it nav-box. All the transforms we apply (save for the shading, which we'll get to later) will be done on our nav-box.
The rules on our nav-box will determine how it behaves as an object. Let's discuss two in particular: transform-origin and transform-style
transform-origin defaults to center center, but I wanted to call it out here. This is basically going to tell our box: Hey, we need you to pivot around your absolute center. If we set this up as transform-origin: center bottom' it would look like the box is spinning around its bottom edge. center top` and it would spin around its top edge. I don't think that's what you want, though.
transform-style needs to be set to preserve-3d. What this does is instruct the browser to not fuss with the elements with transform underneath it. Other options include flat which tells the browser to ignore rotates underneath it. The reason we want to set preserve-3d on our nav-box here is to ensure the transforms we applied to the box sides are preserved when we transform the parent. Neat stuff, huh?
Setting up our sides
We're setting our sides as children of our nav-box and just positioning them in the order that they should be in using rotateX:
0 rotation for the front
180deg for the back
-90deg for the bottom
90deg for the top
We could also set a left and right side right now with .left { transform: rotateY(-90deg); } .right { rotateY(90deg); }. Note that we used the Y axis for those two examples.
Secondly, we set a translateZ value of 25px. So what the hell is this doing? It's telling our boxes they need to move 25px from the center of the parent relative to their respective rotations. Why did we choose 25px? Because it's exactly half the height of each of our boxes. This means that it will flush up nicely with the sides at either edge.
And then the fun part:
We shade the boxes based on their position and what is facing the screen. The background colors are relative to what side of the box we're showing with show-front, show-back, etc. The side on the bottom gets darker, the side on the top gets lighter. I just liked that – totally not necessary to accomplish this task but makes it look a little more realistic.
Hope that helps!
Update for IE
Fiddle Example
So, there's not much pretty about this once we get through fixing it up for IE, but here it is. All preserve-3d is doing is applying the transforms for you when we rotate a container, instead of flattening them. If we can't use preserve-3d, we have to calculate based on the amount of total rotation.
This solution does that. I won't go as in-depth on this one, rather than to highlight how much more JavaScript this requires, and to highlight the .rewind class:
#nav-box.rewind div {
backface-visibility: hidden;
}
Because we have to manually rewind this solution, we'll have to prevent the z-index reordering to be applied at the wrong times. That's where backface-visibility comes in.
Example showing depth in IE
Another example without the need for the rewind class
Hope that solves IE for you.
First of all, thank you to all that commented and answered to this question, especially Josh!
Josh, your example works perfectly for browsers that support preserve-3d. The update you posted without preserve-3d appears flat on IE so it was still not perfected for all browsers.
After three days of headaches, I realized the problem. The origin of the sides was not being set correctly. The sides need to rotate around a point that is half way in on the Z axis.
Once I've updated the origin to :
transform-origin: 25px 25px -25px;
Once this was correct, all you really need to do is update the rotation of the object. No need to use any transformation of the X,Y,Z coordinates.
Here's the fiddle and the solution for a 3D Navigation bar that rotates and works for all browsers including IE10+.
http://jsfiddle.net/tx0emcxe/
I have a CSS3 Animation for an indeterminate progress bar. In the animation I have a gradient oscillating back and forth along the progress bar. I would like to flip the image of gradient horizonally as it travels back to the left side of the progress bar. Basically the gradient always fades out the opposite direction the image is moving. Unfortunately I can't figure out a way for the image to flip horizontally BEFORE it starts moving back towards the left and am getting some odd transformations of the image as it flips.
I have created a JSFiddle to show how it looks right now.
http://jsfiddle.net/MtWzL/
Here is the CSS I'm currently using for the animation:
#-webkit-keyframes loader {
0% {
-webkit-transform: scaleX(1);
-webkit-transform: translateX(-100px);
-webkit-transform-origin:left;
}
50% {
-webkit-transform: translateX(300px);
}
100% {
-webkit-transform: translateX(-100px);
-webkit-transform: scaleX(-1);
}
}
#keyframes loader {
0% {
transform: scaleX(1);
transform: translateX(-100px);
transform-origin:left;
}
50% {
transform: translateX(300px);
}
100% {
transform: translateX(-100px);
transform: scaleX(-1);
}
}
.slider
{
animation: loader 2.5s infinite linear;
-webkit-animation: loader 2.5s infinite linear; /* Safari and Chrome */
background: url('http://s23.postimg.org/mglkwgxuv/indeterminate_bg.png') no-repeat;
border-radius: 10px;
height: 10px;
position: relative;
width: 100px;
z-index: 999;
opacity: .6;
}
.container {
background: -webkit-linear-gradient(#00c3ff,#0071bc);
background: linear-gradient(#00c3ff,#0071bc);
border-radius: 3px;
height: 10px;
overflow: hidden;
width: 300px;
}
.background {
background: rgba(0,0,0,0.7);
border-radius: 3px;
display: inline-block;
padding: 10px;
}
There are 2 issues that need to be fixed
first of all, this
-webkit-transform: scaleX(1);
-webkit-transform: translateX(-100px);
won't work as you expect; the second property over-rides the first one, as you can not set 2 different values for a property in separate lines.
the correct syntax would be
-webkit-transform: translateX(-100px) scaleX(1);
And second, if you want a sudden change in some value, you need to set it from a keyframe to another keyframe close enough to the first one.
So, the solution would be
#-webkit-keyframes loader {
0% { -webkit-transform: translateX(-100px) scaleX(1); }
50% { -webkit-transform: translateX(300px) scaleX(1); }
51% { -webkit-transform: translateX(300px) scaleX(-1); }
100% { -webkit-transform: translateX(-100px) scaleX(-1); }
}
corrected fiddle
I have corrected only the webkit transforms, but the same concept applies to the rest.
I was watching for your problem since you put it here, but I guess its some kind of bug we won't solve or maybe I just dont understand why it is working like that.
Since I had no clue how to solve it I manage to do example for you with alternative solution
EXAMPLE
As you can see I modified your jsfiddle, simple words, created another slide loader .sliderBack that goes backwards. Hope it will helps you somehow. Peace :)
I am trying to do a css3 animation on multiple elements.
All those elements have different background-image and they must be replace in the middle of the animation.
The thing is, I want to use the same animation for all elements.
Wich mean, I can't write the original background-image in the animation.
But, the absence of original background-image make the background-image animate with the rest.
I think I would need something like:
background-image: default;
But I don't think it exist.
Anyone have an idea?
Example:
http://jsfiddle.net/4SRrR/
(Look how the background-image start fading to the red one before the div is out of the screen.)
Html:
<div class="anim"></div>
Css:
.anim {
position: absolute;
top: 0;
left: 0;
width: 400px;
height: 400px;
background-image: url("http://www.webdesign.org/img_articles/15485/Step1.png");
-webkit-animation: anim .75s forwards ease-in;
}
#-webkit-keyframes anim {
0% {-webkit-transform: translateX(0px);}
50% {-webkit-transform: translateX(-400px);}
51% {-webkit-transform: translateX(-400px); background-image: url("http://www.vt2k.com/processing/images/redball.jpg");}
100% {-webkit-transform: translateX(0px); background-image: url("http://www.vt2k.com/processing/images/redball.jpg");}
}
One posibility would be to have 2 backgrounds, and then in the animation just reference the sizes of the first and the second one:
fiddle
The CSS would be:
.anim {
position: absolute;
top: 0;
left: 0;
width: 400px;
height: 400px;
background-image: url("http://www.webdesign.org/img_articles/15485/Step1.png"), url("http://www.vt2k.com/processing/images/redball.jpg");
background-size: 100% 100%, 0% 100%;
background-repeat: no-repeat;
-webkit-animation: anim 7.5s forwards ease-in;
}
#-webkit-keyframes anim {
0% {-webkit-transform: translateX(0px); background-size: 100% 100%, 0% 0%;}
50% {-webkit-transform: translateX(-400px);background-size: 100% 100%, 0% 0%;}
51% {-webkit-transform: translateX(-400px); background-size: 0% 0%, 100% 100%; }
100% {-webkit-transform: translateX(0px); background-size: 0% 0%, 100% 100%;}
}
I have increased the duraion of the transition so that it is more visible. And also overdefined the background-size; it wouldn't be necesary to repeat it in every frame.
I'm confused as to what the question is but I'll take a stab at it. If you take the 51% animation off then it seems to work slightly better. It will shrink until it is gone and then as it comes back the background-image fades in.
One of the hard things with CSS3 animations is that there isn't an easy way to tell when the animation is 50% done. What you could do is 2 keyframe animations. With JS you can listen for the first animation ending. You could add the background-image and then the class that will trigger the second part of the animation. It's not pretty but could work.