-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
[Feature Request/Discussion] @apply with media queries and pseudo selectors #313
Comments
Amen. Is this possible? |
Would like to support this eventually but it's not simple at all; probably at least a full week of effort to figure out and implement. One day, but no timeline right now. |
Yeah I can imagine it's a lot of work! Thanks for the response and congrats on making such an incredible project 👍 |
I'd love to see this in Tailwind some time but I understand the implementation can be a can of worms. Is there anything that can be contributed to help with this, or is it something that needs to be done by the core team? |
I don't know if this helps anyone but this worked for me using scss instead of css.
|
I think this is along the same lines of what @paulcsmith was after, I had hoped something like this was possible:
I know it starts to go against the concept of it being utility driven but if some elements are truly globally styled it'd be great to not have to add the same classes to every instance of the element, and also not have to write custom media queries for a couple of attributes. |
Hey @MattRogowski! That's actually totally possible already, you just need to use media queries or our h1 {
@apply .text-size-3;
@screen lg {
@apply .text-size-5;
}
} Eventually I'd like to make it possible to |
Just wanted to leave some notes for myself here as I start thinking about how the fuck this could possibly work... Possible approaches
In this scenario, when someone types The biggest challenge with this is getting the order right. If someone type The shittiest thing about this solution is that all variant plugins would need to provide this "reverse engineering" function to deduce if a class would have been generated by that plugin. That's a shitty burden for plugin authors.
In this scenario, we would use Using this approach, we could also keep track of the matches position in the stylesheet so that when we go to append the matched rules we can preserve the order in which they appeared in the original stylesheet. This part is easier using this option, but actually finding a match is harder and more expensive. Overall this feature is going to be very hard to do :) |
@adamwathan Correct me if I’m wrong, but I see a problem with approach #1. What if a plugin defines a new variant, let’s say |
@benface It would be the variant plugin's responsibility, so you'd pass Overall I think that approach is shitty — the whole idea of having to break it apart sucks, because it's theoretically possible to write a variant plugin that makes it impossible to reverse engineer the original parts so I think it's fundamentally flawed. Thinking on it more I think what I will need to do is something more like option 2, but where we build our own data structure in advance for doing the lookups and have it include all of Tailwind's utilities + generated variants, and when you look them up there the result should include any of the necessary meta data, like the priority of the variant and stuff like that. I think it's doable but there is going to be complexity around multi-class selectors (like Variant plugins might need to report a "lookup key" for each generated rule or something, so like this rule:
...would need to report a lookup key of "group-hover:bg-blue" since that is how people are going to try and "apply" that. I hope I don't need to do that but not sure it'll be possible to avoid. |
Related to this whole thing, I think part of making this work might mean removing support for applying your own custom utilities if they are defined in CSS. You'd still be able to do it but you'd need to define them in plugins. The reason I'm guessing this might be a problem is because I think it's going to be hard to pull the meta data we need out of the CSS vs. having the JS data structure in advance, but I might be wrong, we'll see. |
Another idea, it might be easier to implement all this stuff if internally we use a nested syntax for our own CSS. It would certainly help for focus/hover/etc, but maybe not for responsive stuff since we group all of our responsive declarations. Example:
Now the lookup key is still just Would need to actually try it to know for sure if there's other crap to worry about but might make some things easier. This approach works in Less too. |
Quoting myself here but thinking about this more, it's probably not that crazy if the apply order actually matter, because that's currently the case anyways. Consider this HTML:
Because Now consider extracting those classes to a component class:
In this case, Tailwind currently renders this output:
...which means the I don't know if we should consider this a bug or not necessarily, but it is the current behavior so I think it's fine to ignore the order problem for a first pass at making it possible to apply utility variants directly. |
I think I've thought of this as a feature when using It is inconsistent, though, if In the end, dunno. I think it depends on what you intended for |
Following up, I think this is going to be the path forward. For all this stuff to work in a sane way, we have to stop thinking of utilities as classes and instead think of them as mixins/functions. As part of Tailwind's processing, it just happens to create a class for every single utility function so that you can use those utility functions in your HTML. From an implementation perspective, Tailwind is going to need to augment the shadow lookup table to include utility variants (right now it just includes raw utilities), so we'd have something like this: const shadowLookup = {
'bg-blue': {},
'hover:bg-blue': {
'&:hover': {
// ...
}
},
'group-hover:bg-pink': {
'.group:hover &': {
// ...
}
},
// ...
'sm:bg-blue': {
'@media ...': {
// ...
}
},
'sm:hover:bg-blue': {
'@media ...': {
'&:hover': {
// ...
}
}
},
// ...
} This way, when someone tries to {
'@media (min-width: 576px)': {
'&:hover': {
backgroundColor: 'blue',
}
}
} Then we just copy that set of properties into the component where One consequence of this approach that I think I'm okay with is that nesting is now a "feature" of Tailwind, because there's no really straightforward way for us to process nesting for Tailwind-generated stuff and not for user generated stuff. This increases the scope of Tailwind a bit and I would prefer if it could be avoided, but I don't think it can. There's also an issue of This is the right thing to do for that project since it's not part of any spec, but since we would need to have that working for this feature to work, we'll have to write our own plugin that just handles nested media queries and have that run before Probably tackle this in December. |
An easy workaround looks something like this: .site-nav {
@screen md {
@apply flex-row
}
@apply flex pt-10
} By using the |
Thanks @joshwcorbett. I think that's a totally acceptable solution! |
@joshwcorbett Any workaround for hover styles? |
@rightaway As per the docs: /* Won't work: */
.btn {
@apply block bg-red-500;
@apply hover:bg-blue-500;
@apply md:inline-block;
}
/* Do this instead: */
.btn {
@apply block bg-red-500;
}
.btn:hover {
@apply bg-blue-500;
}
@screen md {
.btn {
@apply inline-block;
}
} |
@rightaway I usually use a poscss plugin called ‘precss’ which gives me the ability to use SASS-like syntax. So when using this plugin, I can use the ‘&:hover’. I’m typing this on iPad so I can’t do a code snippet but I hope this helps. |
For Tailwind 2.0, it would be great to have something like
|
Here is an action plan:
Rust is freakishly complicated, but the compiler gives so great explanations that you can just follow it and it all works So instead of leaving this unfixed you do:
rule:hover {
I understand you want to discourage @apply, but still need to keep it, but also don’t want to spend 100s of Support hours. In that case not fixing this issue magically (which could have side effects), but instead leading the user to the solution should solve the problem. I love all the tailwind magic, but it is not necessary for everything. For those that don’t want to do it manually and are okay with magic side effects, they could still use the magic prefix apply plugin. So it’s a win for everyone - even if the feature request is ultimatively declined that way. |
From my view, Tailwind is a language, so In the other hand, I understand that Tailwind is "only" a utility-first framework, a set of handy CSS classes. So, it is going to be only a layer of convenient CSS classes. In that line, as Adam pointed out from docs, that this is the best lean approach that is currently supported: .btn {
@apply block bg-red-500;
}
.btn:hover {
@apply bg-blue-500;
}
@screen md {
.btn {
@apply inline-block;
}
} |
@apply currently does not work with pseudo selectors and media queries. I can see why that is difficult, but I wonder if it is on the roadmap to support something like that in the future?
I'd love it if @apply could make media queries or hover selectors automatically. Maybe it would have to be a Saas/Less only feature because I'm not sure how it would work with raw CSS, but I'm not sure.
Thanks for considering, and thanks for making such an awesome lib
The text was updated successfully, but these errors were encountered: