I'm using filter:grayscale(1) on images. The container of the image also have pseudo :after applied with a background color set to mix-blend-mode:screen. Everything seems to work, except on Safari iOS.
Here's the CSS for the images isolated:
.grid-item img {
filter:grayscale(1);
transition:filter 0.25s ease;
}
.grid-item:after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
display:block;
z-index:1;
mix-blend-mode: screen;
transition:opacity 0.25s ease;
pointer-events:none;
}
.grid-item.is-active:hover img {
filter:grayscale(0);
}
You can see the whole site here: http://www.tobiasgerhardsson.com/work/linazedig
And here's a video showing it live: https://streamable.com/a6lxe
The bug is hard to explain, but it seems like it's moving images in between the others, so that some images gets duplicated and replaced with the same image, or fragments of other images are shown in eachother. It disappears on scroll, but sometimes the bug appears again randomly.
I've tried to remove the mix-blend-mode as I thought that was causing the bug, but the bug only disappears when I remove the filter:grayscale(1) from the images. I'm also using a JS plugin for doing a flexbox masonry grid layout on desktop. But I've also removed the script temporarily, and the bug remains.
So all in all, this seems to be a problem with the filter:grayscale, but I'm not sure if it's caused by a combination of other CSS properties or not. Has anyone experienced this before and know what could be causing it? Or is it just a bug not possible to solve?
Reading this thread, I found that applying the following properties to the element with the filter makes the glitch go away:
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
It's doing my eyes in!
looks fine in IE and Firefox
Chrome(Above)
Running version 39 of chrome,
only appears blurry in a modal box, does not make any difference if I change the font family.
This is the CSS (for label "Start") the browser renders the following
box-sizing: border-box;
color: rgb(85, 85, 85);
cursor: default;
display: block;
float: left;
font-family: sans-serif;
font-size: 12px;
font-weight: 600;
height: 24px;
line-height: 17.142858505249px;
margin-bottom: 0px;
margin-top: 0px;
min-height: 1px;
padding-left: 15px;
padding-right: 15px;
padding-top: 7px;
position: relative;
text-align: right;
visibility: visible;
width: 89.65625px;
Is it the browser or CSS?
--UPDATE---
Ok looks like its this CSS
.md-modal {
position: fixed;
top: 50%;
left: 50%;
width: 50%;
max-width: 630px;
min-width: 320px;
height: auto !important;
z-index: 2000;
visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transform: translateX(-50%) translateY(-50%); <--- This line
-moz-transform: translateX(-50%) translateY(-50%);
-ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
However if I take it out my modal no longer centres?
I fixed this issue by subtracting 0.5px from the value of the Y-axis. So instead of doing:
transform: translateX(-50%) translateY(-50%);
I did this:
transform: translateX(-50%) translateY(calc(-50% - .5px));
This solved it for me and I find this a cleaner solution then fiddling around with the percentage or using Javascript.
I experienced the same issue on chrome after applying translate transform to one of my elements. It seems to be a bug on chrome. The only thing that worked for me was this:
#the_element_that_you_applied_translate_to {
-webkit-filter: blur(0.000001px);
}
An Other solution can be turning smooth font rendering on:
#the_element_that_you_applied_translate_to {
-webkit-font-smoothing: antialiased;
}
This fiddle tests out a few different solutions from:
CSS transition effect makes image blurry / moves image 1px, in Chrome?
WebKit: Blurry text with css scale + translate3d
http://www.useragentman.com/blog/2014/05/04/fixing-typography-inside-of-2-d-css-transforms/
Test Output
Fix 0
-webkit-transform: translateZ(0);
transform: translateZ(0);
Fix 3
-webkit-transform: translate3d(0,0,0) !important;
transform: translate3d(0,0,0) !important;
The only correct way to solve this:
This problem arises from the fact of using % values to align the divs using css transforms. This results in decimals subpixel values, which your screen cannot render correctly. The solution is to normalize the resulting transformation matrix.
Might work better for fixed divs that don´t do transforming animation. But if you do animate you could use a after end callback to this function to correct the final state.
So:
matrix (1,0,0,1,-375,-451.5) would become matrix (1,0,0,1,-375,-451)
I call this method before the .show() of jquery... Or maybe just once in the application ( depends on your case) , you might need to also call this on the resize event etc..
function roundCssTransformMatrix(element){
var el = document.getElementById(element);
el.style.transform=""; //resets the redifined matrix to allow recalculation, the original style should be defined in the class not inline.
var mx = window.getComputedStyle(el, null); //gets the current computed style
mx = mx.getPropertyValue("-webkit-transform") ||
mx.getPropertyValue("-moz-transform") ||
mx.getPropertyValue("-ms-transform") ||
mx.getPropertyValue("-o-transform") ||
mx.getPropertyValue("transform") || false;
var values = mx.replace(/ |\(|\)|matrix/g,"").split(",");
for(var v in values) { values[v]=v>4?Math.ceil(values[v]):values[v]; }
$("#"+element).css({transform:"matrix("+values.join()+")"});
}
and call it
roundCssTransformMatrix("MyElementDivId");
$("#MyElementDivId").show();
Beautiful isn't it?
If you need to update on resize you could do it with:
$( window ).resize(function() {
roundCssTransformMatrix("MyElementDivId");
});
For this to work, all the parent must "be aligned / normalized"
because if you by instance have the body with x=10.1px left, and the
child is 10px .. the issue wont disapear because of the parent having residual decimals on their matrix
So you must apply this function to the each element that is a parent and
uses transform.
You can see this live script here: https://jsbin.com/fobana/edit?html,css,js,output
Thanks for the CSS example. It seems translateX(50%) and translateY(50%) are calculating a pixel value with a decimal place (eg, 0.5px) which causes subpixel rendering.
There are many fixes for this but if you want to retain the quality of the text, your best solution right now is to use -webkit-font-smoothing: subpixel-antialiased; on .md-modal to force the render state for webkit browsers like Chrome and Safari.
I ended up fixing this by removing these lines:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
It took me a while to find a solution that I wouldn't bother using, so I'll post it here.
The problem for me was that the child div had width and height properties with a combination that caused the problem.
As I changed the height for another value, it just worked!
This probably has to do with the other answers, but I didn't want to use any JS or change the transform property to fix it.
Here is a live example: JSFIDDLE
If you want to center something, better use flexbox. It will help you position without having blurred text.
Add this to parent div of that element you want to center:
display: flex;
justify-content: center;
align-items: center;
Hope this helps.
Seems Chrome 78 still has this bug https://bugs.chromium.org/p/chromium/issues/detail?id=521364.
Building upon previous answers, I found the CSS below gave me the sharpest display on a translated modal:
transform: translate(calc(-50% - .4px), calc(-50% - .4px));
EDIT:
For IE11 compatibility:
transform: translateX(-50%) translateX(-0.4px) translateY(-50%) translateY(-0.4px);
For modal boxes, this css will help:
-webkit-transform: translate3d(-50%, -51%, 0);
-moz-transform: translate3d(-50%, -51%, 0);
transform: translate3d(-50%, -51%, 0);
Instead of placing Y axis at 50%, make it 51%. This helps in my cse.
If you have a different positioning, play around, but usually 1% up/down fixes blurry content.
TLDR
I faced this problem a few days ago. I almost went crazy trying to sharpen the fonts in Chrome. I have read all posts in this thread and in all other posts regarding sharpening fonts in Chrome. Even the message "The only correct way to solve this" did not help in my case. What helped?
It is worth mentioning that the problem occurred in the following div:
position: sticky;
left: 16%;
And the 'sticky' attribute turned out to be the biggest problem. For sticky elements, we set the position as for 'absolute' elements - using attributes the 'left', 'top' etc. And here is the problem: with not integer values of the 'left' the font is rendered dramatically blurry, with integers it is much better.
What is the solution?
position: sticky;
left: 0;
margin-left: 16%;
And that's all. Chrome will handle the percentage 'margin' and the fonts will look sharp.
I know this is an old issue but since i stumbled across it in 2022 I thought I just tell someone who needs this how I solved it in my situation:
I had a modal with a textarea in it and in Chrome it was displayed blurry, but only when the textarea was overflowing.
My modal - NOT the textarea itself - had overflow: hidden; so I just removed that.
Adding a CSS transition to the parent element of the parent element of my blurry element (which was using transformX which was causing blurriness) actually cancelled out the offending blurriness.
The similar issue happened for me.
I tried with all the suggested methods none worked fine. However,finally I resolved it.
As there is an issue with google chrome having font-weight:600 or more.
Try changing the font-family to font-family:"Webly Sleek SemiBold","Helvetica";
The font-weight property will work fine for it.
Another cause may be that you are not providing the needed font weights that you are utilizing.
For example, if you want to use both Lato or Roboto you want to include more than just the standard weight. This example applies if you are using Google Font API:
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,900|Roboto:500,700">
Note: Lato is available in 100, 300, 400, 700, and 900 font-weight, but I had to specify 900 for my 700 text to become crisp...not sure why.
For now, I found only one good solution:
transform: translate(-50%, -50.1%)
0.1% - in general user can't see this
Hope chrome will fix it - the bug exists since 2014))))
If you do not want implementing any special js or custom solution and the only what you want to achieve is center your div, and the width and height does not have fixed size, you can simply use this:
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
If one of sizes is fixed, you can try this approach:
position: absolute;
left: 50%;
translate: transformX(-50%);
top: 0;
bottom: 0;
margin: auto;
It fixes the problem with blurred font in chrome.
You can solve this issue by putting:
transform: inherit;
The best way I've found to resolve this issue which appears to only be an issue in Chrome and only on specific screen sizes, is to replace all transform:translate(-50%,50%) definitions with alternate solutions. Using any other solution may solve it on your screen, but not on another.
Transform definitions are usually used to center elements. Rather than using a transform definition, find another way to center your element, problem will be solved. In our case, we had a fixed div we wanted centered, with a max-width of 1800px and bottom set to 0px;
#cntr{position:fixed;left:50%;bottom:0;width:100%;max-width:1800px;transform:translateX(-50%);-ms-transform:translateX(-50%);-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-o-transform:translateX(-50%);text-align:center;}
Lot of definitions in there to cover all browsers. Changed to this to resolve it :
#cntr{position:fixed;left:0;right:0;margin:auto;bottom:0;width:100%;max-width:1800px;text-align:center;}
A lot less code, cleaner, faster, and worked 100%, without needing to edit any HTML.
Definitions that now center the fixed pos div are: left:0;right:0;margin:auto;
No translate required, no decimal point placed divs.
For those still trying to find a solution to this, setting background fixed it for me for some reason.
background: #fff;
I found that applying the translate3d(0, 0, 0) fix as JSuar suggested worked in Chrome but not Safari.
The one thing that did work across browsers was to give the element I was centring (using transform: translate(50%, -50%)) an even pixel width — changing the width from 425px to 426px made the text sharp again.
The issue often happens with position: fixed; and transform: translate(...) when the width and height of the element are not a round even number.
One of the solutions is to round up the numbers programmatically. Example:
function roundToEven(x) {
const rounded = Math.round(x)
return rounded % 2 ? rounded + 1 : rounded
}
const element = document.getElementById('element-id')
const rect = element.getBoundingClientRect()
element.style.width = roundToEven(rect.width) + 'px'
element.style.height = roundToEven(rect.height) + 'px'
You should choose your font with corresponding font weight which you want if you want thin, regular and bold text. You should choose font with weight 100 | 400 | 700 example: like below
Font weight is not only number. File should be available in server or directory.
Each font weight is separate file.
If you force to change regular font into bold without resource, it showing with blurry. I hope you get it.
#import
url('https://fonts.googleapis.com/css2?family=Roboto:wght#100;400;700&display=swap');
Just in case anyone is having this issue using the Roboto font from Google. My text was looking sort of blurry. I noticed that I wasn't importing the correct font-weight from Google. I needed 700 but wasn't including it.
https://fonts.googleapis.com/css2?family=Roboto:wght#300;400;500&display=swap
vs
https://fonts.googleapis.com/css2?family=Roboto:wght#300;400;500;700&display=swap
I had this issue with my site as well, using a similar setup.
The issue appears because of a 0.5px difference.
An easy fix is to change the top property from 50% to calc(50% - .5px)
I have been trying to use CSS transforms on a element to center an absolutely positioned image, so that I can transition position from center to left. This is the basic code (with vendor prefixes in all of the combinations) I have been using.
position: absolute;
left: 50%;
height: 100%;
transform: translateX(-50%);
transition: transform 1s, left 1s;
And then on hover, the following properties are changed.
left: 0;
transform: translateX(0%);
This all works perfectly, but the problem starts when the height of the wrapper also changes during transition. WebKit appears to cache the width of the element from what it was before while transitioning the element, and because the width/height change during transition, once it reaches the end of the transition, it jumps to where it belongs. Here is a JSFiddle that shows my problem. It works perfectly in Firefox and IE10, but WebKit based browsers Chrome, Safari, and Opera, have a layout flash at the end of the hover out.
JSFiddle Example
I have spent the past few days trying everything I could think of to trick WebKit into behaving correctly, from adding additional CSS properties, transitions, animations, and even triggering a reflow on the element using requestAnimationFrame and timers, but nothing seems to help. I would be very grateful to anyone who can offer a solution.
This was apparently a bug in the vendor-prefixed implementation of CSS transitions where it pre-computes the target and does not update it after a reflow. It's no longer resent in the un-prefixed version in newer versions of WebKit.
In my CSS I defined a transition for a class. For some reason, when I hover over the class with the transition, the transition-duration for some reason alters the font color elsewhere (form placeholders and certain links). (This happens only in Safari as far as I can tell.)
Here's a jsFiddle that shows what I'm talking about:
http://jsfiddle.net/EJUhd/
Does anyone know why this occurs and how I can prevent it?
I was struggling with a similar issue.
For me, random links throughout the page became apparently bold (clearly something to do with OSX and anti-aliasing in Safari, as Chrome (in windows 7 and OSX) as well as the same version of Safari in Windows worked fine.
The solution is not obvious, and depending on what you are doing might not be optimal, but adding this line of code fixed the issue:
-webkit-transform: translateZ(0);
This basically triggers the GPU to do animation, and the text no longer had artifacts in my site. Do note that it's not always appropriate to use it, as it may use more battery life and use more resources. Sometimes however, it uses less, so basically check the performance when you add it.
You add this to the normal state not the :hover animated state.
img { -webkit-transform: translateZ(0); }
As opposed to on the:
img:hover { /* not here */ }
The other very positive side effect is that depending on the animation you are doing, it might be smoother through the GPU. So you won't get the choppy animation you mention in your follow up post. In my case, the animation was more seamless in safari. I was doing a 120% scale and 5 degree rotation of an image with some box-shadow appearing at the same time. In my situation, it did not reduce CPU usage unfortunately.
There is no more relevant topic I've found for a problem I had, but that's related to mentioned above issue. So, might be helpful for some one.
In two words: I have some container (popup), some element inside.
Appearing goes the following way: container background is fading up to dark via opacity and element inside is scaling up (like coming closer to us from behind). Everything works great everywhere but not in Safari (Mac/Win/iPhone). Safari "initially" shows my container, but it blinks some strange way (tiny short flash appears).
Only adding -webkit-transform: translateZ(0); (to container!!!) did help.
.container {
-webkit-transform: translateZ(0); /* <-- this */
}
.container section {
-webkit-transform: translateZ(0) scale(.92); /* <-- and I added translate here as well */
-webkit-transition: -webkit-transform .4s, opacity .3s;
opacity:0;
}
.container.active section {
-webkit-transform:translateZ(0) scale(1);
-webkit-transition: -webkit-transform .3s, opacity .3s;
opacity:1;
}
But speaking of the transitions, there was also the following part of code:
.container {
...
top:-5000px;
left:-5000px;
-webkit-transition: opacity .5s, top 0s .5s, left 0s 5s, width 0s 5s, height 0s 5s;
}
.container.active {
-webkit-transition: opacity .5s;
top:0;
left:0;
width:100%;
height:100%;
}
considering, that I want to show/hide the popup using only css switching (and also to make it disappear nicely instead just "display:none").
so, somehow on appearing Safari (obviously) was inheriting transition properties besides "opacity" even as I've overloaded them with only -webkit-transition: opacity .5s;
so, adding the following solved the problem:
.container {
...
-webkit-transition: opacity .5s, top 0s 0s, left 0s 0s, width 0s 0s, height 0s 0s;
}
I can't begin to tell you why it's doing this, but Safari isn't changing your text color, it's anti-aliasing the text differently while the transition is in motion. The text edges get smoother, and the text itself becomes thinner. This is extra obvious if you zoom in on the fiddle with accessibility tools. At some smaller sizes, the shading around the button next to the form text shifts too. (Is it possible that Safari is redrawing some things, or reorienting them on a sub-pixel level during the transitions ? Somebody explain this please, it's driving me nuts now!)
Because I have no real idea why it's doing this either, these might not be the best solutions:
Depending on what you're transforming, replacing the css transform with a javascript animation will probably fix it.
For example in your fiddle, the problem also occurred with a scale transformation, but not with a similar jQuery animate function.
There seem to be some shades and styles where the anti-aliasing change is less obvious (at least in the fiddle), so you could also try styling the placeholders and other effected text differently.
(This thread may help with styling the placeholders, if you go that route: Change an HTML5 input's placeholder color with CSS )
Thanks to the identification of anti-aliasing above, as well as help from the articles below, I modified my code to include translate3d(0,0,0) and the problem disappeared:
-webkit-transition-duration: .17s, .17s translate3d(0,0,0);
The transition isn't as smooth as it once was but that's a subject for another question.
Wonky text anti-aliasing when rotating with webkit-transform in Chrome
http://johanbrook.com/design/css/a-fix-for-antialiasing-issues-in-webkit-browsers/
http://www.webkit.org/blog/386/3d-transforms/
i had the same problem, while a transition some text became antialiased. this happen only in anchor text that are positioned relative e with z-index inside an element positioned and with z-index itself.
if i remove all position and index the problem disappear.
There is a similar problem using transition and translate3d. Sometimes any element on the page with :hover styles shows its hover behavior. I have this problem using a slider. Put the -webkit-transform: translateZ(0); to the :hover element and its behavior is normal.
For rotation() maybe it's fine, but for scale() It didn't worked the -webkit-transform: translateZ(0); formula.
I used :
-webkit-font-smoothing: antialiased;