aboutsummaryrefslogtreecommitdiff
path: root/files/ms/learn/html/multimedia_and_embedding/responsive_images/index.html
blob: ef91b7d4789d0525da59fe852f026691e9b14f77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
---
title: Add responsive images to a webpage
slug: Learn/HTML/Multimedia_and_embedding/Responsive_images
translation_of: Learn/HTML/Multimedia_and_embedding/Responsive_images
original_slug: Learn/HTML/Howto/Add_responsive_image_to_a_webpage
---
<div class="summary">
<p><span class="seoSummary">Learn about HTML features you can use to adapt your site's images to various screen sizes and display resolutions.</span></p>
</div>

<table class="learn-box nostripe standard-table">
 <tbody>
  <tr>
   <th scope="row">Prerequisites:</th>
   <td>You should already know how to <a href="/en-US/Learn/HTML/Write_a_simple_page_in_HTML">create a basic HTML document</a> and how to <a href="https://developer.mozilla.org/en-US/Learn/HTML/Howto/Add_images_to_a_webpage">add static images to a webpage.</a></td>
  </tr>
  <tr>
   <th scope="row">Objective:</th>
   <td>Learn how to feed multiple source files to your {{htmlelement("img")}} element, so the browser can pull the right image for the occasion.</td>
  </tr>
 </tbody>
</table>

<div class="note">
<p><strong>Note:</strong> Vector images are the ultimate responsive images because the files are small while the images are scalable to any size without loss of definition. <a href="https://developer.mozilla.org/en-US/Learn/HTML/Howto/Add_vector_image_to_a_webpage">Use vector images</a> whenever you can; they're even more effective than the techniques described here. This article demonstrates how to use multiple versions of a bitmap image, in different sizes, to provide the best possible output given the current screen size and resolution.</p>

<p>Note also that while this article discusses how to implement responsive images in HTML, <a href="http://blog.cloudfour.com/responsive-images-101-part-8-css-images/">sometimes it makes more sense to use CSS</a>.</p>
</div>

<h2 id="Why_responsive_images">Why responsive images?</h2>

<p>Here's the problem we're solving:</p>

<p>On a webpage, you have a box that must be filled by an image. More precisely, the box must be filled by pixels, so many wide by so many tall. Just how many pixels wide and tall depends on your visitor's device.</p>

<p>You also have an image file, a set number of pixels wide and a set number of pixels tall. The image naturally should display in a box the same number of pixels wide and tall as the image. If the box is significantly too big, the image doesn't have enough pixels and it's going to look grainy. If the box is significantly too small, you're wasting bandwidth and slowing down your page by loading a larger image than you need.</p>

<p><em>Responsive images </em>solves this problem by letting you offer the browser several image files, all showing the same thing but containing different numbers of pixels. That way the browser can load an image that will look sharp enough but won't needlessly slow down the page.</p>

<h2 id="So_how_do_you_do_it">So how do you do it?</h2>

<p>In this section, we'll solve what is, by far, the most common problem: displaying identical image content, just larger or smaller depending on the device. In the next section, we'll look at some less common scenarios.</p>

<p>Remember the {{htmlelement("img")}} element? It lets you point the browser to a single source file:</p>

<pre class="brush: html">&lt;img src="chalet.jpg" alt="Quaint wooden cottage in the Alps"&gt;</pre>

<p>We can use two new attributes, {{htmlattrxref("srcset", "img")}} and {{htmlattrxref("sizes", "img")}} <code>sizes</code> (<strong>in addition to</strong> {{htmlattrxref("alt", "img")}} and {{htmlattrxref("src", "img")}}), to provide several additional source images and enough information to help the browser pick the right one. It looks like this when you're done:</p>

<pre class="brush: html">&lt;img
    src="chalet.jpg"
    alt="Quaint wooden cottage in the Alps"
    srcset="
        chalet-256.jpg 256w,
        chalet-512.jpg 512w,
        chalet-1024.jpg 1024w"
    sizes="
        (max-width: 500px) 100vw,
        (max-width: 900px) 40vw,
        400px"&gt;
</pre>

<p><code>srcset</code> and <code>sizes</code> each contain comma-separated lists.</p>

<p><strong>For <code>srcset</code>: </strong>Between the commas, write</p>

<ol>
 <li>an <strong>image filename</strong> (<code>chalet-256.jpg</code>)</li>
 <li>a space</li>
 <li>the image's <strong>inherent width in pixels</strong> (<code>256w</code>)</li>
</ol>

<p><strong>For <code>sizes</code>: </strong>Between the commas, write</p>

<ol>
 <li>a <strong>media condition</strong> (<code>(max-width:500px)</code>)</li>
 <li>a space</li>
 <li>the <strong>width of the slot</strong> the image will fill when the media condition is true (<code>100vw</code>)</li>
</ol>

<div class="note">
<ul>
 <li>For the slot width, you may provide an absolute length (<code>px</code>, <code>em</code>) or a relative length (<code>vw</code>, that is, percent of viewport width). You may also provide a combination using {{cssxref("calc")}}.</li>
 <li>The last slot width is the default (for when no media condition is true). Therefore, the last slot width has <strong>no</strong> media condition.</li>
 <li><code>max-width</code> simply means, "if the user's screen is no wider than X pixels".</li>
 <li>The browser ignores everything after the first matching condition. Pay attention to the order of the media conditions.</li>
</ul>
</div>

<div class="note">
<p><strong>Why can't the browser just look at the CSS to find out the width of the image slot? </strong></p>

<p>Because the browser's preloader starts downloading images before the main parser has a chance to interpret CSS and JavaScript. You want that, because images are heavy and circumventing the preloader may add another 20% on to your page load time.</p>
</div>

<h2 id="Advanced_scenarios">Advanced scenarios</h2>

<h3 id="Images_at_different_resolutions_but_one_real-world_size">Images at different resolutions but one real-world size</h3>

<p>If you're supporting multiple display densities, but everyone sees your image at the same real-world size, you should use <code>srcset</code> with x-descriptors and without <code>sizes</code>:</p>

<pre class="brush: html">&lt;img
    src="chalet.jpg"
    alt="Quaint wooden cottage in the Alps"
    srcset="chalet.jpg,
        chalet-1-5x.jpg 1.5x,
        chalet-2x.jpg 2x,
        chalet-3x.jpg 3x"&gt;
</pre>

<div class="note">
<ul>
 <li>
  <p>Note that <code>1x</code> is implied.</p>
 </li>
 <li>
  <p><code>x</code> means, "this many device pixels for one CSS pixel"</p>
 </li>
</ul>
</div>

<h3 id="Art_direction">Art direction</h3>

<p><strong>Art direction</strong> means cropping an image either 1) to make the main subject easier to see when the image is small or 2) to make a landscape image suitable for a portrait slot (and vice versa). (However, it must be the same image content in all cases. To, say, show phone users a jet and desktop users a ladybug is a misuse of the responsive image mechanism.)<br>
 Art direction is a more complex problem, and needs a more complex solution: the {{htmlelement("picture")}} element. <code>&lt;picture&gt;</code> is a wrapper containing several {{htmlelement("source")}} elements, followed by the all-important {{htmlelement("img")}} element:</p>

<pre class="brush: html">&lt;picture&gt;
    &lt;source
        media="(min-width: 1000px)"
        srcset="chalet-desktop.jpg"&gt;
    &lt;source
        media="(min-width: 700px)"
        srcset="chalet-tablet.jpg"&gt;
    &lt;img src="chalet-phone.jpg" alt="Quaint wooden cottage in the Alps"&gt;
&lt;/picture&gt;
</pre>

<ul>
 <li>Just like <code>&lt;img&gt;</code>, <code>&lt;source&gt;</code> can take <code>srcset</code> and <code>sizes</code>. In a responsive images scenario, do not use <code>&lt;source&gt;</code> and <code>src</code> together.</li>
 <li><code>&lt;source&gt;</code> may also take a <code>media</code> attribute containing a CSS <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries">media query</a>. Use <code>media</code> only in an art direction scenario, because it leaves the browser no choice of which image to use. When you do use <code>media</code>, don't offer media conditions within <code>sizes</code>.</li>
 <li><strong>In all cases, you must provide an <code>&lt;img&gt;</code> element, with <code>src</code> and <code>alt</code>, right before <code>&lt;/picture&gt;</code>, otherwise no images will appear.</strong></li>
</ul>

<h3 id="Use_modern_image_formats_boldly">Use modern image formats boldly</h3>

<p>There are several exciting new image formats (think WebP and JPEG-2000) that can maintain a low file size and high quality at the same time. However, browser support is spotty.</p>

<p><code>&lt;picture&gt;</code> lets us continue catering to older browsers. Supply MIME types inside <code>type</code> attributes so the browser can immediately reject unsupported file types:</p>

<pre class="brush: html">&lt;picture&gt;
  &lt;source type="image/svg+xml" srcset="pyramid.svg"&gt;
  &lt;source type="image/webp" srcset="pyramid.webp"&gt;
  &lt;img src="pyramid.png" alt="regular pyramid built from four equilateral triangles"&gt;
&lt;/picture&gt;
</pre>

<ul>
 <li>Do <em>not </em>use the <code>media</code> attribute, unless you also need art direction.</li>
 <li>In a <code>&lt;source&gt;</code> element, you can only refer to images of the type declared in <code>type</code>.</li>
 <li>As before, you're welcome to use comma-separated lists with <code>srcset</code> and <code>sizes</code>, as needed.</li>
</ul>

<h2 id="Learn_more">Learn more</h2>

<ul>
 <li><a href="http://blog.cloudfour.com/responsive-images-101-definitions">Jason Grigsby's excellent introduction to responsive images</a></li>
 <li>{{htmlelement("img")}}</li>
 <li>{{htmlelement("picture")}}</li>
 <li>{{htmlelement("source")}}</li>
 <li><a href="http://responsiveimages.org/">Responsive Images Community Group</a></li>
</ul>