Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using both selectors and media-queries not working as expected. #24

Open
mia-riezebos opened this issue Jun 15, 2024 · 9 comments
Open
Assignees
Labels
bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request

Comments

@mia-riezebos
Copy link

In the docs on the website, there's a table specifying that if a selector matches, it takes precedence over any media query.

match neither prefers-color-scheme: light prefers-color-scheme: dark
neither none cyan navy
.cyan cyan cyan cyan
.navy navy navy navy

As previously noted, when a required selector is present, it takes precendence over the media queries. Stated another way, the media queries only matter when no selector matches.

The thing is, in my project, my themes are not behaving as described above.

My config is like such:

// tailwind.config.cjs
// ...
	variants: {
		extend: {
			backgroundColor: ['schemes'],
			textColor: ['schemes'],
			fill: ['schemes'],
			stroke: ['schemes'],
			borderColor: ['schemes'],
			outlineColor: ['schemes'],
			ringColor: ['schemes'],
			ringOffsetColor: ['schemes'],
			boxShadow: ['schemes']
		}
	},
	plugins: [
		// ...
		// Color Schemes
		themeVariants({
			group: 'schemes',
			themes: {
				// Basic Dark / Light Themes
				dark: {
					mediaQuery: prefersDark,
					selector: "[data-theme='dark']",
				},

				light: {
					mediaQuery: prefersLight,
					selector: "[data-theme='light']",
				}

				// // Inverted Colors (make sure there's no compatibility issues with inverted colors)
				// 'colors-inverted': {
				// 	mediaQuery: colorsInverted
				// }
			},
			// baseSelector: 'html',
			// fallback: 'dark'
		}),
		// ...
	]

The generated CSS (for example on the light theme), looks like this:

@media (prefers-color-scheme: light){
        :root[data-theme='light'] .light\:bg-other-green-300{
                --tw-bg-opacity: 1;
                background-color: rgb(134 239 172 / var(--tw-bg-opacity));
        }
}

and behaves as you would expect from the generated css; BOTH the media query AND the selector [data-theme='light'] have to match for the background to turn green.

@JNavith JNavith self-assigned this Jun 15, 2024
@JNavith JNavith added the bug Something isn't working label Jun 15, 2024
@JNavith
Copy link
Owner

JNavith commented Jun 15, 2024

Thanks for the report! I can reproduce this.
I'm going to try my best to fix this, but Tailwind CSS and related has changed a lot since my last update to this project, and I haven't been working with JavaScript lately, so it might be a struggle and I might just have to post a snippet of code that bypasses this plugin that you can use in case I can't update this project without breakage. We'll see, but here's hoping.

@JNavith
Copy link
Owner

JNavith commented Jun 15, 2024

This is happening because recent versions of Tailwind CSS reserve special meaning for the dark variant. Even though it's unfortunate that this can't be disabled, they at least allow it to be customized. So, as long as I'm right to assume you are using version 3 (e.g. 3.4.4 is what I'm testing on), you can trim out this plugin and use an easier and terser approach:

// possibly const plugin = require("tailwindcss/plugin"); instead, but you can switch from .cjs to .js and use ESM syntax in modern Tailwind versions
import plugin from 'tailwindcss/plugin';

/** @type {import('tailwindcss').Config} */
// possibly module.exports = instead, but you can switch from .cjs to .js and use ESM syntax in modern Tailwind versions
export default {
	darkMode: ['variant', ['@media (prefers-color-scheme: dark) { :root & }', ':root[data-theme=dark] &']],

	theme: {
                // ... your customizations here
		extend: {}
	},
        // variants: section no longer needed in v3
	plugins: [
		plugin(({ addVariant }) => {
			addVariant('light', ['@media (prefers-color-scheme: light) { :root & }', ':root[data-theme=light] &']);
		})
	]
}

This works for your current configuration without having to refactor the HTML.

A note on potential future needs, though: because their dark variant will only appear after the light variant in the CSS, it wouldn't be possible to have dark as the fallback theme without raising the specificity in the light variant if it comes to that.

@JNavith
Copy link
Owner

JNavith commented Jun 15, 2024

An alternative option that takes more work to implement:

It is also an option not to use the built-in darkMode, but disabling it is not possible, so you'd have to rename the theme variant so that it doesn't clash:

// if you continue to use my plugin
themes: {
        // example names
	"dark-theme": { ... },
	"light-theme": { ... }
}


// if you use the approach bypassing this plugin
addVariant('theme-dark', ['@media (prefers-color-scheme: dark) { :root & }', ':root[data-theme=dark] &']);
addVariant('theme-light', ['@media (prefers-color-scheme: light) { :root & }', ':root[data-theme=light] &']);

and go back and change all occurrences of light: and dark: in the HTML (youch - why I wouldn't go through with this option except if you know you need a capability that the built-in darkMode customization can't provide (e.g. fallback)) to their new variant names.

@JNavith
Copy link
Owner

JNavith commented Jun 16, 2024

Implementing fallback without my plugin would be done by changing the order of the addVariant calls to change the order they appear in the CSS, and writing :not calls like this to replicate how my plugin would've done it:

// theme-dark will apply as long as the light theme hasn't been activated by `prefers-color-scheme: light` or by `[data-theme=light]`
addVariant('theme-dark', ':root &');			
// but this can override it (it will have enough specificity in the CSS)
addVariant('theme-light', [
    '@media (prefers-color-scheme: light) { :root:not([data-theme=dark]) & }',
    '[data-theme=light] &'
]);

(where here, and in the messages before this, :root is the base selector)

@JNavith JNavith added documentation Improvements or additions to documentation enhancement New feature or request labels Jun 16, 2024
@JNavith
Copy link
Owner

JNavith commented Jun 16, 2024

Regardless of these workarounds, this plugin and its documentation need to be updated to address this issue. Thanks again for the report.

@mia-riezebos
Copy link
Author

mia-riezebos commented Jun 16, 2024

Disabling darkMode in the tailwind config is actually possible using darkMode: false. I ran into this with Supermaven and it's not documented, but it does work.
This will have the plugin generate the dark: variant properly again, but the generated styles, even for light mode don't match the described behaviour.

thanks for looking into this!

@mia-riezebos
Copy link
Author

mia-riezebos commented Jun 16, 2024

I quite like the syntax and provided media query exports of this plugin, and would enjoy continued use of it!

At this time, I am circumventing the issue by adding two auto themes

		// Color Schemes
		themeVariants({
			group: 'schemes',
			themes: {
				// Basic Dark / Light Themes
				dark: {
					selector: ":is([data-theme='dark'], :has(>[data-theme='dark']))"
				},

				light: {
					selector: ":is([data-theme='light'], :has(>[data-theme='light']))"
				},

				'auto-light': {
					selector: ":is([data-theme='auto'], :has([data-theme='auto']))",
					mediaQuery: prefersLight
				},

				'auto-dark': {
					selector: ":is([data-theme='auto'], :has([data-theme='auto']))",
					mediaQuery: prefersDark
				}

				// // Inverted Colors (make sure there's no compatibility issues with inverted colors)
				// 'colors-inverted': {
				// 	mediaQuery: colorsInverted
				// }
			},
			baseSelector: '*'
			// fallback: 'auto-dark'
		}),

It is a little... verbose, but it was the solution I came up with the quickest, which is what mattered at this time. The main annoyance is providing all theme variants whenever I style an element.

again, thanks for getting back to me, I'll give the built-in variant config a try.

@mia-riezebos
Copy link
Author

mia-riezebos commented Jun 17, 2024

Ok so I like your workaround approach but I did still wanna keep the syntax from your plugin sooo

@mia-cx/tailwindcss-themes

I will add attribution in the readme in the next commit, there's already a little comment at the top of the index file

@mia-riezebos
Copy link
Author

Seen as this repo seems stale, I would be down to maintain a spiritual successor of this plugin. I don't see a future where I stop working in ts/js soon.

Let me know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants