Menu Search
Jump to the content X X
Smashing Conf San Francisco

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf San Francisco, dedicated to smart front-end techniques and design patterns.

Leaner Responsive Images With Client Hints

Responsive images have been around long enough for most of us to have taken them for a spin, or at least to have learned from the experiences of those who have. Beyond doubt, the responsive images1 specification is a great win for the web. However, quite a few reports from the front lines suggest that responsive images can become pretty ugly.

The good news is that there is a fix! No, not throwing JavaScript at the challenge, but by asking the web server for a helping hand. Enter Client Hints, an initiative spearheaded by Google that is already available in browsers (Chrome and Opera) and that is super-simple to use. Let’s see how Client Hints can reduce both image size and verbosity of the responsive images markup.

Further Reading on SmashingMag:

This article will not demonstrate the challenges of responsive images. Several other sources have already6 done7 that8. Instead, we’ll focus on how to address the issues, with a little help from the web server and a new way for the browser, or client, to request images with specific properties. Even if this is called “Client Hints”, it is pretty specific. Let’s dive in!

Responsive Images

Good old problem: responsive images. Image credit: Eric Portis9.

What Are Client Hints? Link

Client Hints is a new feature already available with Chrome 4610 and Opera 33. More browser vendors are following. It is an initiative by Google11 (spearheaded by Ilya Grigorik), and, as its progress indicates, it is likely to be “a thing”. The initiative was also recently adopted by the HTTP Working Group12.

You can think of Client Hints as the missing link between the browser and the server when it comes to layout information. Instead of specifying every possible image breakpoint, pixel density and format in your responsive images markup, Client Hints append the current setting to the HTTP request, allowing the web server to pick the perfect fit — also known as content negotiation13.

The current way of dealing with responsive images is typically to specify different image sources based on the receiving device’s pixel density, preferred image format and viewport size. If you go through the process of picking breakpoints and formats, your markup might end up something like this:

Brad Frost: I never want to make anything that even remotely resembles this.14

Even relatively simple use cases can become quite complex using the responsive images syntax. The code shown here is from A List Apart15. (Source: Brad Frost16)

I think many of us agree with Brad on this.

To be fair, the example above include different crops of the image too. Which is something Client Hints alone can’t help you with. Still, crafting markup like this is not something a developer or designer should be spending their time on17. We need an automated process. Even if the server can generate dynamic markup automatically, client hints decouples the markup from the image which makes it easier to perform operations on the image without having to worry too much about the markup.

Let The Web Server Know Link

Imagine if the web server knew the pixel density, the viewport size and also the actual size and format of an image. This is what Client Hints does! Browsers that support Client Hints add a few HTTP headers to requests. The latest draft18 mentions these hints:

  • DPR
    This stands for “device pixel ratio,” the ratio of physical pixels on the screen to CSS pixels.
  • Viewport-Width
    This is the width of the viewport in CSS pixels. (CSS pixels means the units used in CSS to describe a layout. A CSS width of 100 pixels would be 200 device pixels (DP) if the device pixel ratio (DPR) was 2.)
  • Width
    This is the actual width of an image in real physical pixels (similar to the w descriptor made famous by responsive images).
  • Downlink
    This is the client’s maximum download speed.
  • Save-Data
    This boolean indicates whether extra measures should be taken to reduce the payload.

Downlink and Save-Data are not available in Chrome just yet, but you can imagine their purpose. Let’s focus on the currently available hints. First, we have to tell the browser to send the hints.

Enabling Client Hints In Your HTML Link

The Client Hints flow: 1. Enable client hints. 2. Client hints are added. 3. Server selects or generates an image. 4. Server responds. 5. Image rendered.19

With a <meta> tag added, Client Hints are enabled and additional HTTP headers are sent with the request. (View large version20)

You’ll have to opt in to enable Client Hints. The reason for this is that additional data shouldn’t be added to a request unless it is used for something. If it’s not used, it would work against the very purpose by adding data to the payload. Web servers can also advertise their support by adding an HTTP header to the HTML response which lists the hints accepted by the server:

Accept-CH: DPR, Width, Viewport-Width

If adding an HTTP header is not an option, you can also add this meta tag inside the <head> element in your markup:

<meta http-equiv="Accept-CH" content="DPR,Width,Viewport-Width"> 

That’s all we need. The browser will now append the DPR, Width and Viewport-Width headers to all subsequent requests generated from the HTML, including CSS, JavaScript and so on (with exception of Width, which, in practice, applies only to images).

Aside from images, Client Hints might be useful if the CSS file contains breakpoints based on the viewport size or device pixel ratio. Knowing the viewport size before the CSS is returned to the browser, the server can strip unqualified blocks from the CSS file before sending the response. That is another story. For now, let’s look at an example with images.

Our Old Friend, <img> Link

Imagine we have a page with the image tag below. Let’s display the flower.jpg image at a width of 200 CSS pixels.

<img src="flower.jpg" width="200"> 

With Client Hints enabled, the browser will send the following request to the server:

http headers21

With just the meta tag added, the browser appends DPR and Viewport-Width to the request. (View large version22)

The browser “hints” to the server that the requesting device has a pixel ratio of 2. As a bonus, we get the size of the viewport, too, since this is known by the browser at the time when the request is being made. Because the DPR is 2 and our page’s design need this image to be 200 pixels wide, we would like to serve an image that is 400 actual pixels wide (200 pixels × 2).

But we’re missing information about the intended display size, even if the img tag says width="200". The specification explains23 that the sizes attribute has to be set in order for the Width header to be sent. In the near future, the width attribute on the image element is likely to be included in the algorithm too, but for now, we’ll have to stick with sizes. The sizes attribute describes the layout and display size of the image. In the beginning, it might be less intimidating to think of it like the good old width attribute or like a CSS property:

<img src="flower.jpg" sizes="200px"> 

Using pixels might make it easier to “retrofit” existing markup, but using relative units24 such as vw is recommended to make the page more “responsive”:

<img src="flower.jpg" sizes="25vw"> 

Now, the request for flowers.jpg will look like this:

HTTP headers25

With sizes attribute added in addition to the meta tag, Width is added to the request. (View large version26)

The browser calculates the intended display size of the image based on the current size of the viewport and the device pixel ratio of the device in time for the preloader to fetch it. In the example above, the viewport (Viewport-Width) is 774 pixels wide . The <img> tag specifies that the image should cover 25% of the viewport size: 193.5 CSS pixels.

Because it’s a high density display, with a pixel ratio (DPR) of two, we multiply the CSS pixels by the pixel ratio and arrive at 387 actual pixels (Width). You might recognize this from how the selection process work with “regular” markup for responsive images with multiple image sources listed. The difference here is that the information is appended to the HTTP request, rather than an image source being picked from the srcset attribute.

Mind. Blown. Link

What just happened? Basically, we boiled our verbose responsive images tag down to something that looks very familiar, but with the same responsive functionality. With the pixel ratio and width information, the server can now pick, or generate, the appropriate size of the requested image.

  • The DPR header takes care of resolution switching. We don’t need srcset with x descriptors in our markup.
  • The Width header tells the server the exact width of the image (relative to the viewport) that the browser need to fit in the layout.

Actually, we don’t need srcset at all. The sizes attribute is our new hero! Based on the relative value of sizes, the browser translates this into the actual size in physical pixels. Also, remember that media conditions can be applied if you want the image to have different sizes as the width of the viewport changes:

<img src="flower.jpg" sizes="(min-width: 30em) 100vw, 50vw"> 

The Width header will, of course, reflect this, too. For a deeper dive, Jason Grigsby has written a great introduction to sizes over on Cloud Four27

But what about type? Responsive images allows you to define different formats, or mime types, of an image by using the type attribute: type="image/webp"

Client Hints does not cover this, but its older brother, the Accept header, may contain valuable information.

Accept: image/webp,image/*,*/*;q=0.8

This example is from Chrome, which is nice enough to tell us that WebP is preferred. Other browsers might just say */* which basically means, “Send me anything.” In those cases, you could apply your own rules, or, even better, the server could implement more advanced device intelligence solutions to decide the best image format to return to the client.

The Server Side of Client Hints Link

We could say that, with Client Hints, we’re moving the responsibility of selecting an image source from the browser to the server. This means, of course, that we need to implement some logic to act on the Client Hints server-side.

The bonus of involving the server is that, rather than just selecting the best match from a list of pre-generated image files like the browser does, the server can generate the perfect fit on the fly! On a small scale, this is quite achievable because we have all the information we need in the HTTP header.

However, if this task is a bit daunting and if performance is a priority, a few web services — image proxies, if you will — already support Client Hints. One of them is the free ImageEngine28. Using ImageEngine, for example, we first have to “prefix” our images with the URL of the service.

If your image src’s URL is, then we’d have to change the src to http://[key] [key] is the personal token you get when you sign up. As long as the meta tag is present and that sizes attribute is present in the image tags, we’re good to go. Looking at the response with cURL, we can see how the server responds:

$ curl -I -H "DPR: 2" -H "Width: 150" -H "Viewport-Width: 800"

HTTP/1.1 200 OK Content-Type: image/jpeg Vary: Width Content-DPR: 2 … 

The request has a DPR of 2, a Width of 150 pixels and a Viewport-Width of 800. The server then responds with the Content-DPR header, whose purpose is to confirm to the browser29 what the pixel ratio is of the returned image, so that the browser can fit it on the page correctly.

In the example above, the Content-DPR will always be the same as the DPR request header, because ImageEngine is scaling the inputted image to the exact value of Width. As a bonus, even if Width is not set, ImageEngine will fall back to Viewport-Width and then to screen size data from WURFL, a database of devices.

If you implement the server yourself, and you chose to mimic browser behavior by selecting the closest match from a set of pre-generated image sources, then the Content-DPR header might be a different number than the DPR hint from the client. The browser will make use of Content-DPR to scale the image to its display dimensions.

Also worth noting is the Vary header. The purpose of this header is to tell the client (the browser or proxy) that the response from this URI will vary according to the value of the Width header. This enables web proxies and content delivery networks to cache the image better — at least compared to caching based on the User-Agent.

Non-Supporting Browsers Link

Before you run off and start implementing support for Client Hints, you should know that not all browsers support them. The last <img> tag above will likely mess up a page viewed in a browser that does not support Client Hints. So, what are our options?

Maybe a JavaScript polyfill30? In this case, we’d have to rely on cookies, not separate HTTP headers. Cookies would create problems for content delivery networks and cache proxies because the cookie value must be included in the cache key, which would likely lead to cache pollution. Further, and more importantly, the browser’s preloader31 would not have any knowledge of the cookie’s value.

Until support for Client Hints has reached critical mass, the safest approach is to combine hints with explicit – but relative – widths and heights to make sure the layout doesn’t break. If the browser doesn’t send Client Hints, but the image server expects it, you need the layout to handle an oversized image if that is the default behavior of the image server. Moreover, to reduce the risk of serving too big an image to a non-supporting browser, an image optimization service is recommended, as described above. ImageEngine is useful because it handles mobile devices fairly well (although I’m biased here!). If a mobile device does not support Client Hints, then ImageEngine will never serve an image wider than that particular device’s screen.

Performance Link

Aside from automation, the motivation for implementing Client Hints is, of course, image performance. It’s difficult to compose a fair test case, but to give an idea of how a Client Hints-based image request performs differently than a “regular” responsive images request, I’ve put together a little demo32 with the two scenarios. Below is a table showing the bytes transferred and the actual size of the image put on the wire at different viewports. The selected image breakpoints and viewport sizes in the demo are arbitrary.

Responsive images w/srcsetClient Hints with server scaling

Viewport width KBytes (w/srcset) Actual width (pixels, w/srcset) KBytes (w/client hints) Actual width (pixels, w/client hints)
320 39.6 480 16.1 288
480 39.6 480 28.6 432
800 81.7 768 63 720
1100 138 1024 113 990
1400 138 1024 186 1260

While the preselected image breakpoints span portions of the viewport’s size, Client Hints, along with an image server capable of resizing images, addresses the continuum of viewport sizes. With Client Hints, we have surgical precision. On average, the Client Hints approach serves 19% less data. If we exclude the 1400-pixel viewport, to which the responsive images approach serves too small an image (1024 pixels), then the data served is 32% less with Client Hints, which is substantial.


Full test result can be viewed on WebPagetest34 (View large version35)

The data sample in the chart above is too small to draw any conclusions, but it illustrates the purpose of Client Hints well. No surprises there. Worth noting, though, is the use of DNS prefetching36 for the external host name Referring to the table above, the time it takes to download the bytes is as expected. Client Hints works as advertised.

(Almost) Ready For Prime Time Link

While responsive images (<img>) element with srcset and sizes) implemented in markup only allows the browser to pick the closest match from a list of image resources, Client Hints enable the web server to serve an image tailored to the browser’s needs, which in most cases mean less data and better image quality. It does require some programming if you’re implementing server-side support by yourself; luckily, some content delivery networks and web services already support it.

The future of Client Hints looks promising. Adding hints about the user’s connection and instructions to reduce data traffic are on the way37. With this information, the server can increase image compression, avoid serving high-density images or reduce the byte size of images in other ways.

As developers, we have no reason not to start exploring Client Hints right now. The key benefits are less verbose and more maintainable responsive image tags, fewer image bytes transferred and, ultimately, happier end users. Only a few steps are needed from you:

  1. add the meta tag to the head element,
  2. put the sizes attribute in your image tags.

Then make, or pick, your image server. I’ve mentioned the free ImageEngine38 optimization service above, which supports Client Hints. The best way to find other services that support Client Hints is to stay tuned and search on Google39 (duh!), because this is a new thing and more providers are announcing support as we speak.

If you want to implement support for Client Hints yourself, the article “Efficient Image Resizing With ImageMagick40” is a great start. Also, the open-source imaging service Thumbor is also considering Client Hints41.


Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41

↑ Back to top Tweet itShare on Facebook

Jon Arne Sæterås (jonarnes most places on the webs) is a mobile guy. He has been an active member and thought leader in the global mobile community since the late nineties. His dream is to make the web mobile.
Jon Arne is a developer by trade who believes that making the end user happy is the key to success. He is dedicated to building innovative technology that achieves an optimal user experience.
Jon Arne is also an occasional writer, blogger, speaker and book reviewer.

  1. 1

    This seems like a terrible idea to me, for a very simple reason: viewport size can change after the server request has happened. “Page orientation” on mobile devices is the clearer example to this. If, like you suggest in the article, you use client hints to discard some CSS based on viewport size, you have a problem when changing page orientantion or simply resizing the window in desktop browsers.

    The solution would be the request the page again everytime the viewport changes sizes. Very bad idea, sorry.

    • 2

      Client Hints used to adapt CSS is definitely not the primary use-case. Like with everything else on the web, we need to be careful with how we use our tools. Same thing with Client Hints.

    • 3

      It’s important to remember that Client Hints are exactly that: hints. They expect the browser to reason a bit about current conditions to decide whether or not to issue another image request.

      Viewport size changes are important to consider, but a minority use case. Client Hints allows for delivery of optimized assets for the 90%+ cases where the viewport will not change, and defers to the browser to handle viewport size changes.

  2. 4

    Did you make the article so long so that no one would read it? Worked for me! That’s okay I still know of the issue in details from other sources and it’s really clear this article is incredibly disingenuous.

    You like long shit? Here ya go:
    (Google fanbois should just stop reading here and personally insult me in the comments or act like a prozac bot and say something nice about Google. Either way, reading on will just either rock your world or it’ll be incomprehensible to you)

    First let get something straight:
    It’s very disingenuous to say “Even relatively simple use cases can become quite complex using the responsive images syntax”. Listing a couple alternate sources per image really isn’t that “complex” or even hard. Also there are other ways to do it that are even easier.

    Also disingenuous:
    “This enables web proxies and content delivery networks to cache the image better . . .” Do you really think they aren’t going to cache ever version of each image? And if they did, that would be “better”?
    “With Client Hints, we have surgical precision.” Now we have vague “hints” (based on “width” not “device-width” so size could change at any time from 380 wide to 4k wide.) with the other methods we have precision AND flexibility. And that’s what proper responsive web design is all about.
    Even more:
    “we have no reason not to start exploring Client Hints right now.”
    I can think of plenty foremost is already mentioned in your article. It’s only available in Google Chrome (And still only partially supported by them). Its best for us all not to waste our time on such things, ever. And since we’ll have to use our old methods on top of this, I’m sure that whomever is paying us would appreciate it if we skipped it.

    Now let’s talk about what you novel-disguised-as-an-article didn’t say:
    1- Google has a vested interest in breaking the internet
    2-This proposed “solution” works toward breaking the internet by making headers larger and more complex.
    3- Do we really want to have to teach rookie web designers about http headers?
    4-We want browser manufacturers touching headers as little as possible, not as much as possible.

    • 5

      There is a sound idea behind this article. I’d certainly like to optimize and automate some of the content coming from our CMS.

      I don’t like the idea of messing up with the HTTP headers as well. IMO much better thing to do is get the data you need whenever you connect with the client and send relevant data based on that.

    • 6

      Seriously, seriously?

      January 24, 2016 11:55 am

      You think this article and your reply are long? You must have the attention span of a pre-schooler.

    • 7

      What a tool.

  3. 8

    After the whole saga that ended with realising we need to shift the decisions to the browser with srcset… we’ve changed our minds? :-/

    • 9

      Some of us knew this was the answer from the very beginning and said at the time that the “markup way” was ridiculous. I don’t know why anybody every thought the current solution was a good idea.

    • 10

      We have not “changed our minds”.

      Client-Hints fit some situations better than srcset (e.g. automated image-only optimization), while other situations are better off handled by srcset (e.g. statically hosted sites).

      • 11

        Nah, not really. My own portfolio site is basically a static HTML page with lots of CSS and a bit of JS. The only dynamic parts are a lil bit of routing, the form mailer and the image generation. So after having worked on the new version of the site, optimized the hell out of it, I went on to the Responsive Image issue .. but: When I found out I’d have to add those horrible attribute mess to my img tags, I was like: Are you .. freaking kidding me? Thats quite … insane?!?

        So the mentioning of Client Hints came in as a big saviour, (kinda like) the metaphorical White Knight, saving the day. Knowing there is the option to use a meta-tag makes it all even better. For the non-supporting (or is it “non-supported”?) browsers I just gonna continue to use my own CSS-JS-mishmash polyfill-ish helpers. Though a bit more refined than what’s currently “in action”.

        Now, this works for a hand-crafted, 90% static (single-page) website. No more srcset “wading through that mess” nightmares. With a CMS or refined toolkit at hand, the situation might be different, ie. less complicated, because of the simple automated generation vs. hand-crafted code (eg. with WordPress, as mentioned in Smashing Magazine about a month ago).

        cu, w0lf.

  4. 12

    There might also be problems with CDNs. Still, more information on the server is… more information.

    Actually, I’ve wanted such information long time ago, but since `srcset` is here there are much better solutions. And because there is not a single great solution now, I’ve built a library that can be useful for you too –

    • 13

      Cache interaction is a challenge. Technically it is pretty straight forward, but the CDNs and cache servers out there will of course need to actually implement the proper cache strategy.

    • 14

      CDNs do present a bit of an issue because of the requirement to vary on Width. An incorrect implementation at the CDN layer leads to an explosion in cache key space and lowering hit rates, thus negating one of the major benefits of using a CDN. Thus, you need a CDN with sophisticated edge logic to handle cache spaces in an intelligent way. imgix is the only service that currently does this.

      You can read more here: Next Generation Responsive Images with Client Hints

      Disclaimer: I work for imgix.

      • 15

        Steve Kamerman

        January 25, 2016 3:16 am

        For clarification, the service mentioned in the article, ImageEngine, supports image resizing on the CDN edge via client-hints and server-side mobile device detection for devices that don’t yet have support for client hints.

        Disclaimer: I work for ScientiaMobile, the company that owns ImageEngine

  5. 16

    Andrea Ganduglia

    January 18, 2016 3:37 pm

    Client Hints is far away to become a standard, but there is a way to detect the DPR (Device Pixel Ratio) through HTTP, server side, without Javascript, for all clients that support srcset attribute.

    You need just one line of HTML and three lines in .htaccess


    • 17

      Forgive me if I am missing something but that will not give you the DPR on initial page load, only subsequent requests?

      • 18

        Andrea Ganduglia

        March 31, 2016 10:35 am

        Nop. If you use SESSION instead of COOKIE you can use DPR on the very first request.

  6. 19

    Client-hints can’t do real media queries, so comparison to the full <picture> syntax is unfair. They’re closer to just a static version of srcset, which has a quite terse syntax already.

    This feature seems to be aimed at a narrow case of CDNs that can dynamically modify served images, can find higher-resolution versions of these images, can modify <head> of the page, but can’t change the <img> tags.

    I’ve implemented Client-Hints in our company’s image server, but it turns out nobody is using it.

    Without the meta opt-in and high-DPI originals it’s not possible to automatically improve old pages, and new pages use srcset or require real art direction that doesn’t break when user resizes the window or rotates the device without clearing the cache.

  7. 20

    There are some concerns about shifting the decision logic to the server based on HTTP Header values.

    1. It will play havoc with CDNs, since they cache output without any processing logic. By vary-ing each combination of client hint headers, would effectively render CDNs useless.

    2. Inability to show new images on resize.

    3. Client-side apps still need the ability to determine the image they want to render, regardless if a server will do negotiation based on HTTP headers, so the client side html markup we already have would never go away, so seems pointless to confuse the situation with duplicate behaviour via http headers.

    P.S. What’s wrong with all the extra markup for images? Yes it’s not as pretty as a simple img tag, but what’s the fear of adding a few additional elements vs achieving a lot of additional functionality. It’s not like devices and modern bandwidth can’t handle it?

    • 21

      Thank you for commenting. WRT to CDNs it is clear that the number of cached resources will increase. How much it will increase remains to be seen, but I doubt it will lead to cache pollution. IMHO it is better to put as much of the responsibility on the caches as we can. Client Hints’ interaction with caches also specify the use of the Key header to improve cache efficiency.

      It is the responsibility of the web developer to choose the best method for displaying images. If the change-image-when-resizes use case is key, then Client Hints alone won’t do the trick. Further, it is not like Client Hints will replace the client side responsive images we’ve just learned to use. The two are very complementary and not mutually exclusive.

  8. 22

    I don’t think this is really ‘Responsive’. Isn’t this more ‘Adaptive’?

    I was hoping that this would be something that would be sent with the initial page request. Having set the headers up on the server to accept ‘Accept-CH’ I only get the headers for subsequent requests for images, JS, CSS etc., which is a shame.

    • 23

      Unfortunately the terms we use have been a bit diluted. I agree that this is more “adaptive” (or adaptive delivery or dynamic delivery, like Google calls it) because the server is adapting the content. On the other hand it is closely related to responsive images markup and the way that is implemented in the browsers.

      Regarding the Accept-CH, this should work if you set this header in the response of the initial html. At least with Chrome. Alternatively, try a meta tag.

  9. 24

    Nice hints it will helpful to the responsive designs.

  10. 25

    Thanks Jon. I for one love the simplicity here and hope for widespread browser adoption.


↑ Back to top