How to fix blurry background-image on transform scale - css

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...

Related

CSS Safari transition with transform and width not working

.items {
position: relative;
display: block;
background-color: red;
height: 300px;
width: 100px;
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
transition: all 1s ease;
-webkit-transition: all 1s ease;
}
.items.animation {
width: 50%;
transform: translate3d(50%, 50%, 0);
-webkit-transform: translate3d(50%, 50%, 0);
}
I use transition to animate transform and width in the same time.
It works well in other browsers but not in safari.
When the animation(transition) finished, get the element value correctly. But 'width' and 'transform' doesnt work by transition (for example 1sec).
Safari doesnt calculate the width value by transition in my opinion. Thats why this transfrom translate 50% calculate with the origin value of width...
I wouldnt like to create one more element as much as possible.
Has anyone idea to figure it?
Example is here:
https://codepen.io/jh-ko/pen/xxdbzga
please test and compare in safari and (chrome/firefox etc.)
This is working as of iOS 15.5 as far as I can tell.

Image shifting/jumping after CSS transition effect with scale transform in Firefox

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>

is there any way to achive growing div animation with transform properties?

I've developed an animation in which a div grows by using the following styles:
.animation-start {
overflow: hidden;
height: 0;
}
.animation-end {
height: 100px;
}
But the problem with this approach is that it is not rendered smoothly on mobile devices. At the moment the only animations rendered smoothly on mobiles are the ones that use transform property. Is there any way to achive growing div animation with solely transform properties (without using height property)?
Yes, you can just add a duration to the element:
$(document).click(function(){
$('div').toggleClass('animation-end');
});
div {
background: #ffc;
transition-duration: 300ms;
}
.animation-start {
overflow: hidden;
height: 0;
}
.animation-end {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="animation-start">asdf</div>
click anywhere
A transition and transform property should be able to handle this for you
transition: all 0.5s ease;
transform: scale(2);
// Or individually target the axis you want to scale
transform: scaleX(2);
transform: scaleY(2);
Scale works as a multiplier but I'm not sure if you need a fixed pixel height

Bug in CSS3 rotateY transition on Safari?

I am showing a modal popup using CSS3 transitions (largely borrowed from Effeckt.css). It works well in all modern browsers except Safari. In Safari, the movement is OK, but the background-color snaps in unevenly.
This is the code, the problem is visible in Safari on OSX: http://jsfiddle.net/eJsZx/4/
A screenshot of the problem before it resolves itself. You can see that half the div is correctly colored white, half is still transparent.
This is the relevant part of the CSS (.effeckt-show and .md-effect-8 are applied when the button is clicked, to show the modal):
.effeckt-modal {
visibility: hidden;
-webkit-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
background: white;
}
.md-effect-8 {
-webkit-perspective: 1300px;
-ms-perspective: 1300px;
-o-perspective: 1300px;
perspective: 1300px;
-webkit-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.md-effect-8 .effeckt-modal {
-webkit-transform: rotateY(-70deg);
-ms-transform: rotateY(-70deg);
-o-transform: rotateY(-70deg);
transform: rotateY(-70deg);
-webkit-transition: all 500ms;
-o-transition: all 500ms;
transition: all 500ms;
opacity: 0;
}
.effeckt-show.md-effect-8 .effeckt-modal {
-webkit-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
-o-transform: rotateY(0deg);
transform: rotateY(0deg);
opacity: 1;
}
As far as I can tell it's a bug, yes, Safari is rendering intersection where it shouldn't.
For some time I thought Safari is doing it right by always rendering intersection of elements, but as far as I understand the specs, only elements in the same 3d rendering context should intersect, and that would be children of elements with a transform-style of preserve-3d.
So far the only workaround I found (only tested on Windows yet where Safari shows the same behaviour) is to translate the underlying elements away on the z-axis. Without perspective being applied it won't actually translate, but Safari/Webkit seems to think it does (which probably is because it mistakenly treats the element as if it were in the same 3d rendering context as the actually transformed dialog) and so the elements do no longer intersect.
.effeckt-overlay {
position: fixed;
width: 100%;
height: 100%;
visibility: hidden;
top: 0;
left: 0;
opacity: 0;
-webkit-transition: 500ms;
-o-transition: 500ms;
transition: 500ms;
z-index: 1000;
background: rgba(0, 0, 0, 0.5);
-webkit-transform: translateZ(-1000px);
}
http://jsfiddle.net/eJsZx/5/
I found this issue when trying to find a solution to a problem I was experiencing in Safari (Mac and iOS), where a y-rotated svg only displayed its right half for no apparent reason.
In my case, the svg was a child of a fixed-position div, and I found that both position: fixed and position: absolute on the parent caused half the svg to disappear.
Neither changing z indexes, perspective, nor translate-z seemed to solve the issue. But randomly, adding a new div around my svg and setting its background-color solved the problem. I hope this helps the next person :)
In my case, adding z-index: 0 to the parent element fixed it as per Thomas's suggestion.
None of the solutions above worked for me. In the end, this is a bug with rotate on Safari that Chrome previously had but fixed. The answer here was what solved it for me - using scale() rather than rotate().
In my case, it worked to put transform: translateZ(0); on the parent container. The object itself is an image.

3D CSS Transform - transform:rotateX(180deg);

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.

Resources