Skip to content

Commit 20ad471

Browse files
jonathantnealromainmenke
authored andcommitted
Sort images by DPR and use the lowest as the default
1 parent da3f4a6 commit 20ad471

File tree

5 files changed

+51
-188
lines changed

5 files changed

+51
-188
lines changed

plugins/postcss-image-set-function/README.md

+19-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ specification.
2121
2222
/* becomes */
2323
24-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
25-
.example {
26-
background-image: url(img.png);
27-
}
24+
.example {
25+
background-image: url(img.png);
2826
}
2927
3028
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
@@ -228,6 +226,23 @@ postcssImageSetFunction({ oninvalid: 'warning' }) // warn on invalid usages
228226
postcssImageSetFunction({ oninvalid: 'throw' }) // throw on invalid usages
229227
```
230228

229+
## Image Resolution
230+
231+
The `image-set()` function allows an author to provide multiple resolutions of
232+
an image and let the browser decide which is most appropriate in a given
233+
situation. The `image-set()` also never fails to choose an image; the
234+
`<resolution>` just helps determine which of the images is chosen.
235+
236+
Since this plugin is not a browser, the image options are sorted by device
237+
pixel ratio and the lowest ratio is used as the default, while the remaining
238+
images are pushed behind media queries.
239+
240+
Therefore, this plugin can only approximate native browser behavior. While
241+
images should typically match the resolution as the device they’re being viewed
242+
in, other factors can affect the chosen image. For example, if the user is on a
243+
slow mobile connection, the browser may prefer to select a lower-res image
244+
rather than wait for a larger, resolution-matching image to load.
245+
231246
[cli-img]: https://img.shields.io/travis/jonathantneal/postcss-image-set-function.svg
232247
[cli-url]: https://travis-ci.org/jonathantneal/postcss-image-set-function
233248
[css-img]: https://cssdb.org/badge/image-set-function.svg

plugins/postcss-image-set-function/lib/get-media.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import postcss from 'postcss';
33
const dpiRatios = { dpcm: 2.54, dpi: 1, dppx: 96, x: 96 };
44

55
// return a valid @media rule
6-
export default (node, mediasByDpi) => {
6+
export default (node, mediasByDpr) => {
77
if (Object(node).type === 'number' && node.unit in dpiRatios) {
88
// calculate min-device-pixel-ratio and min-resolution
99
const dpi = Number(node.value) * dpiRatios[node.unit.toLowerCase()];
10-
const pxRatio = Math.floor(dpi / dpiRatios.x * 100) / 100;
10+
const dpr = Math.floor(dpi / dpiRatios.x * 100) / 100;
1111

12-
if (dpi in mediasByDpi) {
12+
if (dpi in mediasByDpr) {
1313
return false;
1414
} else {
15-
const media = mediasByDpi[dpi] = postcss.atRule({
15+
const media = mediasByDpr[dpi] = postcss.atRule({
1616
name: 'media',
17-
params: `(-webkit-min-device-pixel-ratio: ${pxRatio}), (min-resolution: ${dpi}dpi)`
17+
params: `(-webkit-min-device-pixel-ratio: ${dpr}), (min-resolution: ${dpi}dpi)`
1818
});
1919

2020
return media;

plugins/postcss-image-set-function/lib/process-image-set.js

+23-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import handleInvalidation from './handle-invalidation';
55

66
export default (imageSetOptionNodes, decl, opts) => {
77
const parent = decl.parent;
8-
const mediasByDpi = {};
8+
const mediasByDpr = {};
99

1010
let length = imageSetOptionNodes.length;
1111
let index = -1;
@@ -14,7 +14,7 @@ export default (imageSetOptionNodes, decl, opts) => {
1414
const [comma, value, media] = [
1515
index < 0 ? true : getComma(imageSetOptionNodes[index]),
1616
getImage(imageSetOptionNodes[index + 1]),
17-
getMedia(imageSetOptionNodes[index + 2], mediasByDpi)
17+
getMedia(imageSetOptionNodes[index + 2], mediasByDpr)
1818
];
1919

2020
// handle invalidations
@@ -36,29 +36,35 @@ export default (imageSetOptionNodes, decl, opts) => {
3636
index += 3
3737
}
3838

39-
const medias = Object.keys(mediasByDpi).map(params => mediasByDpi[params]);
39+
const medias = Object.keys(mediasByDpr).sort((a, b) => a - b).map(params => mediasByDpr[params]);
4040

4141
// conditionally prepend previous siblings
4242
if (medias.length) {
43-
const siblings = parent.nodes;
44-
const previousSiblings = siblings.slice(0, siblings.indexOf(decl));
43+
const firstDecl = medias[0].nodes[0].nodes[0];
4544

46-
if (previousSiblings.length) {
47-
const parentClone = parent.cloneBefore().removeAll();
45+
if (medias.length === 1) {
46+
decl.value = firstDecl.value
47+
} else {
48+
const siblings = parent.nodes;
49+
const previousSiblings = siblings.slice(0, siblings.indexOf(decl)).concat(firstDecl);
4850

49-
parentClone.append(previousSiblings);
50-
}
51+
if (previousSiblings.length) {
52+
const parentClone = parent.cloneBefore().removeAll();
53+
54+
parentClone.append(previousSiblings);
55+
}
5156

52-
// prepend any @media { decl: <image> } rules
53-
parent.before(medias);
57+
// prepend any @media { decl: <image> } rules
58+
parent.before(medias.slice(1));
5459

55-
// conditionally remove the current rule
56-
if (!opts.preserve) {
57-
decl.remove();
60+
// conditionally remove the current rule
61+
if (!opts.preserve) {
62+
decl.remove();
5863

59-
// and then conditionally remove its parent
60-
if (!parent.nodes.length) {
61-
parent.remove();
64+
// and then conditionally remove its parent
65+
if (!parent.nodes.length) {
66+
parent.remove();
67+
}
6268
}
6369
}
6470
}

plugins/postcss-image-set-function/test/basic.expect.css

+2-84
Original file line numberDiff line numberDiff line change
@@ -8,45 +8,15 @@
88

99
.test-changed-properties {
1010
order: 1;
11-
}
12-
13-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
14-
15-
.test-changed-properties {
1611
background-image:
1712
url(img/test.png);
18-
}
19-
}
20-
21-
.test-changed-properties {
22-
background-image: image-set(
23-
url(img/test.png) 1x
24-
);
2513
order: 2;
26-
}
27-
28-
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
29-
30-
.test-changed-properties {
3114
background-image:
3215
url(img/test.png);
33-
}
34-
}
35-
36-
.test-changed-properties {
37-
background-image: image-set(
38-
url(img/test.png) 2x
39-
);
4016
order: 3;
41-
}
42-
43-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
44-
45-
.test-changed-properties {
4617
background-image:
4718
url(img/test.png);
4819
}
49-
}
5020

5121
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
5222

@@ -62,15 +32,9 @@
6232
url(img/test-2x.png) 2x
6333
);
6434
order: 4;
65-
}
66-
67-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
68-
69-
.test-changed-properties {
7035
background-image:
7136
url(img/test.png);
7237
}
73-
}
7438

7539
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
7640

@@ -99,15 +63,9 @@
9963

10064
.test-mixed-units {
10165
order: 1;
102-
}
103-
104-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
105-
106-
.test-mixed-units {
10766
background-image:
10867
url(img/test.png);
10968
}
110-
}
11169

11270
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
11371

@@ -123,6 +81,8 @@
12381
url(img/test-2x.png) 2dppx
12482
);
12583
order: 2;
84+
background-image:
85+
url(img/test-2x.png);
12686
}
12787

12888
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
@@ -133,14 +93,6 @@
13393
}
13494
}
13595

136-
@media (-webkit-min-device-pixel-ratio: 0.52), (min-resolution: 50.8dpi) {
137-
138-
.test-mixed-units {
139-
background-image:
140-
url(img/test-2x.png);
141-
}
142-
}
143-
14496
.test-mixed-units {
14597
background-image: image-set(
14698
url(img/test.png) 1x,
@@ -151,15 +103,9 @@
151103

152104
.test-mixed-order {
153105
order: 1;
154-
}
155-
156-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
157-
158-
.test-mixed-order {
159106
background:
160107
url(../images/bck.png);
161108
}
162-
}
163109

164110
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
165111

@@ -184,15 +130,9 @@
184130
url(../images/bck@2x.png) 2x
185131
);
186132
order: 2;
187-
}
188-
189-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
190-
191-
.test-mixed-order {
192133
background:
193134
url(../images/bck.png);
194135
}
195-
}
196136

197137
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
198138

@@ -221,14 +161,8 @@
221161

222162
.test-no-url {
223163
order: 1;
224-
}
225-
226-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
227-
228-
.test-no-url {
229164
background-image: img/test.png;
230165
}
231-
}
232166

233167
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
234168

@@ -243,14 +177,8 @@
243177
"img/test-2x.png" 2x
244178
);
245179
order: 2;
246-
}
247-
248-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
249-
250-
.test-no-url {
251180
background-image: img/test.png;
252181
}
253-
}
254182

255183
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
256184

@@ -277,15 +205,9 @@
277205

278206
.test-webkit-prefix {
279207
order: 1;
280-
}
281-
282-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
283-
284-
.test-webkit-prefix {
285208
background-image:
286209
url(img/test.png);
287210
}
288-
}
289211

290212
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
291213

@@ -313,12 +235,10 @@
313235
}
314236

315237
@media (min-width: 1000px) {
316-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
317238
.test-within-mq-1 {
318239
background-image:
319240
url(img/test.png);
320241
}
321-
}
322242
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
323243
.test-within-mq-1 {
324244
background-image:
@@ -341,12 +261,10 @@
341261
}
342262

343263
@media (min-width: 768px) and (max-width: 1024px) {
344-
@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) {
345264
.test-within-mq-2 {
346265
background-image:
347266
url(img/test.png);
348267
}
349-
}
350268
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
351269
.test-within-mq-2 {
352270
background-image:

0 commit comments

Comments
 (0)