I'm trying to animate an image on hover by flipping it upside-down (180 deg) along the x-axis.
Just like here
Except I can't get it to work for some reason.
img {
transition:all 2s ease-in-out;
perspective: 800px;
perspective-origin: 50% 100px;
}
img:hover {
transform:rotateX(180deg);
}
According to this page, Chrome still needs the -webkit prefix.
You're missing the browser prefix.
img {
-webkit-transition:all 2s ease-in-out;
-webkit-perspective: 800px;
-webkit-perspective-origin: 50% 100px;
}
img:hover {
-webkit-transform:rotateX(180deg);
}
This also means that you'll need to add in the other browser prefixes for their respective browsers. If you would rather not mess around with browser prefixes, you can use a plugin called prefixfree.js by Lea Verou to take care of it all for you.
Related
In my application users can scale down a specific part. I'm using tranform: scale() to achieve this.
I was able to achieve much less blurred images by using
-webkit-backface-visibility: hidden;
-ms-transform: translateZ(0);
-webkit-transform: translateZ(0);
transform: translateZ(0);
on my images.
Sadly this doesn't work for divs with background-image. Those images are still very blury.
Is there a way to fix this? (Please don't tell me to not use scale)
using transforms can cause blurry images when the transition happens or when it rescales, there's a workaround for this...the reason the blur looks like Webkit renders elements as images during animated transforms, so if scaling up an element it appears to blur until the transition has finished.
A solution might be to size the element as big as you will ever need it in the first place, and use a transformation to scale it down for initial display - e.g. if doubling the size on hover, instead of doing "scale(2,2)", start with "size:200%, scale:(.5,.5)" and on hover switch to "scale(1,1)"...
Here's a workaround:
.normal {
width: 200px;
height: 200px;
margin: 1em auto;
transition: all 1s linear;
}
.normal:hover {
transform: scale(2, 2);
}
.prescaled {
width: 400px;
height: 400px;
margin: 1em auto;
transition: all 1s linear;
transform: scale(.5, .5);
// fix positioning due to scale
position: relative;
top: -100px;
}
.prescaled:hover {
transform: scale(1, 1);
}
This one's mainly an idea about how you can implement it in your way...Let me know if it works...
Can I animate width from 0px to initial? Or it has to be absolute value?
span {
background: red;
animation: scroolDown 1s linear;
display: inline-block;
}
#keyframes scroolDown {
from {
width: 0px;
}
to {
width: initial;
//width: 130px;//works
}
}
<span>asdfdsafsafdsafdsaf</span>
Why does this happen?
When you set width to initial, you're really setting the width to auto (which is the initial value of the width property).
This issue dates as far back as 2007, when this bug was reported on WebKit. You can follow the conversation on that report and see:
The CSS WG has resolved that transitions don't run to/from auto values.
This is the behavior for all of the major browsers, so when trying to animate width to auto, we're out of luck and we have to go with an existing workaround.
The Workarounds
There's a few workarounds for animating to auto, but animating max-width is by far the most popular as it was already referenced by the two answers before this.
Rather than listing and explaining the workarounds in this post, I suggest you see this awesome article on the workarounds for this problem.
Summarizing the article, the workarounds are:
Animating max-height with explicit values
Animate transform with scaleX
Use JavaScript to achieve the desired effect
Use Flexbox
If you really need the functionality of animating to auto, your best bet is animating with JavaScript.
You can animate the max-width rather that the width; if you set the end width to something you know is at least as great as the desired end width, it will stop growing automatically at its natural width!
In this example, I set the end width at 20em, about twice the natural size, and I also increased the animation time, so that the time is about the same as the originally intended one.
span {
background: red;
animation: scroolDown 2s linear; /* about twice the expected time */
display: inline-block;
}
#keyframes scroolDown {
from {
max-width: 0px;
}
to {
max-width: 20em; /* about twice the expected size */
}
}
<span>asdfdsafsafdsafdsaf</span>
The concept for this kind of solution comes from How can I transition height: 0; to height: auto; using CSS?, so maybe I should have closed as a duplicate instead. Sorry.
Is this what you're trying to achieve?
The text gets unrevealed as the animation occurs with the background instead of text appearing and the background animating with a delay.
.inner {
display: inline-block;
height:20px;
background: #c3c;
overflow: hidden;
-webkit-transition: width 1s ease-in-out;
-moz-transition: width 1s ease-in-out;
-o-transition: width 1s ease-in-out;
transition: width 1s ease-in-out;
animation: mymove 3s linear;
}
#keyframes mymove {
0% {
max-width: 0px;
}
100% {
max-width: 100%;
}
}
<span class="inner">
This is a test text for testing the text appearance for this test.
</span>
Once I start animating, on Chrome I get a ripple effect. My circle transform scales up. On Firefox, that exact same animation is ignored for some reason.
$("#animate").click(function() {
$("#square").toggleClass("animate");
$("#fab").toggleClass("ripple");
});
#keyframes ripple {
from {
transform: scale(0)
}
to {
transform: scale(20)
}
}
#square {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid red;
transition: background 0.1s linear 0.6s, transform 1s;
transform: rotate(0deg);
}
#fab {
position: absolute;
width: 56px;
height: 56px;
border-radius: 50%;
background: #4FB5AB;
top: 122px;
right: 0;
transform: scale(1);
transition: transform 1s;
}
.ripple {
animation: ripple 1s 0.5s;
transform: scale(20) !important;
/*Duration - delay */
transition: transform 0s 1s !important;
}
.animate {
transform: rotate(90deg) !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="square">
<div id="fab"></div>
</div>
<br />
<button id="animate">animate</button>
CodePen Demo
Before I start explaining the problem with your code, here is a word of caution - Do not use transitions and animations together. They generally end up causing problems like the one faced here.
When an animation is specified on an element, it will take complete control over the properties that are being animated unless there is a rule with !important setting. If !important setting is used then that rule takes precedence over the animation. (but unfortunately Chrome and Firefox seem to be handling this case differently).
As per W3C Spec:
CSS Animations affect computed property values. During the execution of an animation, the computed value for a property is controlled by the animation. This overrides the value specified in the normal styling system. Animations override all normal rules, but are overriden by !important rules.
emphasis is mine
In your code, there were two problems and they are as follows:
Within .ripple selector, you were specifying the transition-duration as 0s, which means, there is no transition at all and that the change of transform is an instant one. As explained in the W3C Spec, Firefox seems to be (correctly) giving the control to the rule with !important setting (that is, the transform and transition within .ripple selector) and so it transitions the state change immediately after the specified 1s delay+. Chrome lets animation take control and thus produces the effect you are looking for.
Firefox seems to animate the element quicker than Chrome does and so while a duration of 1s is enough for the animation in Chrome, FF needs it to be 2s to be slower and show the effect.
+ - You can further verify this by removing the !important settings on the rules. Once !important is removed, the animation would take control.
$("#animate").click(function() {
$("#square").toggleClass("animate");
$("#fab").toggleClass("ripple");
});
#keyframes ripple {
from {
transform: scale(0)
}
to {
transform: scale(20)
}
}
#square {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid red;
transition: background 0.1s linear 0.6s, transform 1s;
transform: rotate(0deg);
}
#fab {
position: absolute;
width: 56px;
height: 56px;
border-radius: 50%;
background: #4FB5AB;
top: 122px;
right: 0;
transform: scale(1);
transition: transform 1s;
}
#fab.ripple {
animation: ripple 2s 1s;
transform: scale(20);
/*Duration - delay */
transition: transform 1s 1s;
}
#square.animate {
transform: rotate(90deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="square">
<div id="fab"></div>
</div>
<br />
<button id="animate">animate</button>
Finally, please do not use !important unless it is mandatory. Instead just make the selector more specific. In the snippet, I have made it more specific by using the #id.class format.
I have a problem in latest Firefox browser version 34 (system: Windows 7, screen width: 1600px). I made effect with zooming images (in some container) after hover on it. I am using transform: scale(1.1) with transition: transform 0.3s ease-in-out. But when I hover on image, and after image zoom in.. it make some strange 1px-shifting. Some rendering browser bug, but I hope that existing some fix for it.
Most important CSS definition and part of HTML code:
figure {
display: block;
overflow: hidden;
position: relative;
backface-visibility: hidden;
}
figure img {
width: 100%;
transform: scale(1);
transition: transform 0.3s ease-in-out;
}
figure:hover img {
transform: scale(1.1);
}
<figure>
<img class="img-responsive" src="http://lorempixel.com/600/400/fashion/7">
</figure>
Sample with bug is online here: http://templates.silversite.pl/test/jumpingimg/
I saw also that somebody can fix it, but I do not know how, e.g. box "Our recent work" on http://demo.qodeinteractive.com/bridge/
I had a similar problem on my project. All images were position: absolute; and the transform look like that:
figure img{
transform: translate( -50%, 50%) scale(1);
position: absolute;
top: 50%;
left: 50%;
}
figure img:hover{
transform: translate( -50%, 50%) scale(1.1);
}
I replace every scale with scale3d and that solved my problem.
The final styles look like that:
figure img{
transform: translate( -50%, 50%) scale3d(1, 1, 1);
position: absolute;
top: 50%;
left: 50%;
}
figure img:hover{
transform: translate( -50%, 50%) scale3d(1.1, 1.1, 1);
}
Hope that's will fix your problem
On the link that you provided, http://demo.qodeinteractive.com/bridge/ , if you actually go here: http://demo.qodeinteractive.com/bridge/portfolio/gallery-style-condensed/two-columns-grid/ , you can see that, once looking at dev tools, that they apply a margin of "1px" on left/right side
.projects_holder.hover_text.no_space article .image img {
margin: 0 1px;
}
If you disable that style, you'll see the image move as you're describing when hovering on the image.
Therefore, your CSS for the image should be:
figure img {
width: 100%;
transform: scale(1);
transition: transform 0.3s ease-in-out;
display: block; /* (or inline-block) */
margin: 0 1px;
}
I have just run into this same problem now. The solutions here didn't fix the issue, so I'm posting what I did to get this to work.
Like OP I had a container with oveflow hidden and was the same size as the image inside it. The image would scale on hover to create a 'zoom' effect - but when initially starting and ending the transition, the image was "jumping"/growing a tiny bit on the bottom and right-hand side. This made it jumpy and not smooth.
I had calculated the dimensions of my components based off of percentages, which caused them to be non-integers (Chrome). I have a feeling Scale & Scale3d round the pixel values when scaling, which caused this jump. I gave a parent container display:table, which caused all children to have their width/heights be rounded to be an integer value. This fixed the issue for me, and the images now scale smoothly!
7,5 years later it's still an issue and the now solution is will-change css property. Only IE won't get this, but others seems to be doing fine - no more px jumping (edit: on non retina screens).
figure {
display: block;
overflow: hidden;
position: relative;
backface-visibility: hidden;
}
figure img {
width: 100%;
transform: scale(1);
transition: transform 0.3s ease-in-out;
}
figure:hover img {
transform: scale(1.1);
will-change: transform;
}
I just run over the same issue and for me it looks like that the browser corrects the decimal pixel after the scaling is done. Or some how the height and the width doesn't get scaled equals and that gets corrected in the end.
So I think the solution is to use an image with a 1 x 1 ration factor.
So for me the code of the question works fine when I use a the lorempixel with a width and height of 400px.
Let me know if that solves the issue?!
figure {
display: block;
overflow: hidden;
position: relative;
backface-visibility: hidden;
}
figure img {
width: 100%;
transform: scale(1);
transition: transform 0.3s ease-in-out;
}
figure:hover img {
transform: scale(1.1);
}
<figure>
<img class="img-responsive" src="http://lorempixel.com/400/400/fashion/7">
</figure>
What is a syntactically clean solution to run a chain of individual CSS3 transitions on a single element, one by one? An example:
set left to 10px and opacity to 1 through 200ms
set left to 30px through 500ms
set left to 50px and opacity to 0 through 200ms
Can this be done without JavaScript? If not, how to code it cleanly with JavaScript?
I believe you want a CSS3 animation where you define the CSS styles at different points in the animation and the browser does the tweening for you. Here's one description of it: http://css3.bradshawenterprises.com/animations/.
You will have to check on browser support for your targeted browsers.
Here's a demo that works in Chrome. The animation is pure CSS3, I only use Javascript to initiate and reset the animation:
http://jsfiddle.net/jfriend00/fhemr/
The CSS could be modified to make it work in Firefox 5+ also.
#box {
height: 100px;
width: 100px;
background-color: #777;
position: absolute;
left: 5px;
top: 5px;
opacity: 0;
}
#-webkit-keyframes demo {
0% {
left: 10px;
}
22% {
opacity: 1;
}
77% {
left: 30px;
}
100% {
left: 50px;
opacity: 0;
}
}
.demo {
-webkit-animation-name: demo;
-webkit-animation-duration: 900ms;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in-out;
}
In pure CSS this can be done with the transition-delay property, with it you can delay the second and third transition.
I personally would like a JS solution better. timeouts or the "transitioned" event can be used to achieve this.
I would also suggest the script.aculo.us (or the beta v2: scripty2), it is especially designed to make programming these kinds of things efficient and easy.