Browsers, css and image aliasing - css

I try to scale down pictures (representing rendered text).
Something I noticed is that different browsers will give very different results in the way they are handling the scaling and the anti-aliasing after that (it seems that they almost all apply that by default).
Here is a jsfiddle (I can only rely on the results on my Mac and to see the problem, it has to be tested on different browsers too):
https://jsfiddle.net/ottmobk9/7/
<div class="test"></div>
<script>
/* I added an animation and a loop in order for you to see how Safari and */
/* Opera handle the scaling (after the scaling, it's sharp for one second */
/* then it becomes blurry) but no animation or loop is needed. If the */
/* picture is downscaled, it loses its sharpness. */
function testResize()
{
setTimeout(function()
{
x=$('.test>img').height();
if(x>55)
{
$('.test>img').css('height',(x-1)+'px');
testResize();
}
},5);
}
setInterval(function()
{
$(".test>img").remove();
$(".test").append("\
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/T.png'>\
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/E.png'>\
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/S.png'>\
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/T.png'>\
");
setTimeout(testResize,1000)
}, 3000);
</script>
Firefox (on Mac): The original size is a bit blurry (which is strange) but the scaled size seems very crisp.
Chrome (on Mac): The original size is crisp but the scaling automatically applies a filter of some sort which makes the resized text instantly blurry.
Safari and Opera (on Mac) are somewhere in between as, the original picture is crisp but after the scaling, they keep the picture crisp for about one second before they apply an anti-aliasing "filter" of some sort.
Those tests on different browsers prove that the blurry render is not a matter of a non integer ratio between the original and scaled picture.
Firefox starts bad but ends good.
Safari/Opera: start good but end bad after a second
Chrome: start good but instantly ends bad.
But it is not a fatality as Firefox shows a decent final scaled picture and Safari/Opera render the scaled picture alright for about one second. Chrome just can't handle it right.
So, these browsers apply something to the pictures and I want that "something" to just not be applied if not asked for, which is a fair request.
So, I tried to use the "image-rendering" property (uncomment it in the css part of the JSfiddle to see it in action).
And it works.
Kind of.
It depends on the picture...
So, it's not a problem solver.
To show that, here is another test where we can see it doesn't work that well in all situations after all:
https://jsfiddle.net/9f36rtza/34/
<style>
.non_scaled_non_filtered{
background:white;
}
.non_scaled_non_filtered img{
height:100%;
}
.scaled_nonfiltered{
margin-top:20px;
background:white;
}
.scaled_nonfiltered img{
height:34px;
}
.scaled_filtered
{
background:white;
margin-top:20px;
image-rendering: -moz-crisp-edges;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
-ms-interpolation-mode: nearest-neighbor;
}
.scaled_filtered img
{
height:34px;
}
</style>
<div class="non_scaled_non_filtered">
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/84.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/101.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/115.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/116.png'>
</div>
<div class="scaled_nonfiltered">
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/84.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/101.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/115.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/116.png'>
</div>
<div class="scaled_filtered">
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/84.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/101.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/115.png'>
<img src='http://www.lexgotham.com/xx-prev-xx/b-generator8/test/116.png'>
</div>
Firefox (on Mac): The non-scaled/non-filtered picture is a bit blurry once again, for whatever reason compared to the original (which is supposed to be the same size). But the "image-rendering" gives a scaled result very close to the original. Way more than the non-scaled picture, which is weird.
Chrome and Opera (on Mac):The unscaled picture is crisp as it should and the scaled picture
with "image-rendering is a bit blurry. Less than the scaled/unrendered one, though.
Safari (on Mac): This one is absolutely the worst. The non scaled picture is perfect.
The scaled but unfiltered version is a bit blurry. And the scaled and
"image-rendered" picture is just totally over-processed. It looks
like the picture has been sharpened several times in a row. This alone makes the "image-rendering" property unusable for production.
FYI: In the JSFiddle, I also added the "font-smoothing" and "text-rendering" properties (uncomment if you want to see them in action).
But as we don't deal with real text, of course, it doesn't change a thing.
All in all, it doesn't look like "image-rendering" is de-activating the "anti-aliasing" filter that the browsers apply by default.
It only seems to add a new layer of image rendering process that each browser handles more or less well.
So, it's not a problem solver. It only hides more or less well the problem, depending of the picture. And sometimes it's even worse (Safari).
All I want is to de-activate any unwanted anti-aliasing process for any size of picture and to have a consistent result among all the browsers.
So, I have a situation.
I need to have a faithful render as I'm doing a web app that renders divs containing pictures and texts that people can scale, and the final purpose is to print the results in Hi-res.
That filter applied won't just allow me that and I have found no solution or workaround that works in any situation.
Depending on the browser, people will get various results with none of them that is perfect.
If I don't apply "image-rendering", all aforementioned browsers but Firefox is giving me a blurry render. And firefox gives me a blurry render if the picture is not scaled.
If I do apply "image-rendering" however, none will handle the sharpness well. Firefox is the least worse but it is not perfect neither.
Each of them seems to apply another filter instead of just de-activating that anti-alias filter they just apply.
So, what can I do?
The ideal way would be to know how just not to apply that anti-alias filter in the first place.
Of course I can use other ways to scale down the picture (css scale/zoom) but it's just the same. I tried. The method of scaling doesn't seem to be the problem, it's the way the browsers render a scaled image in all cases.
Thank you for your help.

Related

Image is blurry when upscaling in Mobile Safari

I'm implementing a Pinch to Zoom gesture in JS/CSS. In order to do so, I'm putting a fairly large image source inside a small sized IMG tag and then apply a CSS scale transform to make it bigger.
Things are working fine however on Mobile Safari the image gets blurry once I start scaling up. It should not be the case as the src for the image is big enough to support this size, but somehow Mobile Safari is displayed it as blurry.
I have debugged the issue quite a bit and found out that the culprit is an unrelated div in my page that is setting translate3d(0,0,0). To my understanding this is a Hack to trigger GPU hardware acceleration. What I believe it is happening is that because of translate3d(0,0,0), hardware acceleration is being applied when rendering the <img/>, and since the <img> is small in size, it is drawn small and the scale is applied afterwards.
To better understand the problem, I have it this code, available in in codepen here
HTML
<div>
<div id="translate3d-div"/>
</div>
<img id="image" src="https://www.trackalytics.com/assets/thumbnails/lipsum.com.jpg"/>
CSS
#translate3d-div {
/* If I remove this, the image is not blurry */
transform: translate3d(0,0,0)
}
#image {
width: 95px;
height:76px;
transform: scale(20);
}
This displays the image blurry on Mobile Safari, but it works fine on Chrome in Android.
Is there a way to fix this other than removing the unrelated translate3d? I don't think I can do that since it might be used by some other feature in the webpage.
This is because how WebKit renders transforms when hardware acceleration is enabled (like in iPhone). It increases performance dramatically but affects antialiasing when you apply a 3DTransform when no real transformation happens.
A hackfix is to set a background for the element.
#translate3d-div {
transform: translate3d(0,0,0);
background: transparent;
}
Source: https://dropshado.ws/post/6142339613/resolving-anti-aliasing-on-webkit
I couldn't find a working hack for this, but the workaround I used was to simply create a bigger HTMLImageElement and scale it down initially. Then scaled up it will not look blurry. This made my code slightly more complicated but it is working fine.

linear-gradient inaccurate in Google Chrome

I have a little problem in Google Chrome with my gradient:
body {
background-image: linear-gradient(rgba(43,66,88,0) 144px,#f4f7fa 144px), radial-gradient(at top center, #44698b,#162a3c);
}
.header {
height: 144px;
}
.main {
height: 500px;
}
The HTML:
<div class="header"></div>
<div class="main"></div>
Live view: http://jsfiddle.net/p726s/
You can see the problem in the picture:
Even if there is set the gradient to end at 144px and the next color begins at the exact same pixel, Chrome creates a little gradient so that the first color does not end at 144px but at 142px. The next two pixels it creates a gradient to the second color instead of creating a straight line. I don't know how do force the browser to don't do it. Has anyone any suggestion?
Edit 6th July 2016:
It seems that Google has fixed that problem the last months…
I do not have this issue with my own Chrome installation; is your Google Chrome updated to the latest version (33.0.1750.154m)?
I realise that some people on your site may not have (or be willing) to update their Chrome installation (e.g. they have Google Update turned off), however Chrome is known to be picky with some stuff, and you might have just stumbled into one of the things that it just doesn't like.
Also, please rephrase your question; I could only just about see the difference in your gradients and some people (like King King, whom replied to your OP) may not be able to see the difference.
It seems that Chrome is triggering subpixel rendering. Check if is there any CSS 2D or 3D transformation activated on the element or parent container, such as transform:rotate(), and disable it to test.

Font Pixelate Issue in Chrome (HTML5/CSS3)

I have a issue that text is pixelated when 2D scale of CSS transform is applied. (I only tested in Chrome. I'll do cross-browsing later, so you don't need to test it on different browsers.)
CSS
.versus_block_hover
{
-webkit-transform: scale(1.2,1.2)!important;
-webkit-transition: 50ms 0ms!important;
z-index:1100!important;
border-width:1px;
border-color:#000;
border-style:solid;
}
Javascript Code
$('.versus_block').hover(function() {
$(this).addClass('versus_block_hover');
$(this).parent().css('z-index','1100');
}, function() {
$(this).removeClass('versus_block_hover');
$(this).parent().css('z-index','0');
});
I know that Chrome uses bitmap operation during CSS transform for 3D acceleration.
However, when I tested it in jsfiddle, it wasn't pixelated. In face, it seems that Chrome re-draws a text when the transition is done.
See this working example. Hover over a box. (I put all CSS elements from my actual site.)
http://jsfiddle.net/eCkdE/11/
And, this is an actual site that has an issue. (Hover any of blocks, then you can see pixelated fonts when it's expanded)
http://jsfiddle.net/GJ7BM
Anyone has an idea how to fix it? It's okay that you can fix it on my jsfiddle directly.
The problem seems similar to this: http://code.google.com/p/chromium/issues/detail?id=119470
So what actually triggers the problem, is when the element is rendered as a comsposited layer on uneven coordinates. If you enable the Composited render layer borders option in chrome://flags you can see that in your first jsfiddle example the div becomes a composited layer while the transition is in progress, the text becomes blurry, once the transition is complete it's no longer composited, and the text becomes clear (see this modified fiddle where it's easier to spot the border: http://jsfiddle.net/kF2Q5/).
In your second jsfiddle example the text stays blurry even after the transition is complete because it's still an composited layer (on uneven coordinates presumably), this is caused by these lots of nested and underlayed transforms (an element that lies above a composited layer, becomes a composited layer too). See this modified fiddle: http://jsfiddle.net/PqPSU/ All transforms are being disabled using:
* {
-webkit-transform: translateX(0) !important;
}
So only the transform on the hovered element is left. If you have enabled the Composited render layer borders option, you should see that all the red/brown borders around the tiles, indicating composited layers should be gone. And you should see that the text becomes clear once the transition is complete, just like in your first example.
Unfortunately I have no solution for the underlying problem, ie the blurry rendering of composited layers, I guess it's something that cannot be solved on this end, but can only be fixed in the rendering engine and/or the graphics card driver, depending on where exactly the problem is caused.
You can adjust the text-rendering css property.
https://developer.mozilla.org/fr/docs/CSS/text-rendering
But your example works fine for me, check on another computer.
You should update your browser, or your graphic card drivers.

Browser Alignment Compatibility Issue

My jsfiddle is here http://jsfiddle.net/pedz/YG3bv/
The full page is http://jsfiddle.net/pedz/YG3bv/14/embedded/result/
This is my first attempt at posting jsfiddle pages so let me know if I botched it.
If you view this with Chrome or Safari, the leftmost pixel of the left tip of the little triangle is directly under the rightmost pixel of the underline. This is what I want.
If viewed with Firefox (I'm using 13), the little triangle is moved right by what looks like two pixels.
I've been told that when viewed with IE9, it is moved left one pixel.
I've fiddled with this for days comparing Chrome with FF mostly. If you add in borders to the various elements, then you can determine some of my conclusions.
FF and Chrome agree about the left and bottom but they do not agree about the top nor the right of the parent container. FF has an extra column or two of pixels on the right when compared to Chrome. That is why the arrow is one or two pixels further right.
It also appears, when you put a border around the foo span, that FF moves the text up a pixel when compared to Chrome. The descenders in FF do not touch the border while they do (or very nearly do) in Chrome. Likewise, there is a bit more white space above the text (within the border) in Chrome than in FF. This particular issue I'm not concerned with... its just something I've observed.
What I figure is I need to "reset" some CSS attribute but I've not yet figured out which one I need. That is really my ultimate goal here... to understand what CSS attribute is different between the browsers.
My secondary goal is to come up with a way to get the little triangle in the same place in the different browsers... or a technique to do it. I could add in browser specific Javascript to nudge things one way or the other but, from the net, that sounds like a really bad idea.
Previews:
Preview in Chrome 19
Preview in Internet Explorer 9
Preview in Firefox 13
This is certainly a very interesting scenario.
Looks like Firefox is rendering a non-breaking space after the <span> with triangle, which is certainly not your intention. This is because span with triangle is nested inside another span.
The tbody in your code looks like:
<td class='upd_apar_def-defect upd_apar_def_dual_button'>
<span class='foo'>
<a href='some/path' class='upd_apar_def_link'>123456</a><span class='upd_apar_def_span'></span>
</span>
</td>
<td class='upd_apar_def-apar upd_apar_def_dual_button'>
<span class='foo'>
<a href='some/path' class='upd_apar_def_link'>987654</a><span class='upd_apar_def_span'></span>
</span>
</td>
Try replacing it with to resolve the issue:
<td class='upd_apar_def-defect upd_apar_def_dual_button'>
<span class='foo'>
<a href='some/path' class='upd_apar_def_link'>123456</a><span class='upd_apar_def_span'></span></span>
</td>
<td class='upd_apar_def-apar upd_apar_def_dual_button'>
<span class='foo'>
<a href='some/path' class='upd_apar_def_link'>987654</a><span class='upd_apar_def_span'></span></span>
</td>
No issues with CSS and rest of your DOM, but apparently Firefox seems to do the right thing (imo).. though its debatable! :-)
At a glance, what I'm seeing is that there are no font-size or font-family values set. The content appears to have a different default font-size and/or font-family in different browsers, which may be part of what's causing the layout to vary by browser.
Edit:
After adding font-size and font-family, I still see a difference between FF and Chrome. Adding a traditional reset.css did not appear to have any effect. I suspect that the differences are mainly from trying to apply CSS-layout styling (position:absolute, etc) to HTML table elements (td, etc). That combination may have unpredictable results no matter what you do.
Fixed the Firefox issue.
Fixed on Firefox
I have updated your Fiddler post with additional CSS reset code for cross-browser compatibility from here. Make a local copy of this file or embed in your existing CSS file.
I added the following CSS reset code above /* your CSS starts here */ line:
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
border:0;
font-size:100%;
font:inherit;
vertical-align:baseline;
margin:0;
padding:0;
}
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
display:block;
}
Editable: http://jsfiddle.net/YG3bv/31/
Full screen result: http://jsfiddle.net/YG3bv/31/embedded/result/
Hope this help.

Does IE(7?) distort backgrounds from sprites?

I am pulling my hair out on this one.
We're just about done with the development of an overhaul to our site. As a last step, we're trying to wrap up all the glyphs and icons into a sprite. They're all transparent .png's so the sprite is too. It appears that if a background comes from a sptire, IE distorts it. If it comes from the original file, it does not. FF and Chrome are fine either way.
I am looking at the orignal image and the sprited version side-by-side with grids to see that the pixels are identical. I have counted the pixels in the sprite many times to ensure I'm using the right coordinates. My CSS looks like this:
XXbackground: url(sprite.png) no-repeat 0px -837px; /* lozRedRedSpacer */
background: url(lozRedRedSpacer.png) no-repeat;
The 'XX' lets me toggle back and forth. With the single-file version, it looks perfect: . The sprite-version looks like this: . It looks like it is 'squished' both vertically and horizontally. This does not happen in FF or Chrome.
Any ideas?
EDIT I was able to strip out most of the noise and post an example here. I've added notes to the example to describe my problem.
Thank you so much for taking the time to look at this!
UPDATE We've since replaced these 'overlapped divider images' with CSS pseudo-classes that REALLY do overlap and the zooming issue seems to have gone away. Of course now we have new problems - IE8 gets the z-order wrong and IE7 doesn't understand psuedo-elements at all. But at least the markup is simpler and the zooming issue is gone.
It turns out my problem was caused by IE's 'zoom' feature. Without any zoom, everything looks great like the other browsers. Even 150% or 200% looks good. But 125%, where I had it, causes this distortion. It happens in IE7 and IE8.

Resources