This is a bit of a long-winded question, but I hope someone can break this down for me. I have 2 questions:
Why a CSS property doesn't do what it should.
Why this particular CSS property works on an unsuspecting element, and why it doesn't work on the CSS :hover selector.
Created a flipcard animation. Got some graphics/trailing lines issues with transitions (in Chrome).
Doing some Googling, I found out that apparently, using -webkit-transform: translate3d(0,0,0); is supposed to fix the issue by using hardware acceleration.
However, I couldn't figure out where to place this CSS property. I tried placing it on the .flipcard-container, .flipcard, on the actual transition (.flipcard-container: hover .flipcard).
None of these removed the trailing lines caused by the animation.
Question 1: Where can I use the -webkit-transform: translate3d(0,0,0); properly in order to take advantage of the hardware acceleration, and why does/doesn't it work there?
But, after doing even more Googling and copying someone else's code, I found adding perspective: 600pxto the .flipcard-container somehow fixed the issue. And on top of that, it even makes my animation look really nice.
It shouldn't bother me so much, but it does that I cannot figure out why this worked.
According to the MDN docs:
The perspective CSS property determines the distance between the z=0
plane and the user in order to give a 3D-positioned element some
perspective.
Question 2: Why does this work in my transition so well? Shouldn't I have to place perspective in .flipcard-container: hover .flipcard instead of the .flip-container?
Of course, when placing it in the css :hover selector, the entire transition stops working. Does the perspective property also use hardware acceleration?
Here is the code, and thank you in advance.
.flipcard-container {
height: 400px;
width: 300px;
/* uncommenting the below property will fix the issue */
/* -webkit-perspective: 600; */
}
.flipcard-container:hover .flipcard {
transform: rotateY(180deg) scale(1.5);
}
.flipcard, .front, .back {
width: 100%;
height: 100%;
}
.flipcard {
transform-style: preserve-3d;
transition: all .8s ease-in-out;
}
.front {
background: #6093e5;
position: relative;
backface-visibility: hidden;
}
.back {
background: #e56060;
position: absolute;
backface-visibility: hidden;
top: 0;
transform: rotateY(180deg);
}
<div class="flipcard-container">
<div class="flipcard">
<div class="front"></div>
<div class="back"></div>
</div>
</div>
Question 1
You are overriding the transform: tags with the hardware acceleration. This causes that the animation doesn't work if you put it in.
You can use this, to archive better (more stable fps)
.flipcard-container:hover .flipcard {
transform: rotateY(180deg) scale(1.5);
will-change: -webkit-transition;
will-change: transition;
}
it uses the new will-change property.
More details
The will-change CSS property provides a way for authors to hint
browsers about the kind of changes to be expected on an element, so
that the browser can setup appropriate optimizations ahead of time
before the element is actually changed. These kind of optimizations
can increase the responsiveness of a page by doing potentially
expensive work ahead of time before they are actually required.
Question 2
If you look at e.g. this:
https://codepen.io/jfcorugedo/pen/bBPWaO?q=3d+turn&limit=all&type=type-pens
you see that it also uses the perspective tag. It is used that you can see the rotation of the box (like in your case).
If you remove it, it looks like your code. It works only on the container because the object you want to flip is wrapped in it.
If you have more questions just ask :)
When i put transform: scale(1.1); on hover on some element the image became blurry. How to fix this bug?
Example
Try this, it's work fine for me!
img {
-webkit-backface-visibility: hidden;
-ms-transform: translateZ(0); /* IE 9 */
-webkit-transform: translateZ(0); /* Chrome, Safari, Opera */
transform: translateZ(0);
}
TL;DR
transform: scale is actually scaling the original image, and because you are leaving it to the browser's render engine to figure out what should go there you got a blurry image. try
img {
transform: scale(.9)
}
img:hover {
transform: scale(1)
}
Aaron Sibler answered the question for me.
I just experienced this riddle. In your example, you’ll
need to transform img DOWN something like “transform: scale(0.7)” and
then scale UP to the images native dimensions on hover like
“transform: scale(1.0)”
The scale value is relative to the original image’s dimensions – not
their current dimensions on screen so a scale of 1 always equals the
original image’s dimensions.
I’ve used this here;
http://meetaaronsilber.com/experiments/css3imgpop/index.html
I had this problem with SVG scaling and blurry images. I scaled up a background image to 4.5 and the image rendered very blurry while scaling up.
I read that you can scale down first transform: scale(0.7) and then scale up to transform: scale(1.0). In my case this meant a huge rebuild of my animation. I had a very complex animation with multiple scales and transforms etc.
I just left all as is and added a pseudo scale width. The browser then seems to re-render every frame, but since the width does not actually change you still can use
transform: scale(x.x) for scaling and you get a very sharp image.
Maybe someone can confirm this. Here is my code. In my case the image was 86px wide and it zoomed up to 4.5 times the initial value.
<div class="overall-scale">
<div class="image-scale"></div>
</div>
#keyframes overall-scale {
0% {
transform: scale(1);
}
100% {
transform: scale(4.5);
}
}
#keyframes image-scale {
0% {
width: 86px;
}
100% {
width: 86px;
}
}
Hope this helps and my explanation makes sense.
Please comment if this does not work for you.
I' ve read all the comments, and tryied all solutions people suggested. But nothing was really good except rotate(360deg). Everything, except this one made stuttering on images, or they became too blurry initially. But rotating is looking strange if you don't hide it. So I decided to rotate for 0.0000001deg and it worked! Image is blurry only during the transition, but at the end and at the start of it it is sharp. May be I just had too small pictures.
So, my current solution is adding this part to CSS (and nothing else):
img {
transform: rotate(0.00000000001deg);
}
I am working on making a fixed navigation web site. I have a navigation bar fixed at the top of the screen using absolute positioning. The CSS looks something like this:
.navbar {
background-color: #1f1f1f
top: 0px;
position: fixed;
width: 100%;
}
And here is my HTML:
<header class="navbar">...</header>
This should be pretty simple, but for some reason I am seeing the background of the navigation flicker between #1f1f1f and what I would describe as simply transparent.
I can get the scroll position to a point where the background color is transparent. At that point, when I inspect the element in the WebKit inspector, the expected styling is there. A background-color of #1f1f1f and basically everything else I mentioned above.
I can toggle the background-color property on and off in the inspector, and that will, more often than not, make the background come back to normal.
Finally, this only seems to be an issue with WebKit based browsers. I can reproduce the issue in Chrome and Opera, but not in Firefox or Internet Explorer. I also don't seem to be able to reproduce this in Safari, at least not in version 7.0 (9537.71) I am also using the Startup Design Framework and the website does feature a video in the background underneath the content <div>, similar to that demo page. Could this be causing some sort of rendering glitch?
More Info:
I removed the background video <div> from the page, and this appeared to solve the issue entirely. This isn't really an ideal solution, though. Are there any known issues with background videos?
You should try a couple different things. First try stacking the item with z-index:
z-index: 1000000; /* max: 2147483647 */
Next, you can try and force hardware acceleration on your menu. The browser will create new rendering layers for your menu which may prevent the flicker.
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
And finally, if your element is larger than the screen (even by one pixel in any direction), it can cause flickering during scrolling on some devices. Try adding the following:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;
I recently had the same problem with webkit browsers. All you have to do is add this in your .navbar class in css and see if it works:
backface-visibility:visible;
-webkit-backface-visibility: visible;
-webkit-transform: translateZ(0);
try this:
.navbar {
position: fixed;
right: 0;
left: 0;
z-index: 1030;
margin-bottom: 0;
background-color: #1f1f1f
}
.navbar {
left: 0;
position: fixed;
top: 0;
width: 100%;
background-color: #1f1f1f;
z-index: 1030;
}
Have you tried to use Firebug to debug the issue? I would suggest you to use Firebug to debug this issue.
I have an unordered list with a few list items that act as flip cards using CSS 3D transforms. I want them to flip via clicks on links/anchor elements inside of the list items, and these links fill up the entire list item as well.
The list items look and act fine in their default non-flipped state, but once I click one and it flips, the clickable link area on the back side of it is only on the top half of the list item. When I inspect in Chrome, the link area is still filling up the entire height of the list item, so I'm not sure what is going on.
Fiddle: http://jsfiddle.net/chucknelson/B8aaR/
Below is a summary of the transform properties I'm using on various elements (see fiddle for detail):
-webkit-transition: 0.6s;
-webkit-transform-style: preserve-3d;
-webkit-transform-origin: 100% 1.5em;
-webkit-transform: rotateX(180deg);
Note that I'm testing in Chrome 28 on Windows, and I'm just using -webkit prefix items in the fiddle. I also apologize for any messy CSS or markup, this problem had me iterating a bit. Any help in understanding what is happening is greatly appreciated!
Update 8/11/2013:
I was having this same problem with a 2D transforms on list items (just flipping the item, no front/back). Adding #thirtydot's translateZ(1px) transform in the CSS for the <a> tag fixed that one too. So it looks like the issue is related to the z-axis...but only on part of the link. Maybe this is a bug in browsers?
This problem may be the result of a webkit rendering bug, but the solution was to tranlsate the link's Z-axis by 1px - this seemed to push the link layer up and have it fully clickable.
To fix the 3D transform (via the fiddle from #thirtydot http://jsfiddle.net/thirtydot/YCGjZ/7/), some javascript was required:
setTimeout(function() {
flipTarget.find('div.back a').css('-webkit-transform', 'translateZ(1px)');
flipTarget.find('div.back a').css('transform', 'translateZ(1px)');
}, 600);
When using a 2D transform, adding translateZ in the CSS class worked:
.flipped {
border-top: 1px solid black;
background-color: #555;
-webkit-transform: rotateX(180deg);
}
.flipped a {
color: #eee;
text-decoration: line-through;
-webkit-transform: scaleY(-1) translateZ(1px); /* the fix */
}
Seems like there has been a recent update to Google Chrome that causes blurry text after doing a transform: scale(). Specifically I'm doing this:
#-webkit-keyframes bounceIn {
0% {
opacity: 0;
-webkit-transform: scale(.3);
}
50% {
opacity: 1;
-webkit-transform: scale(1.05);
}
70% {
-webkit-transform: scale(.9);
}
100% {
-webkit-transform: scale(1);
}
}
If you visit http://rourkery.com in Chrome, you should see the problem on the main text area. It didn't used to do this and it doesn't seem to effect other webkit browsers (like Safari). There were some other posts about people experiencing a similar issue with 3d transforms, but can't find anything about 2d transforms like this.
Any ideas would be appreciated, thanks!
I have had this problem a number of times and there seems to be 2 ways of fixing it (shown below). You can use either of these properties to fix the rendering, or both at the same time.
Backface visibility hidden fixes the problem as it simplifies the animation to just the front of the object, whereas the default state is the front and the back.
backface-visibility: hidden;
TranslateZ also works as it is a hack to add hardware acceleration to the animation.
transform: translateZ(0);
Both of these properties fix the problem that you are having but some people also like to add
-webkit-font-smoothing: subpixel-antialiased;
to their animated object. I find that it can change the rendering of a web font but feel free to experiment with that method too.
After trying everything else here with no luck, what finally fixed this issue for me was removing the will-change: transform; property. For some reason it caused horribly blurry looking scaling in Chrome, but not Firefox.
To improve the blurriness, esp. on Chrome, try doing this:
transform: perspective(1px) translateZ(0);
backface-visibility: hidden;
UPDATE: Perspective adds distance between the user and the z-plane, which technically scales the object, making the blurriness seem 'permanent'. The perspective(1px) above is like duck-tape because we're matching the blurriness we're trying to solve. You might have better luck with the css below:
transform: translateZ(0);
backface-visibility: hidden;
I found that adjusting the scale ratio helped slightly.
Using scale(1.048) over (1.05) seemed to generate a better approximation to a whole-pixel font size, reducing the sub-pixel blurring.
I also used translateZ(0) which seems to adjust Chrome's final rounding step in the transform animation. This is a plus for my onhover usage because it increases speed and reduces visual noise. For an onclick function however, I wouldn't use it because, the transformed font doesn't appear to be as crispy.
Instead of
transform: scale(1.5);
using
zoom : 150%;
fixes the text blurring problem in Chrome.
This must be a bug with Chrome (Version 56.0.2924.87), but the below fixes the bluriness for me when changing css properties in the console('.0'). I'll report it.
filter: blur(.0px)
Sunderls lead me to the answer. Except filter: scale does not exist, but filter: blur does.
Apply the next declarations to the elements that appear blurred (in my case they were inside a transformed element):
backface-visibility: hidden;
-webkit-filter: blur(0);
It almost worked perfectly. "Almost" because i'm using a transition and while in transition, elements don't look perfect, but once the transition is done, they do.
I found out, that the problem occures on relative transforms in any way. translateX(50%), scale(1.1) or what ever. providing absolute values always works (does not produce blurry text(ures)).
None of the solutions mentions here worked, and I think there is not solution, yet (using Chrome 62.0.3202.94 while I am writing this).
In my case transform: translateY(-50%) translateX(-50%) causes the blur (I want to center a dialog).
To reach a bit more "absolute" values, I had to set decimal values to transform: translateY(-50.09%) translateX(-50.09%).
NOTE
I am quite sure, that this values vary on different screen sizes. I just wanted to share my experiences, in case it helps someone.
In my case following code caused blurry font:
-webkit-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
and just adding zoom property fixed it for me. Play around with zoom, following worked for me:
zoom: 97%;
I have found a much better and clean solution:
.element{
transform:scale(0.5)
transform-origin: 100% 0;
}
or
.element{
transform:scale(0.5)
transform-origin: 0% 0;
}
Thanks to this post:
Preventing blurry rendering with transform: scale
I have this same problem. I fixed this using:
.element {
display: table
}
Another fix to try i just found for blurry transforms (translate3d, scaleX) on Chrome is to set the element as
"display: inline-table;".
It seems to force pixel rounding in some case (on the X axis).
I read subpixel positioning under Chrome was intended and devs won't fix it.
Try using zoom: 101%; for complex designs when you can't use a combination of zoom + scale.
2019 UpdateThe Chrome display bug is still unfixed and though no fault of the patrons, none of the suggestions offered in the entirety of this website help to resolve the issue. I can concur that I have tried every single one of them in vain: only 1 comes close and that's the css rule: filter:blur(0); which eliminates the shifting of a container by 1px but does not resolve the blurred display bug of the container itself and any content it may have.
Here's the reality: there literally is no fix to this problem so here is a work around for fluid websites
CASE
I'm currently developing a fluid website and have 3 divs, all centered with hover effects and sharing percentage values in both the width and position. The Chrome bug occurs on the center container which is set to left:50%; and transform:translateX(-50%); a common setting.
EXAMPLE: First the HTML...
<div id="box1" class="box">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry"s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</div>
<div id="box2" class="box">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry"s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</div>
<div id="box3" class="box">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry"s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</div>
Here's the CSS where the Chrome bug occurs...
*{margin:0; padding:0; border:0; outline:0; box-sizing:border-box; background:#505050;}
.box {position:absolute; border:1px solid #fff; border-radius:10px; width:26%; background:#8e1515; padding:25px; top:20px; font-size:12pt; color:#fff; overflow:hidden; text-align:center; transition:0.5s ease-in-out;}
.box:hover {background:#191616;}
.box:active {background:#191616;}
.box:focus {background:#191616;}
#box1 {left:5%;}
#box2 {left:50%; transform:translateX(-50%);} /* Bugged */
#box3 {right:5%;}
Here's the fixed css...
*{margin:0; padding:0; border:0; outline:0; box-sizing:border-box; background:#505050;}
.box {position:absolute; border:1px solid #fff; border-radius:10px; width:26%; background:#8e1515; padding:25px; top:20px; font-size:12pt; color:#fff; overflow:hidden; text-align:center; transition:0.5s ease-in-out;}
.box:hover {background:#191616;}
.box:active {background:#191616;}
.box:focus {background:#191616;}
#box1 {left:5%;}
#box2 {left:37%;} /* Fixed */
#box3 {right:5%;}
Bugged fiddle: https://jsfiddle.net/m9bgrunx/2/
Fixed fiddle: https://jsfiddle.net/uoc6e2dm/2/
As you can see a small amount of tweaking to the CSS should reduce or eliminate the requirement to use transform for positioning. This could also apply to fixed width websites as well as fluid.
It's important to add that this issue arises if the element which is being translated has a height with an odd number of pixels. So, if you have control over the height of the element, setting it to an even number will make the content appear crisp
None of above worked for me.
I had this animation for popups:
#keyframes pulse {
from {
transform: scale3d(1, 1, 1);
}
50% {
transform: scale3d(1.05, 1.05, 1.05);
}
to {
transform: scale3d(1, 1, 1);
}
}
In my case blurry effect was gone after applying this rule:
-webkit-perspective: 1000; even though it is marked as unused in Chrome inspector.
None of the above worked for me.
It worked when I added perspective
ie from
transform : translate3d(-10px,-20px,0) scale3d(0.7,0.7, 1)
i changed to
transform : perspective(1px) translate3d(-10px,-20px,0) scale3d(0.7,0.7, 1)
I used a combination of all answers and this is what worked for me in the end:
.modal .modal--transition {
display: inline-table;
transform: perspective(1px) scale(1) translateZ(0);
backface-visibility: hidden;
-webkit-font-smoothing: subpixel-antialiased;
}
My solution was:
display: initial;
Then it was crispy sharp
I was facing the blurry text issue on Chrome but not on Firefox when I used transform: translate(-50%,-50%).
Well, I really tried a lot of workarounds like:
transform: perspective(1px);
filter: blur(0);
transform: translateZ(0);
backface-visibility: hidden;
None of these worked to me.
Finally, I made the height and width of the element even. It resolved the issue for me!!!
Note: It might depend from use case to use case. But surely worth a try!
I have tried a lot of examples from these answers unfortunately nothing help for
Chrome Version 81.0.4044.138
I have added to transforming element instead
transform-origin: 50% 50%;
this one
transform-origin: 51% 51%;
it helps for me
This is what worked for me:
body { perspective: 1px; }
I fixed my case by adding:
transform: perspective(-1px)
I removed this from my code - transform-style: preserve-3d;
and added this- transform: perspective(1px) translateZ(0);
the blur went away!
FOR CHORME:
I´ve tried all suggestions here. But diden't work.
My college found a great solution, that works better:
You should NOT scale past 1.0
And include translateZ(0) in the hover but NOT in the none-hover/initial position.
Example:
a {
transition: all 500ms cubic-bezier(0.165, 0.840, 0.440, 1.000);
transform: scale(0.8, 0.8);
}
a:hover {
transform: translateZ(0)scale(1.0, 1.0);
}
In Chrome 74.0.3729.169, current as of 5-25-19, there doesn't seem to be any fix for blurring occurring at certain browser zoom levels caused by the transform. Even a simple TransformY(50px) will blur the element. This doesn't occur in current versions of Firefox, Edge or Safari, and it doesn't seem to occur at all zoom levels.
I have a div that has a small perspective shift on it to give a subtle 3D effect. The text in the div was blurring and I tried all the suggestions here to no avail.
Oddly, I found that setting 'filter: inherit;' on the text elements vastly improved the clarity. Though I can't understand why.
Here's my code in case it helps:
Html:
<div id="NavContainer">
<div id="Nav">
<label>Title</label>
<nav>
home
link1
link2
</nav>
</div>
</div>
Css:
#NavContainer {
position: absolute;
z-index: 1;
top: 0;
left: 20px;
right: 20px;
perspective: 80vw;
perspective-origin: top center;
}
#Nav {
text-align: right;
transform: rotateX(-5deg);
}
#Nav > nav > a,
#Nav > label {
display: inline-block;
filter: inherit;
}
#Nav > label {
float: left;
font-weight: bold;
}
For me the problem was that my elements were using transformStyle: preserve-3d. I realized that this wasn't actually needed for the app and removing it fixed the blurriness.
It will be difficult to solve with only css.
So I solved it with jquery.
This is my CSS.
.trY {
top: 50%;
transform: translateY(-50%);
}
.trX {
left: 50%;
transform: translateX(-50%);
}
.trXY {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
and this is my jquery.
function tr_init() {
$(".trY, .trX, .trXY").each(function () {
if ($(this).outerWidth() % 2 != 0) {
var fixed_width = Math.ceil($(this).outerWidth() / 2) * 2;
$(this).css("width", fixed_width);
}
if ($(this).outerHeight() % 2 != 0) {
var fixed_height = Math.ceil($(this).outerHeight() / 2) * 2;
$(this).css("height", fixed_height);
}
})}
Just to add to the fix craze, putting {border:1px solid #???} around the badly looking object fixes the issue for me.
In case you have a stable background colour, consider this too.
This is so dumb noone thought about mentioning I guess, eh eh.