diff --git a/src/corePlugins.js b/src/corePlugins.js index 2bd8e9d0357a..90973cf09877 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -1,6 +1,7 @@ import fs from 'fs' import * as path from 'path' import postcss from 'postcss' +import postcssValueParser from 'postcss-value-parser' import createUtilityPlugin from './util/createUtilityPlugin' import buildMediaQuery from './util/buildMediaQuery' import escapeClassName from './util/escapeClassName' @@ -208,10 +209,29 @@ export let variantPlugins = { }, screenVariants: ({ theme, addVariant }) => { + let id = Symbol('screens') + let values = Object.values(theme('screens', {})) + let sort = !( + values.every((value) => typeof value === 'string') && + new Set(values.map((value) => postcssValueParser.unit(value)?.unit ?? value)).size === 1 + ) + ? () => 0 + : (a, z) => { + // Compare min-width screens + if (a.length === 1 && z.length === 1) { + let [{ min: aMin }] = a + let [{ min: zMin }] = z + return parseInt(aMin) - parseInt(zMin) + } + + // Not a screen we want to even try and compare + return 0 + } + for (let screen of normalizeScreens(theme('screens'))) { let query = buildMediaQuery(screen) - addVariant(screen.name, `@media ${query}`) + addVariant(screen.name, `@media ${query}`, { id, sort, value: screen.values }) } }, diff --git a/tests/responsive-and-variants-atrules.test.js b/tests/responsive-and-variants-atrules.test.js index 4bebc73faa1a..eb6b64d77456 100644 --- a/tests/responsive-and-variants-atrules.test.js +++ b/tests/responsive-and-variants-atrules.test.js @@ -1,7 +1,7 @@ import fs from 'fs' import path from 'path' -import { run, css } from './util/run' +import { run, css, html } from './util/run' test('responsive and variants atrules', () => { let config = { @@ -79,3 +79,37 @@ test('responsive and variants atrules', () => { expect(result.css).toMatchFormattedCss(expected) }) }) + +it('should sort breakpoints intelligentally', () => { + let config = { + content: [{ raw: html`
` }], + theme: { + extend: { + screens: { + xs: '123px', + }, + }, + }, + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + @media (min-width: 123px) { + .xs\:italic { + font-style: italic; + } + } + + @media (min-width: 768px) { + .md\:underline { + text-decoration-line: underline; + } + } + `) + }) +})