Closed peterhirn closed 1 year ago
Potential related Issues / PRs:
@apply
directive. The provided reproduction URL demonstrates the issue and provides a workaround. This may be relevant because it involves the generation of duplicate selectors, similar to the issue being reported.@import
CSS rules cause undefined behavior in the Tailwind CSS plugin. The provided reproduction URL demonstrates the issue and provides insights into the root cause. This may be relevant because it involves the handling of duplicate rules, similar to the issue being reported.This message was generated by AI from www.triagetickets.com
Hey! Rules with identical selectors are merged and identical properties are removed. I doubt this is a behavior we'll remove anytime soon as we rely on it for some things. I would suggest wrapping your imported files in native CSS layers:
@import "./tokens.light.css" layer(light);
@import "./tokens.dark.css" layer(dark);
This should prevent them from being merged and de-duplicated (because the at-rules will have different "names"). You can then look for @layer light
and @layer dark
in your PostCSS plugin and remove the wrapping layer by replacing it with the child nodes:
This is pseudo code for a PostCSS visitor so it may need some tweaks but the general idea is this:
AtRule(rule) {
if (rule.name === 'layer' && (rule.params === 'dark' || rule.params === 'light')) {
rule.replaceWith(...rule.nodes)
}
},
Note that you'll want to be sure to run this after Tailwind CSS is run.
Hope that helps! ✨
Hey! Thanks for your response.
I just realized that my approach was nonsensical. I ended up with all my classes looking like "bg-primary-light dark:bg-primary-dark"
which is noisy and redundant.
I now wrapped the token.css
files in html[data-mode="dark"]
/ html[data-mode="light"]
, adjusted my tailwind config and removed all dark:
variants and -light
suffixes. So the example above is now simply "bg-primary"
¯\_(ツ)_/¯
I'll dump my full config below for anyone interested. Variables / token files were generated using https://material-components.github.io/material-web/.
tokens.light.css
html[data-mode="light"] {
--md-sys-color-background: #f8f9fd;
--md-sys-color-on-background: #191c1f;
--md-sys-color-surface: #f8f9fd;
...
}
tokens.dark.css
html[data-mode="dark"] {
--md-sys-color-background: #111417;
--md-sys-color-on-background: #e1e2e6;
--md-sys-color-surface: #111417;
...
}
index.css
@import "./tokens.light.css";
@import "./tokens.dark.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
postcss.config.js
import tailwindcss from "tailwindcss"
import autoprefixer from "autoprefixer"
const variablesToRgb = () => ({
postcssPlugin: "material-variables-to-rgb",
Declaration(decl) {
if (
decl.variable &&
decl.prop.startsWith("--md-") &&
decl.value.startsWith("#") &&
decl.value.length === 7
) {
const color = parseInt(decl.value.slice(1, 7), 16)
const r = (color >> 16) & 255
const g = (color >> 8) & 255
const b = color & 255
decl.value = `${r} ${g} ${b}`
}
}
})
variablesToRgb.postcss = true
export default {
plugins: [variablesToRgb, tailwindcss, autoprefixer]
}
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
darkMode: ["class", '[data-mode="dark"]'],
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
future: {
hoverOnlyWhenSupported: true
},
theme: {
extend: {
colors: {
primary: {
DEFAULT: "rgb(var(--md-sys-color-primary) / <alpha-value>)",
container: "rgb(var(--md-sys-color-primary-container) / <alpha-value>)"
},
secondary: {
DEFAULT: "rgb(var(--md-sys-color-secondary) / <alpha-value>)",
container: "rgb(var(--md-sys-color-secondary-container) / <alpha-value>)"
},
tertiary: {
DEFAULT: "rgb(var(--md-sys-color-tertiary) / <alpha-value>)",
container: "rgb(var(--md-sys-color-tertiary-container) / <alpha-value>)"
},
error: {
DEFAULT: "rgb(var(--md-sys-color-error) / <alpha-value>)",
container: "rgb(var(--md-sys-color-error-container) / <alpha-value>)"
},
surface: {
DEFAULT: "rgb(var(--md-sys-color-surface) / <alpha-value>)",
dim: "rgb(var(--md-sys-color-surface-dim) / <alpha-value>)",
bright: "rgb(var(--md-sys-color-surface-bright) / <alpha-value>)",
tint: "rgb(var(--md-sys-color-surface-tint) / <alpha-value>)",
variant: "rgb(var(--md-sys-color-surface-variant) / <alpha-value>)",
container: {
DEFAULT: "rgb(var(--md-sys-color-surface-container) / <alpha-value>)",
lowest: "rgb(var(--md-sys-color-surface-container-lowest) / <alpha-value>)",
low: "rgb(var(--md-sys-color-surface-container-low) / <alpha-value>)",
high: "rgb(var(--md-sys-color-surface-container-high) / <alpha-value>)",
highest: "rgb(var(--md-sys-color-surface-container-highest) / <alpha-value>)"
}
},
inverse: {
surface: "rgb(var(--md-sys-color-inverse-surface) / <alpha-value>)",
primary: "rgb(var(--md-sys-color-inverse-primary) / <alpha-value>)",
on: {
surface: "rgb(var(--md-sys-color-inverse-on-surface) / <alpha-value>)",
primary: "rgb(var(--md-sys-color-inverse-on-primary) / <alpha-value>)"
}
},
background: "rgb(var(--md-sys-color-background) / <alpha-value>)",
outline: {
DEFAULT: "rgb(var(--md-sys-color-outline) / <alpha-value>)",
variant: "rgb(var(--md-sys-color-outline-variant) / <alpha-value>)"
},
shadow: "rgb(var(--md-sys-color-shadow) / <alpha-value>)",
scrim: "rgb(var(--md-sys-color-scrim) / <alpha-value>)",
on: {
primary: {
DEFAULT: "rgb(var(--md-sys-color-on-primary) / <alpha-value>)",
container: "rgb(var(--md-sys-color-on-primary-container) / <alpha-value>)"
},
secondary: {
DEFAULT: "rgb(var(--md-sys-color-on-secondary) / <alpha-value>)",
container: "rgb(var(--md-sys-color-on-secondary-container) / <alpha-value>)"
},
tertiary: {
DEFAULT: "rgb(var(--md-sys-color-on-tertiary) / <alpha-value>)",
container: "rgb(var(--md-sys-color-on-tertiary-container) / <alpha-value>)"
},
error: {
DEFAULT: "rgb(var(--md-sys-color-on-error) / <alpha-value>)",
container: "rgb(var(--md-sys-color-on-error-container) / <alpha-value>)"
},
surface: {
DEFAULT: "rgb(var(--md-sys-color-on-surface) / <alpha-value>)",
variant: "rgb(var(--md-sys-color-on-surface-variant) / <alpha-value>)"
},
background: "rgb(var(--md-sys-color-on-background) / <alpha-value>)"
}
},
}
},
plugins: []
}
What version of Tailwind CSS are you using?
v3.3.2
What build tool (or framework if it abstracts the build tool) are you using?
postcss 8.4.24, vite 4.3.9
What version of Node.js are you using?
v20.3.0
What browser are you using?
Chrome
What operating system are you using?
Windows 10
Reproduction
tailwind.config.js
postcss.config.js
tokens.light.css
tokens.dark.css
index.css
Describe your issue
I have a set of two css files which declare variables with identical variable names (
tokens.light.css
andtokens.dark.css
). I'm using this minimal PostCSS plugin to automatically append-light
/-dark
to the variable names depending on which file they were declared in. Additionally I also convert the hex colors to rgb but this is not relevant here.This works perfectly until a variable has not only the same name but also the same value, see
--md-sys-color-outline
above. In this case one of the variants is not created, here--md-sys-color-outline-light
is missing.Expected
Actual