
When I try to use @apply on .btn-orange, it doesn't actually work for the hover styles, because the input element in reality doesn't have the class. As a workaround I had to use @extend.
Is there any better solution for this issue? I don't have control over the html so adding the class is not an option.
Sorry if this was asked before. Thanks for your work!
Experiencing the same _issue_.
EDIT: My workaround has been defining an extra class for hover styles and then applying that to whatever selectors I need to use it with:
.btn { @apply bg-transparent border; }
.btn-hover { @apply text-white bg-black; }
.button { @apply btn; }
.button:hover { @apply btn-hover; }
The issue description confuses me a bit. Are you saying that .btn-orange _is_ or _is not_ applied to the input element?
If it _is_ applied, are you just having issues with the @apply nested in &:hover not working? What's the actual output of that CSS Rule?
@taylorbryant I think they have an error in their scss and have both missed a . in front of the class name. This is how I have it in my SCSS file and it works just fine
`a {
@apply .pt-5 .pb-3 .text-grey-darker .no-underline;
&:hover {
@apply .text-teal;
}
}
`
Dots aren’t required according to the docs so that shouldn’t be the issue.
EDIT: I have a project where I had a similar setup so I might be able to test it in a couple days.
Please have a look at this Tutorial ..
https://youtu.be/3pN9EcFvPxo?list=PLht-7jHewMA4KfgZGHNyEx3mD-OJjaasM&t=145
I followed it and have to add the dots to make it work! like in the video
Ok, I wasn't too clear in the original post, so let me clarify.
@hacknug is right about the workaround, that's a better solution, but still a lot of extra work if you use SCSS and hover styles often.
(the dots are not required, but I'll add them now to avoid confusion)
.btn {
@apply .bg-red;
&:hover {
@apply .bg-black;
}
}
button {
@apply .btn;
}
This is the shortest representation of the issue. This generates the following CSS:
.btn {
background-color: #e3342f;
}
.btn:hover {
background-color: #22292f;
}
button {
background-color: #e3342f;
}
So the hover styles are lost. It's because the &:hover creates a new CSS rule, so when applying .btn to other elements, .btn:hover is left out.
This is usually not an issue, adding .btn to a real HTML element works as expected.
<button class="btn">Push</button>
In this example the button receives the hover styles. Actually there is no Tailwind here, this is just basic SCSS. The 'Tailwind solution' to this issue would be:
<button class="bg-red hover:bg-black">Push</button>
I guess this is how Tailwind was intended to be used, adding TW classes to the Markup. But for my usecase I need to style elements where I don't want to clutter the html and keep the style in the scss files and _still_ use TW's short css styling.
In the TW example .hover:bg-black is actually a class generated according to the tailwind.js file. So I don't see any easy solutions to this since .hover:btn would need to exist, plus it would need to be applied with the @apply .btn; line. (every time .btn is used, you want the new class work similar to the applied class)
I'm not sure if it's possible.
@apply-ed class and checking if they also have a corresponding .class:hover line. (same for focus, etc.).hover:class extra classes similarly to the built-in classes.@apply-ed classes.So in this ideal world the output CSS would look like this:
.btn {
background-color: #e3342f;
}
.btn:hover {
background-color: #22292f;
}
.hover\:btn:hover {
background-color: #22292f;
}
button {
background-color: #e3342f; // comes from `@apply .btn;`
}
button:hover {
background-color: #22292f; // theoretically comes from `@apply .hover:btn;`
}
Does that make any sense?
@adamwathan said on his post about going full-time with Tailwind that he's planning on solving this issue: https://adamwathan.me/going-full-time-on-tailwind-css/
I guess this means we'll also be able to @apply classes generated for all variants (also via plugins) 🎉
You are right, it's great news!
So in this particular example, @apply is sort of being used in a way it wasn't intended to be used.
The idea with @apply is that you use it to mix in existing _utilities_, simple classes that just do one thing, but in this example it's being used to mix in .btn which is a component class and has a lot more complexity to it (like the hover state.)
In fact in the current example, it's sort of just a coincidence that @apply .btn works at all, because we process @apply rules in a single pass.
That means that this happens to work:
// Input
.foo {
@apply bg-red;
}
.bar {
@apply foo;
}
// Output ✅
.foo {
background-color: red;
}
.bar {
background-color: red;
}
...but this wouldn't:
// Input
.foo {
@apply bar;
}
.bar {
@apply bg-red;
}
// Output ❌
.foo {
@apply bg-red;
}
.bar {
background-color: red;
}
Since @apply is processed in one pass, you can't reliably apply classes that apply other classes, because we don't process them recursively until all @apply calls are gone. This may change in the future but right now it's by design.
That all said, the plan for making @apply work for more scenarios will allow you to do what you want eventually, but you'd have to write it like this:
.btn {
@apply cursor-pointer;
@apply font-bold box;
}
.btn-orange {
@apply bg-orange text-white hover:bg-orange-dark;
}
input[type="submit"] {
@apply btn btn-orange;
}
...or alternatively not use Sass, and rely on the nesting support that will be coming to Tailwind itself.
In general I am sort of hesitant to recommend working this way or promise support for using @apply to apply component classes, because again it's meant to be used only for utilities by design. I want to be very careful avoiding scope-creep here and having what was designed to just be a simple "mix tiny utility classes into bigger component classes" feature become a full-blown mixin system like in Sass or Less. But it may end up that I can comfortably support this workflow depending on how these other improvements I'm making to @apply change the architecture of the feature, so we'll see.
Until then, since you're already using Sass I would recommend just using regular Sass mixins for what you are trying to do:
@mixin btn {
@apply cursor-pointer;
@apply font-bold box;
}
@mixin btn-orange {
@apply bg-orange text-white;
&:hover {
@apply bg-orange-dark;
}
}
.btn {
@include btn;
}
.btn-orange {
@include btn-orange;
}
input[type="submit"] {
@include btn;
@include btn-orange;
}
I'm going to close this for now as it's not a bug or anything, Tailwind is working as designed in this case, but I'm still planning to explore expanding the scope of @apply to handle this scenario closer to how the OP expected it to work.
Most helpful comment
So in this particular example,
@applyis sort of being used in a way it wasn't intended to be used.The idea with
@applyis that you use it to mix in existing _utilities_, simple classes that just do one thing, but in this example it's being used to mix in.btnwhich is a component class and has a lot more complexity to it (like the hover state.)In fact in the current example, it's sort of just a coincidence that
@apply .btnworks at all, because we process@applyrules in a single pass.That means that this happens to work:
...but this wouldn't:
Since
@applyis processed in one pass, you can't reliably apply classes that apply other classes, because we don't process them recursively until all@applycalls are gone. This may change in the future but right now it's by design.That all said, the plan for making
@applywork for more scenarios will allow you to do what you want eventually, but you'd have to write it like this:...or alternatively not use Sass, and rely on the nesting support that will be coming to Tailwind itself.
In general I am sort of hesitant to recommend working this way or promise support for using
@applyto apply component classes, because again it's meant to be used only for utilities by design. I want to be very careful avoiding scope-creep here and having what was designed to just be a simple "mix tiny utility classes into bigger component classes" feature become a full-blown mixin system like in Sass or Less. But it may end up that I can comfortably support this workflow depending on how these other improvements I'm making to@applychange the architecture of the feature, so we'll see.Until then, since you're already using Sass I would recommend just using regular Sass mixins for what you are trying to do:
I'm going to close this for now as it's not a bug or anything, Tailwind is working as designed in this case, but I'm still planning to explore expanding the scope of
@applyto handle this scenario closer to how the OP expected it to work.