Preparing graphics for high resolution devices

I have a very basic question about making images look sharp on high resolution devices like retina displays, etc. Let’s say I have this code:

<p>This is my dog:</p>
<img src="dog.jpg" width="200" height="200">

and dog.jpg has dimensions 200x200 pixels - then I suspect on high dpi displays the physical size of the picture will be more or less the same as on a low dpi device except it will look a bit blurry. What do I need to do to make the image look sharper? Is it enough to leave the html code the same and provide dog.jpg in 400x400 size to make the device use all the details?

Yes you can leave the html alone but actually create the image at 400x400. Of course this means creating the image at 400x400 and not just resizing your existing 200px image to 400px. You can then lower the quality of the image so that the filesize isn’t far away from the original because as it gets resized in the browser it becomes sharp again.

This article explains it.

Or you could just use svg depending on the type of the image.

Lastly you can use srcset to display different images depending on the device but means changing html and creating separate images.

3 Likes

Thanks, this is an interesting article about compression. I’ve never actually used high dpi images for web sites so I want to make sure I got my knowledge straight.

And what about background images, how are they scaled on retina displays? With <img> tags the situation is quite simple because images get width and hight in css pixels and the device adjusts its physical size according to its resolution. But a background image usually has no specified dimensions. For example:

<div style="width: 200px; height: 200px; background: url(bg200x200.jpg) no-repeat">
  text
</div>

Suppose the image file has dimensions 200x200 pixels. On a normal display the image will be the same size as the div but how big will it be on a retina display? Same as the div or smaller? If I want to do the same thing, that is provide a sharper image 400x400 for retina displays how do I do it? By using background-size property to set the size to 200x200 pixels the same way as in an <img> tag?

With backgrounds you can specify sizes explicitly with the background-size property (or within the shorthand background). Where it’s a fixed size, you may do the same and just use an image double the resolution.
In some cases you may have a more dynamic background size, like cover. Again use an image of sufficient resolution, optimised with compression. But you may also optimise things for slower connections by dishing out different resolutions in media queries. Eg:-

@media screen and (min-device-width: 500px) and (min-resolution: 2dppx) { /* For Double density "Retina" and larger screens */ }

Will target larger screens, or ones with double density which may have a higher res image.

2 Likes

Thanks. So it looks like the traditional practice of keeping the image file dimensions and html/css image dimensions the same is no longer valid because in high dpi displays a html/css pixel is no longer equivalent to a pixel in the image file nor to the pixel on the display.

Are there any tools for testing web sites on high dpi displays for those who don’t have real devices? I don’t mean exact emulators but at least being able to see the actual dimensions and the amount of detail in images on a site relative to other elements.

If you’re on a mac ios simulator (part of xcode) should do. It shows retina devices at actual dpi size so they take over your screen… I have to say the fact that high dpi devices show images blurred annoys the hell out of me. It means that if you use lots of icon images in your site you have to fix them all for higher dpi and that can become really tedious and inconvenient. So these days I think twice when introducing images. A good alternative can be SVGs because they scale. Adobe illustrator has a very handy utility to convert to SVG. And most times I’m inclined to just use html entities for icons if i can, this page has a lot of them http://htmlarrows.com

I’m not on a mac so I can’t use that. But I’ve found that it can be done in Firefox by changing a hidden pref, I set it to 2 and everything is scaled up so that it shows all the pixels that would be visible on a high dpi display - I’ll still need to test it out but it appears to be working fine.

I used to copy some arrows and symbols from the windows Character Map but this website is much more convenient, thanks. But I’m always worried that a symbol I choose may not be available in the character range on some devices. I see that this site uses Helvetica font, if I use Helvetica then can I be sure that all the symbols I see on that site will be displayed in other browsers, systems, mobile phones, etc.?

For things like icons, graphical elements, I try to exclusively use SVG now.
For photos and the likes, I try to use higher res, but higher compression too, for retina. It just concerns me about the greater bulk of high-res images, though the increased compression helps.
With SVG it’s win-win, being very lightweight and always sharp.

1 Like

I don’t think changing the font family changes much but maybe I’m wrong.
I haven’t tested widely so I’m not sure, and already notice some symbols look slightly different in different browsers, and would use images instead of some of those and others anyway. But there are a handful that are quite convenient and should have no problems in other devices. You can set any css text property to those and they’ll scale just fine. Also you can set those html entities in CSS like so:

.element:after {
	content : "\02630";
	/* Note how the CSS uses the unicode version of the html entity and it has to be escaped and put in the format above. "\02630" instead of "U+02630" */
	position: absolute;
	color: black;
	text-align: center;
    font-size:20px;
	top:4px;
	right: 4px;
	width: 20px;
	height: 20px;
}

The only thing that I don’t like about SVG is that it is not code friendly. Put an SVG in an HTML template and most of what you’ll see is random numbers on screen. I think creating a utility library of SVG’s stored by key in an object would be very useful in order to abstract it from the code. Also I bet they take a bit more resources to generate, the difference might be insignificant though, depending on how many and the device.

What do you mean, when the svg is in-lined, within <svg> tags? Yes this can look unsightly in the html source code.
You can use svg like an ordinary image referencing the source file in an <img> tag. But if you want some interaction through css effects, such as a colour change on hover for example, you must in-line them for that to work.
The way I handle this in an html template is to have the svg as a php include.

<div class="icon"><?php include 'images/MyIcon.svg' ?></div>

This takes all that mess out of your html and keep the image as a separate, single file that may be reused elsewhere and edited from one place.
So this give the best of both worlds, separates the image data from the html, while allowing all the fancy css effects you may want to do with it. If you don’t need those effects, just use <img>.

3 Likes

Yes exactly what you said, I was perhaps thinking in a javascript way and storing them in an object, then having a utility function that returns the svg node. But as for a PHP solution what you said is perfect. I guess for JavaScript you could also just do an AJAX request to the file and insert the content.

I’ve played a little with using larger images for retina displays and here come browser differences in their resizing algorithms. When html width and height are smaller than image’s width and height then we don’t always get the result we want, especially if it’s important to preserve image’s sharpness and detail. From my tests the worst is Chrome and all its webkit derivatives - it’s not a problem when an image is shrunk 50% or 25%, but when it’s smaller a little bit more like 49% or 24.5% then it becomes very blurry and loses sharpness.

You can have a look at a test page I’ve created - resize the browser window to see the image scaled to different sizes. The original image size is 400x400. Notice how in Chrome the image is sharp at 200x200 and blurry at 199x199, 198x198, etc. The same unpleasant threshold is between 100x100 and 99x99. This problem does not exist in Firefox and IE/Edge. (Chrome also sometimes fails to finish its resizing action after window resize and a reload is needed - but that’s a different subject).

IE/Edge, on the other hand, have a problem with too much shrinking - below 100x100 the final image starts losing pixels and the result looks pretty bad.

As far as I can see only Firefox gets the job done well and for cross browser visual compatibility it is best to keep the shrinking ratio between 50% and 100%.

This usually won’t be a problem for photographic images but for line art graphics, logos with texts, shapes, thin lines, etc., anything that is important to appear sharp and detailed, this can be a problem. Unless there is some way to force the offending browsers to use a better resizing algorithms apart from switching to svg?

1 Like

There seems to be no straight forward free of hassle solution. I found this article, which you might find useful : https://addyosmani.com/blog/generate-multi-resolution-images-for-srcset-with-grunt/

However support is not yet everywhere:

Yeah, I’ve read about srcset, actually I think its support is quite good and I wouldn’t mind using it at all. It can be used to prevent scaling of images at ‘awkward’ aspect ratios. This can work well for (more or less) fixed size images but the problem is with a more fluid design where a line art image needs to be dynamically resized, according to the browser window size or container size, for example somewhere between 50% and 100% of the original. I’ve noticed that in Chrome aspect ratios just below 100% are problematic and shrinking to 95% or 99% results in very noticeable blur and may look bad. This is the issue I was referring to and it would be great to find a solution. Generating hundreds of images for each possible shrinking ratio to be used in srcset looks like a crazy idea.

I think we’re out of luck here, unless there’s some tech I’m unaware of which could be… But I think people wouldn’t go into the other hassles discussed if there was. Sounds like your best bet is vector graphics then. Just finding a developer friendly way of using them as @SamA74 pointed out would in my opinion overvome its caveat, and also finding a hassle free way of converting normal images to svg, which there are. GIMP is free and supported in all platforms and can do that

Try this:

AMP Retina Image Version:

And instantly cached because it is a Valid AMP Page

Google Cached Version

Is there much of a difference?

Then you need to use svg for those images and your problem is eliminated.

For normal images browser scaling is fine most of the time and no one will notice.

Alternatively rather than progressively scaling the image you could reduce in a few steps instead with media queries and jump to a size that you know won’t result in half pixels.

There are some browser options to optimise the quality of the image but results are varied and not well supported. Hopefully in the future they will implement better.

In the end it does depend on the image and the image shown in your demo does exhibit the problem but is an image I would not scale progressively and would jump to a smaller image when needed. An easy universal ‘one size fits all’ solution does not yet exist :slight_smile:

3 Likes

Hm, I don’t see what AMP pages have to do with this topic? Your sample page just shows the same problem I was talking about.

Yes, svg should be the best but I’ve yet to discover how to use it effectively. So far I’ve tried a few online png to svg converters and most of them output very lousy quality svg files and those that preserve the quality output enormous file sizes like 10x bigger than a png. GIMP appears to require quite a bit of work to do proper conversion. Inkscape was close but still it requires some work and I should learn the program first. From my initial tests I’ve also found it is not easy to embed fonts in svg for cross browser support. Svg is not such an easy thing, I suppose. It would be great to have original graphics in vector format but it’s not always available.

That’s what I also think would be the best solution.

Thanks for your replies, I’m gradually learning about the pros and cons of various methods.

1 Like

I copied the AMP retina version and also could not see any differences which I thought may be due to my poor eyesight :frowning:

Try searching for @ralphm retina. He believes in having double an image size and less quality. When the image is shrunk to half size the perceived quality is better than the original size. I think that was his observations. It is not easy searching on a tablet. He recommended an article which is currently off line.

http://blog.netvlies.nl/design-interactie/retina-revolution/

Basically, you let the image keep its large dimensions, but save it at very low quality. When squashed to fit the actal space available it looks good even on retina screens.

I already linked to the proper article way back in post #2 :slight_smile:

1 Like