-
Notifications
You must be signed in to change notification settings - Fork 117
/
demo.html
279 lines (177 loc) · 15 KB
/
demo.html
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>progressive-image.js</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="src/demo.css">
<link rel="stylesheet" href="src/css/progressive-image.css">
<script src="src/js/progressive-image.js" async></script>
</head>
<body>
<main>
<article>
<h1>progressive-image.js</h1>
<p><a href="https://github.com/craigbuckler/progressive-image.js"><strong>GitHub</strong></a> | <a href="https://www.npmjs.com/package/progressive-image.js"><strong>npm</strong></a> | <a href="https://gum.co/vIjey"><strong>donate</strong></a> | <a href="https://twitter.com/craigbuckler">@craigbuckler</a> | <a href="https://craigbuckler.com/">craigbuckler.com</a></p>
<p><a href="https://github.com/craigbuckler/progressive-image.js"><code>progressive-image.js</code></a> implements a progressively-loaded image effect similar to those seen on <a href="https://code.facebook.com/posts/991252547593574/the-technology-behind-preview-photos/">Facebook</a> and <a href="https://jmperezperez.com/medium-image-progressive-loading-placeholder/">Medium</a>. A very small blurred image is replaced with the full-resolution equivalent when the element is scrolled into view. See <a href="https://www.sitepoint.com/how-to-build-your-own-progressive-image-loader/">How to Build Your Own Progressive Image Loader</a> for information about how it was initially developed.</p>
<p>Please use the code as you wish. <a href="https://twitter.com/craigbuckler">Tweet me @craigbuckler</a> if you find it useful and consider <a href="https://gum.co/vIjey">donating toward development</a>.</p>
<a href="https://res.cloudinary.com/oworks/image/upload/f_auto/v1593762372/pimage/iceland" data-srcset="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_400/v1593762372/pimage/iceland 400w, https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_800/v1593762372/pimage/iceland 800w, https://res.cloudinary.com/oworks/image/upload/f_auto/v1593762372/pimage/iceland 1600w" class="primary progressive replace">
<img src="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_32/v1593762372/pimage/iceland" class="preview" loading="lazy" width="32" height="8" alt="Iceland" />
</a>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="#benefits">benefits</a></li>
<li><a href="#basic">basic example</a></li>
<li><a href="#native">native lazy-loading</a></li>
<li><a href="#link">retain the link</a></li>
<li><a href="#container">alternative container elements</a></li>
<li><a href="#responsive">responsive images (<code>srcset</code> and <code>sizes</code>)</a></li>
<li><a href="#reveal">custom reveal effects</a></li>
<li><a href="#background">CSS background images</a></li>
<li><a href="#notes">usage notes</a></li>
</ol>
<h2 id="benefits">Benefits</h2>
<a href="https://res.cloudinary.com/oworks/image/upload/f_auto/v1593769674/pimage/jump" class="boxout2 progressive replace">
<img src="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_20/v1593769674/pimage/jump" class="preview" loading="lazy" width="20" height="15" alt="jump" />
</a>
<ul>
<li>saves unnecessary bandwidth</li>
<li>fast loading, high performance, images loaded on view</li>
<li>supports any image type (JPEG photographs are most appropriate)</li>
<li>supports <a href="#responsive">responsive images</a> (<code>srcset</code> and <code>sizes</code> attributes)</li>
<li>supports <a href="#background">CSS background images</a></li>
<li>supports <a href="#native">native lazy loading and aspect ratios</a></li>
<li>lightweight: 1,407 bytes of JavaScript, 407 bytes of optional CSS (minified)</li>
<li>any <a href="#reveal">CSS reveal effect</a> can be applied</li>
<li>no external dependencies – works with any framework</li>
<li>makes up to three attempts if images fail to download</li>
<li>works in all modern browsers (IE10+)</li>
<li>progressively-enhanced to work in older browsers</li>
<li>easy to use</li>
</ul>
<a href="https://res.cloudinary.com/oworks/image/upload/f_auto/v1593770219/pimage/canoe" class="boxout1 progressive replace">
<img src="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_20/v1593770219/pimage/canoe" class="preview" loading="lazy" width="20" height="15" alt="canoe" />
</a>
<p>The preview image can be very small – perhaps 20px in width and saved with high JPEG compression. This typically results in an image less than 500 bytes in size. It be added to the page directly or inlined as a base-64 data URI.</p>
<p>The large image can be any size but it <strong>must match the preview image's aspect ratio</strong>. For example, a preview image of 20x15 could be used for large image sizes including 200x150, 400x300, 1600x1200, etc.</p>
<p><em>The page layout will re-layout and jump if differing aspect ratios are used.</em></p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="basic">Basic example</h2>
<p>The page must load the CSS and JavaScript. It can be placed anywhere on the page but as early as possible in <code><head></code> is ideal:</p>
<pre><code><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/progressive-image.js/dist/progressive-image.css">
<script src="https://cdn.jsdelivr.net/npm/progressive-image.js/dist/progressive-image.js" defer></script></code></pre>
<p>CDN URLs are shown above but you can also use <a href="https://www.npmjs.com/package/progressive-image.js"><code>npm</code></a> and a bundler:</p>
<pre><code>npm i progressive-image.js</code></pre>
<p>To use the lazy loading effect:
<ol>
<li>add an <code><img></code> tag for the <strong>small image</strong> with a class of <code>preview</code></li>
<li>surround it with <code><a></code> link to the <strong>large image</strong> and add both <code>progressive replace</code> as classes</li>
</ol>
<p>Example:</p>
<pre><code><a href="full.jpg" class="progressive replace">
<img src="tiny.jpg" class="preview" alt="image" />
</a></code></pre>
<p><strong>The preview and full-size images must have the same aspect ratio</strong>, e.g. 40x30 and 800x600.</p>
<p>The full image is revealed when the preview is scrolled into view. CSS3 effects are used to fade and zoom the image:</p>
<a href="https://res.cloudinary.com/oworks/image/upload/f_auto/v1593771256/pimage/squirrel" class="full progressive replace">
<img src="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_20/v1593771256/pimage/squirrel" class="preview" loading="lazy" width="20" height="15" alt="squirrel" />
</a>
<p>After replacement, link-clicking is disabled and the HTML becomes:</p>
<pre><code><a href="full.jpg" class="progressive">
<img src="full.jpg" alt="image" />
</a></code></pre>
<p>Any <code>class</code> names applied to the preview image are applied to the full image (except <code>preview</code>).</p>
<p>If JavaScript or image loading fails, a blurred version of the preview image can be clicked to view the full image:</p>
<a href="https://res.cloudinary.com/oworks/image/upload/f_auto/v1593771256/pimage/squirrel" class="full progressive">
<img src="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_20/v1593771256/pimage/squirrel" class="preview" loading="lazy" width="20" height="15" alt="squirrel" />
</a>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="native">Native lazy-loading</h2>
<p>To improve performance, add <code>width</code>, <code>height</code>, and <code>loading="lazy"</code> attributes to the <strong>preview image</strong>:</p>
<pre><code><img src="tiny.jpg" class="preview"
width="20" height="15"
loading="lazy"
alt="image"
/></code></pre>
<p>Modern browsers will set the correct aspect ratio and load the preview image shortly before it is scrolled into view.</p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="link">Retain the link</h2>
<p>If you require a responsive image to remain a real link, set the <code>href</code> to the link address and add a <code>data-href</code> attribute with the large image URL:</p>
<pre><code><a href="http://site.com/"
data-href="full.jpg"
class="progressive replace">
<img src="tiny.jpg" class="preview" alt="image" />
</a></code></pre>
<p><em>Users will not be able to view the full image if downloading or JavaScript fails.</em></p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="container">Alternative container elements</h2>
<p>If necessary, most HTML container elements can be used with a <code>data-href</code> attribute rather than a link, e.g.</p>
<pre><code><figure data-href="full.jpg" class="progressive replace">
<img src="tiny.jpg" class="preview" alt="image" />
</figure></code></pre>
<p>Exceptions include <code><picture></code>, <code><video></code>, <code><audio></code>, and <code><iframe></code>. These are inappropriate and may cause unexpected browser behavior.</p>
<p><em>Users will not be able to view the full image if downloading or JavaScript fails.</em></p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="responsive">Responsive images</h2>
<p><a href="https://www.sitepoint.com/how-to-build-responsive-images-with-srcset/">Responsive images</a> of differing sizes can be defined in the container link/element using <code>data-srcset</code> and <code>data-sizes</code> attributes. These correspond to the standard <code>srcset</code> and <code>sizes</code> attributes, e.g.</p>
<pre><code><a href="small.jpg"
data-srcset="small.jpg 800w, large.jpg 1200w"
data-sizes="100vw"
class="progressive replace">
<img src="preview.jpg" class="preview" alt="image" />
</a></code></pre>
<p><em>(carriage returns added to aid legibility)</em></p>
<p>On replacement, the image code is transformed to:</p>
<pre><code><img src="small.jpg"
srcset="small.jpg 800w, large.jpg 1200w"
sizes="100vw"
alt="image" /></code></pre>
<p>Modern browsers will load large.jpg when the viewport width is 800px or greater.</p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="reveal">Custom reveal effects</h2>
<p>A class of <code>reveal</code> is applied to the full image when it is placed on the page. This starts a 1 second CSS3 animation named <code>progressiveReveal</code>:</p>
<pre><code>.progressive img.reveal {
animation: progressiveReveal 1s linear;
}
@keyframes progressiveReveal {
0% { transform: scale(1.05); opacity: 0; }
100% { transform: scale(1); opacity: 1; }
}</code></pre>
<p>This code can be changed or overridden with alternative animations, perhaps by applying another class to the container element.</p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="background">CSS background images</h2>
<p><code>progressive-image.js</code> can lazy-load CSS background images.</p>
<p>However, it is not best-suited to that task and CSS3 animations cannot be applied. You will get better results using a real <code><img></code> rendered below other content and maximized with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit"><code>object-fit: cover</code></a>.</p>
<div class="full bgimg progressive replace">CSS background image</div>
<p>Example HTML:</p>
<pre><code><div class="bgimg progressive replace">content</div></code></pre>
<p>Any CSS selector can be used – a <code>bgimg</code> class has been added here. Set the full-size image in your CSS as normal, e.g.</p>
<pre><code>.bgimg {
background: url(large.jpg) 50% 50% no-repeat;
background-size: cover;
}</code></pre>
<p>then add a <code>.replace</code> definition with the smaller preview image:</p>
<pre><code>.bgimg.replace {
background-img: url(tiny.jpg);
}</code></pre>
<p><code>tiny.jpg</code> is replaced with <code>large.jpg</code> as soon as the element appears in the viewport. If necessary, media queries can be used to load appropriately-sized images.</p>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2 id="notes">Usage notes</h2>
<p>Thanks for trying <a href="https://github.com/craigbuckler/progressive-image.js/"><code>progressive-image.js</code></a> and please <a href="https://github.com/craigbuckler/progressive-image.js/issues/">report any issues</a> you encounter.</p>
<ol>
<li>The code works in all browsers from IE10 and above. IE10/11 will not smoothly blur the preview image. Older browsers fallback to click-to-view.</li>
<li>The code cannot be used for <a href="https://developer.mozilla.org/Web/HTML/Element/picture">art direction</a> where different images with different aspect ratios are requested according to the dimensions and/or orientation of a device using <code><picture></code> and <code><source></code> elements.</li>
<li>Only vertical scrolling is checked. All images in the horizontal plane will be loaded – it may not be suitable for carousels.</li>
<li>Progressive images dynamically added to the page using JavaScript are handled if a navigation event occurs or the browser supports <code>MutationObserver</code>.</li>
<li>Actual or perceived performance may be improved using an SVG preview image or <a href="https://css-tricks.com/data-uris/">inlined data URIs</a>.</li>
</ol>
<p class="top"><a href="#contents">back to contents…</a></p>
<h2>Image credit</h2>
<p>Images in this demonstration have been sourced from <a href="https://unsplash.com/">unsplash.com</a> and are credited to Matt Palmer, Joshua Gaunt, Viktor Jakovlev, Caleb Martin, & Red Zepplin.</p>
<a href="https://res.cloudinary.com/oworks/image/upload/f_auto/v1593773543/pimage/exmouth" data-srcset="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_400/v1593773543/pimage/exmouth 400w, https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_800/v1593773543/pimage/exmouth 800w, https://res.cloudinary.com/oworks/image/upload/f_auto/v1593773543/pimage/exmouth 1600w" class="primary progressive replace">
<img src="https://res.cloudinary.com/oworks/image/upload/f_auto,c_scale,w_32/v1593773543/pimage/exmouth" class="preview" loading="lazy" width="32" height="8" alt="Exmouth" />
</a>
</article>
</main>
</body>
</html>