Original address:www.html5rocks.com/en/mobile/h…

# introduction

In today’s increasingly complex device world, the available pixel density of screens has become very wide. They range from very high resolution displays to far less advanced ones. Application developers need to support a range of pixel density display devices, which can be quite challenging. On the mobile Web, things get more complicated:

  • A variety of devices come in different shapes and sizes.
  • Limited network bandwidth and battery life. When it comes to images, the goal of Web application developers is to provide the best quality images as efficiently as possible. This article describes effective techniques for achieving this effect, both now and in the near future.

If possible, avoid using pictures

Before opening this worm, keep in mind that the Web has many powerful technologies, mainly resolution and DPI independence. Specifically, text, SVG, and most CSS will “only work” due to the Web’s automatic pixel scaling capabilities (via devicePixelRatio).

That said, you can’t always avoid using images. For example, when you are working with some image resources, it is difficult to use pure SVG or CSS. It doesn’t make much sense to automatically convert images to SVG, because simply zooming in will make the images look blurry.

Overview of high DPI imaging technology

There are many techniques for solving the problem of displaying the best quality images as quickly as possible, which fall into two broad categories:

  • Single picture for quality optimization
  • Multiple images are displayed selectively

Single image solution: Clever manipulation of an image. The downside is that performance on some devices will inevitably be sacrificed, as images with high DPI will be downloaded even on older devices with lower DPI. The implementation methods are as follows:

Multi-picture solution: use multiple pictures, select the best picture for display. This approach adds additional developer effort because multiple versions are created for each image and an optimal selection strategy is used. Some optional ways:

  • Javascript
  • Server forwarding
  • CSS Media Query
  • Take advantage of built-in browser features (image-set(), sercset)

High compression of high DPI images

Image resources typically account for 60% of a site’s download bandwidth, and this proportion will continue to grow if high DPI images are provided to all clients. So what are the details?

I used some test scripts to generate 1x and 2X images with 90%, 50% and 20% image quality respectively:

From this small and not very scientific sample, it seems that compressing large images provides a good mass size trade-off. To our eyes, a 2x image with a high compression ratio actually looks better than an uncompressed 1X image.

Of course, providing low quality, high compression ratio 2X images to 2X devices is not nearly as good as providing high quality images, and the above approach will result in a loss of image quality. If you compare a 90% image quality image to a 20% image quality image, you will feel significant distortion and graininess. These images are not acceptable in situations where there are high requirements for image quality (for example, a photo viewer application) or for application developers who are not willing to compromise.

The above comparison uses uncompressed JPEG images. It is worth noting that there are more trade-offs and trade-offs between the widely used image formats (JPEG, PNG, GIF), which led us to choose another processing method…

Webp image format

WebP is a very compelling image format that compreses very well while maintaining high image fidelity. Of course it is not available in all cases!

One way is to check WebP support through JavaScript. Load the 1x image through data-URI, wait for the load or error event to be triggered, and then verify that the size is correct. Modernizr comes with such feature detection scripts, available through modernizr.webp.

A better way to do this is to use the image() function in CSS. If you have webP or JPEG images, you can write:

#pic {

background: image("foo.webp", "foo.jpg");

}

Copy the code

There are some problems with this approach. First, image() is not widely implemented. Second, while WebP compression breaks the compression limits of JPEG, it is still a relative improvement – less than 30% reduction in volume. Therefore, WebP alone is not enough to solve the problem of high DPI.

Progressive image format

Progressive image formats such as JPEG 2000, Progressive JPEG, Progressive PNG and GIF have the advantage of being able to see the image before it is fully loaded. This may incur some additional overhead. Jeff Atwood claims that progressive images “increase the size of PNG images by about 20%, and JPEG and GIF images by about 10%”. However, Stoyan Stefanov claims that for large files, progressive images are more efficient (in most cases).

At first glance, progressive graphics looks very promising, providing the best quality picture possible as quickly as possible. The reality is that browsers may stop downloading and decoding images once they know that additional data will not improve image quality (all fidelity improvements are based on sub-pixels).

Although connections are easy to terminate, restarting them is often expensive. For sites with many images, the most efficient approach is to keep a single HTTP connection active and reuse it for as long as possible. Once an image has been downloaded, the browser will close the current connection and then create a new one, which can be really slow on weak networks.

One solution to this is to use HTTP Range requests, which allow the browser to specify the Range of bytes to extract. Smart browsers can make a HEAD request to get the title, process it, decide how many images are actually needed and get it. Unfortunately, HTTP Rang is poorly supported in Web servers, making this approach impractical.

Finally, an obvious limitation of this approach is that you can’t choose the resolution of the image, only different fidelity of the same image. Therefore, an “art level” user experience cannot be satisfied.

Select images in javascript for loading

The most obvious way to do this is to use JavaScript on the client side to decide which image to load. This method requires information from the browser to make a judgment. You can get the devicePixelRatio with window.devicepixelratio, get screen width and height, and maybe even do some network connection sniffing with navigator.connection or by making a fake request like the foresight.js library. Collect all this information before deciding which image to load.

There are about a million JavaScript libraries that do this, none of which are particularly useful, unfortunately.

One big drawback to this approach is that using JavaScript means delaying image loading until the forward-looking parser is complete. This essentially means that images won’t even start downloading until the Pageload event is triggered.

The server selects the image

This can be handled by writing a custom request handler for each image. Such a handler checks Retina support based on user-agent (unique information relayed to the server). The server-side logic then decides whether to provide a high DPI image to load the appropriate asset (named according to some known convention).

Unfortunately, the user agent does not necessarily provide enough information to determine whether the device should receive high or low quality images. In addition, anything related to user-Agent can be a vulnerability and should be avoided as much as possible.

Use the CSS media

CSS media queries let the browser know your intent and load the correct code. In addition to the most common media query use – match device size – you can also match devicePixelRatio. The associated media query is device-Pixel-ratio, and min and Max values can be set. If you want to load a high DPI image and the device pixel ratio exceeds the threshold, you can do the following:

#my-image { background: (low.png); }



@media only screen and (min-device-pixel-ratio: 1.5) {

#my-image { background: (high.png); }

}

Copy the code

Using this approach, you can regain the benefits of forward-looking parsing that JS solutions lose. There is also flexibility in choosing response breakpoints (for example, loading images with low, medium and high DPI) when certain image requests go wrong.

Unfortunately, it’s still a bit clunky and requires writing and looking weird CSS. Also, this method is limited to CSS properties and therefore cannot be set. All images must be background elements.

Use new browser features

There has been a lot of discussion recently about the issue of high DPI images supported by the Web platform. Apple recently added the image-set() CSS function to WebKit. Therefore, both Safari and Chrome support it. Since it is a CSS function, image-set() does not solve the label problem. The srcset attribute solves this problem, and image-set and srcset are discussed in more detail below.

image-set

The image-set function is very simple to use and needs to be prefixed in WebKit:

background-image:  -webkit-image-set(

url(icon1x.jpg) 1x,

url(icon2x.jpg) 2x

);

Copy the code

It will tell the browser that there are two images to choose from. One is 1x and one is 2x. The browser then automatically selects the right image to load based on a number of factors.

In addition, the browser will automatically scale the corresponding image size for loading.

In addition to setting 1x,1.5x, or Nx, you can specify the pixel density of other devices.

This is ideal, except on browsers that do not support image-set (no images will be displayed! This is too tragic, so a backup strategy is needed).

background-image: url(icon1x.jpg);

background-image: -webkit-image-set(

url(icon1x.jpg) 1x,

url(icon2x.jpg) 2x

);



background-image: image-set(

url(icon1x.jpg) 1x,

url(icon2x.jpg) 2x

);

Copy the code

Browsers that support image-set will select images to load, those that do not will load 1x images. The obvious drawback is that only 1x images will be loaded on browsers that do not support image-set.

srcset

<img alt="my awesome image"

src="banner.jpeg"

srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">

Copy the code

As shown above, in addition to the x declaration provided by image-set, the SRcset element also accepts values of W and H corresponding to the viewport size in an attempt to provide the most relevant version. The above will provide devices with viewport widths below 640 pixels for banner-phone. Jpeg to small-screen high-DPI devices, banner-hd.jpeg to high-DPI devices with screens larger than 640px, and banner.jpeg to everything.

Since the SRcset attribute of the IMG element is not implemented in most browsers, you might be tempted to use the one with the background

Tags are semantic, and using div reduces the accessibility of crawlers.

conclusion

There is no silver bullet to solve the problem of high DPI images.

The simplest solution is to avoid images altogether and opt for SVG and CSS. However, this is not realistic, especially if there are high-quality images on the site.

JS, CSS, and using server-side methods all have their advantages and disadvantages. The most promising approach, however, is to take advantage of new browser features. Although browser support for image-set and srcset is still incomplete.


Blog: Yalishizhude.github. IO Grow with the author please follow and subscribe to blog: star