diff --git a/lib/resolution.js b/lib/resolution.js index ee04d6d99..2b920864b 100644 --- a/lib/resolution.js +++ b/lib/resolution.js @@ -4,7 +4,7 @@ let Prefixer = require('./prefixer') let utils = require('./utils') const REGEXP = /(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpcm|dpi|x)/gi -const SPLIT = /(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i +const SPLIT = /((min|max)-resolution)(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i class Resolution extends Prefixer { /** @@ -73,19 +73,36 @@ class Resolution extends Prefixer { continue } + let fallbackExpression + let addFallbackExpression = false for (let prefix of prefixes) { let processed = query.replace(REGEXP, str => { let parts = str.match(SPLIT) + let fallbackName = parts[1] + let colon = parts[3] + let value = parts[4] + let units = parts[5] + + // Add `ddpx` for browsers that do not support `x` unit. + // `x` unit: Chrome 68+, Edge 79+, Opera 55+, Safari 16+, Firefox 62+ + // See: https://developer.mozilla.org/en-US/docs/Web/CSS/resolution#browser_compatibility + if (units === 'x') { + fallbackExpression = '(' + fallbackName + colon + value + 'dppx' + ')' + addFallbackExpression = true + } + return this.prefixQuery( prefix, - parts[1], - parts[2], - parts[3], - parts[4] + parts[2], // min- or max- + colon, + value, + units ) }) prefixed.push(processed) } + + if (addFallbackExpression) prefixed.push(fallbackExpression) prefixed.push(query) } diff --git a/test/autoprefixer.test.js b/test/autoprefixer.test.js index 4496564a7..38a3932ca 100644 --- a/test/autoprefixer.test.js +++ b/test/autoprefixer.test.js @@ -231,6 +231,7 @@ const COMMONS = [ 'supports', 'viewport', 'resolution', + 'resolution-dppx-fallback', 'logical', 'appearance', 'advanced-filter', @@ -505,6 +506,11 @@ test('removes unnecessary prefixes', () => { if (i === 'grid-template-areas') continue let input = read(i + '.out') let output = read(i) + + if (i === 'resolution-dppx-fallback') { + output = '@media (min-resolution: 2dppx), (min-resolution: 2x) { }\n' + } + equal(processor.process(input).css, output) } }) diff --git a/test/cases/resolution-dppx-fallback.css b/test/cases/resolution-dppx-fallback.css new file mode 100644 index 000000000..43994b214 --- /dev/null +++ b/test/cases/resolution-dppx-fallback.css @@ -0,0 +1 @@ +@media (min-resolution: 2x) { } diff --git a/test/cases/resolution-dppx-fallback.out.css b/test/cases/resolution-dppx-fallback.out.css new file mode 100644 index 000000000..e2bf9a8a4 --- /dev/null +++ b/test/cases/resolution-dppx-fallback.out.css @@ -0,0 +1 @@ +@media (-webkit-min-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 2x) { } diff --git a/test/cases/resolution.css b/test/cases/resolution.css index 18d357d97..a4d8a3350 100644 --- a/test/cases/resolution.css +++ b/test/cases/resolution.css @@ -7,6 +7,8 @@ @media (min-resolution: 2x) { } +@media (min-resolution: 2dppx), (min-resolution: 2x) { } + @media (min-resolution: 120dpi) { } @media (min-resolution: 2dppx) { } diff --git a/test/cases/resolution.out.css b/test/cases/resolution.out.css index 708e4703f..e7dfa8a4e 100644 --- a/test/cases/resolution.out.css +++ b/test/cases/resolution.out.css @@ -8,7 +8,9 @@ @media (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 144dpi) { } -@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2x) { } +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 2x) { } + +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 2x) { } @media (-webkit-min-device-pixel-ratio: 1.25), (min--moz-device-pixel-ratio: 1.25), (-o-min-device-pixel-ratio: 5/4), (min-resolution: 120dpi) { }