• Stars
    star
    401
  • Rank 103,596 (Top 3 %)
  • Language
    Ruby
  • Created over 11 years ago
  • Updated about 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Development of this specification has moved to the HTTPWG repository. For latest drafts and issue discussions, head to:


HTTP Client Hints Explainer

This specification defines a set of HTTP request header fields, colloquially known as Client Hints, that are intended to be used as input to proactive content negotiation; just as the Accept header allows clients to indicate what formats they prefer, Client Hints allow clients to indicate a list of device and agent specific preferences.


Available hints

Current list includes DPR (device pixel ratio), Width (resource width), Viewport-Width (layout viewport width), and Downlink (maximum downlink speed) request headers, and Content-DPR response header that is used to confirm the DPR of selected image resources - see full definitions in latest spec.

Note: have a proposal for another hint? Open an issue, document your use case.

Opt-in hint delivery

To reduce request overhead the hints are sent based on opt-in basis: the server advertises supported hints, the user agent sends the appropriate hint request headers for subsequent requests - see Advertising Support for Client Hints.

Note that this means that the user agent will not send hints on the very first request. However, if the site provides correct opt-in information in the response, hints will be delivered by all subsequent requests. Also, the user agent may remember site opt-in across browsing sessions, enabling hint delivery of all subsequent requests.

Use cases

Responsive Design + Server Side Components (RESS)

The application may want to deliver alternate set of optimized resources based on advertised hints. For example, it may use the device pixel ratio (DPR), or the layout viewport width (Viewport-Width) to respond with optimized HTML markup, CSS, or script resources - see Responsive Design + Server Side Components (RESS).

Note: Applications that use this approach must also serve appropriate Vary and Cache-Control response headers to ensure correct delivery of optimized assets.

<img> element

Delivering DPR-aware images

DPR hint automates device-pixel-ratio-based selection and enables delivery of optimal image variant without any changes in markup. For example, given the following HTML markup:

<img src="img.jpg" alt="I'm a DPR-aware image!">

The client and server can negotiate the appropriate resolution of img.jpg via HTTP negotiation:

GET /img.jpg HTTP/1.1
User-Agent: Awesome Browser
Accept: image/webp, image/jpg
DPR: 2.0
HTTP/1.1 200 OK
Server: Awesome Server
Content-Type: image/jpg
Content-Length: 124523
Vary: DPR
Content-DPR: 2.0

(image data)

In the above example, the user agent advertises its device pixel ratio via DPR request header on the image request. Given this information, the server is able to select and respond with the optimal resource variant for the client. For full details refer to the latest spec.

Note: when server side DPR-selection is used the server must confirm the DPR of the selected resource via Content-DPR response header to allow the user agent to compute the correct intrinsic size of the image.

Delivering DPR and resource width aware images

If the image resource width is known at request time, the user agent can communicate it to the server to enable selection of an optimized resource. For example, given the following HTML markup:

<img src="img.jpg" width="160" alt="I'm a DPR and width aware image!">

The client and server can negotiate an optimized asset based on DPR and Width request hints:

GET /img.jpg HTTP/1.1
User-Agent: Awesome Browser
Accept: image/webp, image/jpg
DPR: 2.0
Width: 320
HTTP/1.1 200 OK
Server: Awesome Server
Content-Type: image/jpg
Content-Length: 124523
Vary: Width
Content-DPR: 2.0

(image data)

In the above example, the user agent advertises its device pixel ratio and image resource width via respective DPR and Width headers on the image request. Given this information, the server is able to select and respond with the optimal resource variant for the client:

  • The server can scale the asset to requested width, or return the closest available match to help reduce number of transfered bytes.
  • The server can factor in the device pixel ratio of the device in its selection algorithm.

Note that the width of the image may not be available at request time, in which case the user agent would omit the Width hint. Also, the exact logic as to which asset is selected is deferred to the server, which can optimize its selection based on available resources, cache hit rates, and other criteria.

<picture> element

Client Hints can be used alongside picture element to automate resolution switching, simplify art-direction, and automate delivery of variable-sized images.

Device-pixel-ratio-based selection

DPR header automates device-pixel-ratio-based selection by eliminating the need to write x descriptors for img and picture elements:

<!-- picture resolution switching -->
<picture>
  <source srcset="pic1x.jpg 1x, pic2x.jpg 2x, pic4x.jpg 4x">
  <img alt="A rad wolf." src="pic1x.jpg">
</picture>

<!-- alternative and equivalent syntax -->
<img src="pic1x.jpg" srcset="pic2x.jpg 2x, pic4x.jpg 4x" alt="A rad wolf.">

<!-- equivalent functionality with DPR hint -->
<img alt="A rad wolf." src="pic.jpg">

<!-- ... similarly ... -->

<!-- picture art-direction with resolution switching -->
<picture>
  <source media="(min-width: 45em)" srcset="large-1.jpg, large-2.jpg 2x">
  <source media="(min-width: 18em)" srcset="med-1.jpg, med-2.jpg 2x">
  <img src="small-1.jpg" srcset="small-2.jpg 2x" alt="The president giving an award." width="500" height="500">
</picture>

<!-- equivalent functionality with resolution switching with Client Hints -->
<picture>
  <source media="(min-width: 45em)" srcset="large.jpg">
  <source media="(min-width: 18em)" srcset="med.jpg">
  <img src="small.jpg" alt="The president giving an award." width="500" height="500">
</picture>

Note that the second example with art direction-based selection illustrates that hints do not eliminate the need for the picture element. Rather, Client Hints is able to simplify and automate certain parts of the negotiation, allowing the developer to focus on art direction, which by definition requires developer/designer input.

Device-pixel-ratio and viewport-based selection

The combination of DPR and Width hints also simplifies delivery of variable sized images when viewport-based selection is used. The developer specifies the resource width of the image in vw units (which are relative to viewport width) via sizes attribute and the user agent handles the rest:

<!-- viewport-based selection -->
<img src="wolf-400.jpg" sizes="100vw" alt="The rad wolf"
     srcset="wolf-400.jpg 400w, wolf-800.jpg 800w, wolf-1600.jpg 1600w">

<!-- equivalent functionality with DPR and Width hints -->
<img src="wolf.jpg" sizes="100vw" alt="The rad wolf">
  • Device pixel ratio is communicated via the DPR request header
  • The vw size is converted to physical px size based on client's layout viewport size and the resulting value is communicated via the Width request header
  • The server computes the optimal image variant based on communicated DPR and Width values and responds with the optimal image variant.

HTTP negotiation flow for the example above:

> GET /wolf.jpg HTTP/1.1
> DPR: 2.0
> Width: 800

< 200 OK
< Content-DPR: 2.0
< Vary: Width
< ...

In situations where multiple layout breakpoints impact the image's dimensions the workflow is similar to that of the previous example:

<!-- multiple layout breakpoints -->
<img src="swing-400.jpg" alt="Kettlebell Swing"
  sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)"
  srcset="swing-200.jpg 200w, swing-400.jpg 400w, swing-800.jpg 800w, swing-1600.jpg 1600w">

<!-- equivalent functionality with DPR and Width hints -->
<img src="swing.jpg" alt="Kettlebell Swing"
  sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw,calc (33vw - 100px)">

The combination of the DPR and Width hints allows the server to deliver 'pixel perfect' images that match the device resolution and exact display size. However, the server is not required to do so: it can round or bin the advertised values based on own logic and serve the closest matching resource - just as srcset picks the nearest resource based on the provided parameters in the markup.

Resource selection

When request hints are used the resource selection algorithm logic is shared between the user agent and the server: the user agent may apply own selection rules based on specified markup and defer other decisions to the server by communicating the appropriate DPR and Width values within the image request. With that, a few considerations to keep in mind:

  • The device pixel ratio and the resource width may change after the initial image request was sent to the server - e.g. layout change, desktop zoom, etc. When this occurs, and if resource selection is done via sizes or srcset attributes, the decision to initiate a new request is deferred to the user agent: it may send a new request advertising new hint values, or it may choose to reuse and rescale the existing asset. Note that this is the default behavior of the user agent - i.e. the user agent is not required to initiate a new request and use of hints does not modify this behavior.
  • For cases where an environment change (layout, zoom, etc.) must trigger a new asset download, you should use art-direction with source and appropriate media queries.

Use of Client Hints does not incur additional or unnecessary requests. However, as an extra optimization, the server should advertise the Key caching header to improve cache efficiency.

Maximum downlink speed

The application may want to deliver an alternate set of resources (e.g. - alternate image asset, stylesheet, HTML document, media stream, and so on) based on the maximum downlink (Downlink) speed of the client, as defined by the downlinkMax attribute in the W3C Network Information API.

Hands-on example

A hands-on example courtesy of resrc.it:

# Request 100 CSS px wide asset with DPR of 1.0
$> curl -s http://app.resrc.it/http://www.resrc.it/img/demo/preferred.jpg \
  -o /dev/null -w "Image bytes: %{size_download}\n" \
  -H "DPR: 1.0" -H "Width: 100"
Image bytes: 9998

# Request 100 CSS px wide asset with DPR of 1.5
$> curl -s http://app.resrc.it/http://www.resrc.it/img/demo/preferred.jpg \
  -o /dev/null -w "Image bytes: %{size_download}\n" \
  -H "DPR: 1.5" -H "Width: 150"
Image bytes: 17667

# Request 200 CSS px wide asset with DPR of 1.0
$> curl -s http://app.resrc.it/http://www.resrc.it/img/demo/preferred.jpg \
  -o /dev/null -w "Image bytes: %{size_download}\n" \
  -H "DPR: 1.0" -H "Width: 200"
Image bytes: 28535

ReSRC.it servers automate the delivery of optimal image assets based on advertised DPR and Width hint values and append the correct caching header (Vary: DPR, Width), which allows the asset to be cached on the client and by any Vary-capable intermediaries.

Implementation status

Feedback

Please feel free to open a new issue, or send a pull request!

More Repositories

1

videospeed

HTML5 video speed controller (for Google Chrome)
JavaScript
3,654
star
2

ga-beacon

Google Analytics collector-as-a-service (using GA measurement protocol).
Go
3,527
star
3

gharchive.org

GH Archive is a project to record the public GitHub timeline, archive it, and make it easily accessible for further analysis.
Ruby
2,567
star
4

em-websocket

EventMachine based WebSocket server
Ruby
1,690
star
5

decisiontree

ID3-based implementation of the ML Decision Tree algorithm
Ruby
1,414
star
6

em-http-request

Asynchronous HTTP Client (EventMachine + Ruby)
Ruby
1,216
star
7

em-synchrony

Fiber aware EventMachine clients and convenience classes
Ruby
1,040
star
8

http-2

Pure Ruby implementation of HTTP/2 protocol
Ruby
876
star
9

bugspots

Implementation of simple bug prediction hotspot heuristic
Ruby
841
star
10

agent

Agent is an attempt at modelling Go-like concurrency, in Ruby
Ruby
729
star
11

em-proxy

EventMachine Proxy DSL for writing high-performance transparent / intercepting proxies in Ruby
Ruby
664
star
12

vimgolf

Real Vim ninjas count every keystroke - do you?
Ruby
632
star
13

node-spdyproxy

SPDY forwarding proxy - fast and secure
JavaScript
528
star
14

bloomfilter-rb

BloomFilter(s) in Ruby: Native counting filter + Redis counting/non-counting filters
C
468
star
15

async-rails

async Rails 3 stack demo
Ruby
467
star
16

hackernews-button

Embeddable Hacker News button + vote counter for your site
Go
417
star
17

istlsfastyet.com

Is TLS fast yet? Yes, yes it is.
HTML
417
star
18

spdy

SPDY is a protocol designed to reduce latency of web pages
Ruby
317
star
19

hpbn.co

High Performance Browser Networking (O'Reilly)
HTML
286
star
20

webp-detect

WebP with Accept negotiation
C++
242
star
21

zeroconf-router

Zero-config reverse proxies: let's get there!
Ruby
205
star
22

autoperf

Ruby driver for httperf - automated load and performance testing
Ruby
179
star
23

PubSubHubbub

Asynchronous PubSubHubbub Ruby Client
Ruby
174
star
24

heroku-buildpack-dart

Heroku buildpack for Dart
Shell
166
star
25

rack-speedtracer

SpeedTracer middleware for server side debugging
Ruby
156
star
26

textquery

Evaluate any text against a collection of match rules
Ruby
145
star
27

tokyo-recipes

Lean & mean Tokyo Cabinet recipes (with Lua)
Lua
144
star
28

slowgrowl

Surface slow code paths in your Rails 3 app via Growl
Ruby
117
star
29

mneme

Mneme is an HTTP web-service for recording and identifying previously seen records - aka, duplicate detection.
Ruby
108
star
30

RRRDTool

Round robin database pattern via Redis sorted sets
Ruby
79
star
31

pregel

Single-node implementation of Google's Pregel framework for graph processing.
Ruby
72
star
32

gmetric

Pure Ruby interface for generating Ganglia gmetric packets
Ruby
70
star
33

rack-aggregate

Rack response-time statistics aggregator middleware
Ruby
67
star
34

em-jack

An Evented Beanstalk Client
Ruby
65
star
35

rb-pagerank

Code from RailsConf '09 pres: Building Mini Google in Ruby
Ruby
54
star
36

closure-sprockets

Sprockets processor for Google's Closure tools
Python
54
star
37

netinfo-monitor

Displays network quality as reported by Network Information API.
JavaScript
48
star
38

shopify-core-web-vitals

This embedded app provides a report on how real-world Google Chrome users experience the Shopify-powered storefront, as captured by the Chrome UX Report, and enables the site owner to benchmark their site against a custom list of competitors.
Ruby
48
star
39

libsnappy

Snappy, a fast compressor/decompressor (courtesy of Google)
Ruby
45
star
40

hydra5

Load-balanced (multi-headed) SOCKS5 proxy
Ruby
42
star
41

zdevice

ZDevice is a Ruby DSL for assembling ZeroMQ routing devices, with support for the ZDCF configuration syntax
Ruby
42
star
42

ruby2lolz

Ruby to Lolcode translator, kthnxbai.
Ruby
38
star
43

bmr-wordcount

Browser Map-Reduce: distributed word count example
Ruby
33
star
44

em-socksify

Transparent proxy support for any EventMachine protocol
Ruby
32
star
45

resource-hints

Moved to...
JavaScript
32
star
46

gitter

XML history generator for CodeSwarm
31
star
47

em-handlersocket

EventMachine HandlerSocket MySQL plugin for direct read/write of InnoDB tables
Ruby
29
star
48

canicrawl

Hosted robots.txt permissions verifier
Go
23
star
49

udacity-webperf

JavaScript
17
star
50

omnipipe

web pipes for your browser's omnibar!
Ruby
12
star
51

issue-tracker

W3C webperf issue tracker
JavaScript
11
star
52

contextual

runtime contextual HTML autoescaper
Ruby
10
star
53

presentations

Slides, notes, code examples from some of the bigger conferences & talks.
9
star
54

performance-observer

JavaScript
7
star
55

libgeohash

Ruby FFI wrapper for libgeohash
Ruby
7
star
56

ImageQuote

Convert text quotes to images
Ruby
7
star
57

resourcehints.info

HTML
2
star
58

igrigorik

1
star