Add a colorMixPolyfill option to @tailwindcss/postcss
The compiler always emits the color-mix() compatibility pair — a plain fallback declaration plus the original gated behind @supports (color: color-mix(in lab, red, red)) — for browsers without color-mix() support (Safari < 16.2). For projects whose browser floor is at or above Tailwind's own supported targets, the gated arm always wins and the fallback arm is dead bytes on the render-blocking path. Measured in a large app: 342 duplicated @supports blocks, ~42KB decoded / ~4KB gzipped, with zero rendering difference on every supported browser. colorMixPolyfill?: boolean (default true, existing behavior unchanged) masks Polyfills.ColorMix out of the compile, mirroring how the plugin already varies the polyfill set per input (Polyfills.All ^ Polyfills.AtProperty for CSS Modules). The compiler-cache key gains the flag so two configs sharing an input file cannot reuse each other's compiler.
This commit is contained in:
parent
90f8ff41c8
commit
b92b9f7bdd
3 changed files with 43 additions and 2 deletions
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- Add `@tailwindcss/turbopack` package to run Tailwind CSS with Next.js ([20367](https://github.com/tailwindlabs/tailwindcss/pull/20367))
|
||||
- Add a `colorMixPolyfill` option to `@tailwindcss/postcss` so projects whose browser targets all support `color-mix()` can drop the duplicated `@supports` fallback declarations
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,33 @@ test('output is optimized by Lightning CSS', async () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test('`color-mix(…)` fallbacks can be disabled', async () => {
|
||||
let input = css`
|
||||
@reference 'tailwindcss/theme.css';
|
||||
.foo {
|
||||
@apply text-red-500/50;
|
||||
}
|
||||
`
|
||||
|
||||
// On by default: a `color-mix(…)` declaration is emitted twice — a plain
|
||||
// fallback, plus the original behind an `@supports` gate.
|
||||
let withPolyfill = await postcss([
|
||||
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
||||
]).process(input, { from: inputCssFilePath() })
|
||||
expect(withPolyfill.css).toContain('color-mix(in lab, red, red)')
|
||||
|
||||
// Disabled: the declaration ships once, and nothing else changes.
|
||||
let withoutPolyfill = await postcss([
|
||||
tailwindcss({
|
||||
base: `${__dirname}/fixtures/example-project`,
|
||||
colorMixPolyfill: false,
|
||||
optimize: { minify: false },
|
||||
}),
|
||||
]).process(input, { from: inputCssFilePath() })
|
||||
expect(withoutPolyfill.css).toContain('color-mix(')
|
||||
expect(withoutPolyfill.css).not.toContain('@supports')
|
||||
})
|
||||
|
||||
test('@apply can be used without emitting the theme in the CSS file', async () => {
|
||||
let processor = postcss([
|
||||
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ interface CacheEntry {
|
|||
const cache = new QuickLRU<string, CacheEntry>({ maxSize: 50 })
|
||||
|
||||
function getContextFromCache(postcss: Postcss, inputFile: string, opts: PluginOptions): CacheEntry {
|
||||
let key = `${inputFile}:${opts.base ?? ''}:${JSON.stringify(opts.optimize)}`
|
||||
let key = `${inputFile}:${opts.base ?? ''}:${JSON.stringify(opts.optimize)}:${opts.colorMixPolyfill ?? true}`
|
||||
if (cache.has(key)) return cache.get(key)!
|
||||
let entry = {
|
||||
mtimes: new Map<string, number>(),
|
||||
|
|
@ -68,12 +68,23 @@ export type PluginOptions = {
|
|||
* Defaults to `true`.
|
||||
*/
|
||||
transformAssetUrls?: boolean
|
||||
|
||||
/**
|
||||
* Emit `color-mix(…)` fallbacks for browsers without `color-mix()` support
|
||||
* (Safari < 16.2): a plain fallback declaration, plus a copy of the original
|
||||
* declaration gated behind `@supports (color: color-mix(in lab, red, red))`.
|
||||
*
|
||||
* Defaults to `true`. Set this to `false` when every browser you support has
|
||||
* `color-mix()`, which removes the duplicated declarations from the output.
|
||||
*/
|
||||
colorMixPolyfill?: boolean
|
||||
}
|
||||
|
||||
function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
|
||||
let base = opts.base ?? process.cwd()
|
||||
let optimize = opts.optimize ?? process.env.NODE_ENV === 'production'
|
||||
let shouldRewriteUrls = opts.transformAssetUrls ?? true
|
||||
let colorMixPolyfill = opts.colorMixPolyfill ?? true
|
||||
|
||||
return {
|
||||
postcssPlugin: '@tailwindcss/postcss',
|
||||
|
|
@ -144,7 +155,9 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
|
|||
// In CSS Module files, we have to disable the `@property` polyfill since these will
|
||||
// emit global `*` rules which are considered to be non-pure and will cause builds
|
||||
// to fail.
|
||||
polyfills: isCSSModuleFile ? Polyfills.All ^ Polyfills.AtProperty : Polyfills.All,
|
||||
polyfills:
|
||||
(isCSSModuleFile ? Polyfills.All ^ Polyfills.AtProperty : Polyfills.All) &
|
||||
(colorMixPolyfill ? Polyfills.All : ~Polyfills.ColorMix),
|
||||
})
|
||||
DEBUG && I.end('Create compiler')
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue