Closed unformatt closed 2 years ago
Will look into this in more detail when I can but wanted to quickly answer this part:
Why is this a circular dependency?
.my-border {
@apply border-2;
}
.bar.my-border {
@apply my-border;
}
The part that is a circular dependency here is just this part:
.bar.my-border {
@apply my-border;
}
@apply
in Tailwind 2 will apply all instance of a selector, so this is trying to apply my-border
within another selector that already contains .my-border
triggering a circular dependency.
Consider with different names:
.foo {
color: blue;
}
.bar.foo {
color: red;
}
.potato {
@apply foo;
}
The output of this is:
.foo {
color: blue;
}
.bar.foo {
color: red;
}
.potato {
color: blue;
}
.bar.potato {
color: red;
}
In regards to the last example, I don't think it's intuitive behavior that @apply foo
would pick up styles from .bar.foo
.
I don't think it's intuitive behavior that @apply foo would pick up styles from .bar.foo.
You say that now but if you had this HTML:
<div class="group">
<div class="group-hover:bg-black text-red-500 font-medium">...</div>
</div>
...you'd expect this refactoring to work right?
<style>
.custom-class {
@apply group-hover:bg-black text-red-500 font-medium
}
</style>
<div class="group">
<div class="custom-class">...</div>
</div>
The only way for that to work is for @apply
to consider every use of a class name in the stylesheet. The guiding principal for what the correct behavior of @apply
should be is "if you extract a list of classes from your HTML into a custom class using @apply
, your code should work the same way it did before".
I have a use case for this, where I don't want @apply
to pickup styles from every css class
I am using element UI as my framework for frontend.
Now I would want to apply w-full
to say upload element but it won't work because the width is set to some child div tag.
Now to solve this I am doing this
.w-full {
.el-upload {
@apply w-full;
.el-upload-dragger {
@apply w-full ;
}
}
}
Now I can use a different out class, but the reason I want it to be called w-full
is to keep my class names similar to tailwindcss.
The possible solution would be
.w-full {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
}
}
}
But again w-full
is simple behaviour. It would be a prob if I want to apply color or margins etc
@adamwathan
I have a similar issue where tailwind 2 does not allow me to apply a generated class, even though I do not see how this is an actual circular dependency:
@layer base {
.bg-magenta.text-white .rte a[href]:not(.cta) {
@apply text-white;
}
}
I am using .rte
("real text editor") like .prose
is used in @tailwindcss/typography
. All CMS output (which will not contain tailwind classes) is wrapped in .rte
containers.
So this says:
Now tailwindcss answers with:
You cannot
@apply
thetext-white
utility here because it creates a circular dependency.
I am not wanting to apply anything to .bg-magenta.text-white
(which could cause a circular dependency), but, actually, to its decendant elements .bg-magenta.text-white .rte a[href]:not(.cta)
.
So I fail to understand wht this case is considered a circular dependency.
What am I missing? Is the heuristic for circular dependencies correct?
What can I do? Is reverting to color: theme('colors.white');
my only chance?
I'm having a similar issue on a Phoenix app, it works fine with Tailwind 2 and esbuild as in this Phoenix PR and this tutorial but if I try to use the @layer
directive, I get a RangeError: Maximum call stack size exceeded
error.
Here are the details on my CSS and config:
https://gist.github.com/jaimeiniesta/79dd351e77a7537b7b5c6e908d128ff2
It works fine if I put my classes outside the @layer components
block.
Update: I found where the circular dependency was in my CSS:
div.leading-relaxed p {
@apply leading-relaxed mb-4;
}
I will fix that on my side, but I wanted to report that this doesn't fail unless it's inside a @layer
directive. If my main app.css
file is like this:
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
@layer components {}
div.leading-relaxed p {
@apply leading-relaxed mb-4;
}
Then it works fine and generates:
.leading-relaxed {
line-height: 1.625;
}
div.leading-relaxed p {
margin-bottom: 1rem;
line-height: 1.625;
}
But, if I move that inside @layer components
like this, it fails with a maximum call stack size exceeded:
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
@layer components {
div.leading-relaxed p {
@apply leading-relaxed mb-4;
}
}
I was doing something like:
textarea {
&.hidden {
@apply hidden
}
}
makes sense that there is a circular dependency, it just got detected in tailwindcss 3, solution is just to do:
textarea {
&.hidden {
display: none;
}
}
Hey! Thank you for your bug report! Much appreciated! 🙏
In the latest version we detect circular dependencies and notify you instead of causing an infinite loop 👍
@RobinMalfait are you referring to the last comment about an actual circular dependency or the original bug report here which about a non-circular dependency being reported as a circular dependency?
What is the proper solution with Tailwind 3 to avoid circular dependencies but still explicitly define styles and re-use class names?
Wrong:
#cms-output .clear-left {
@apply clear-left;
}
Right: ?
@unformatt multiple things are happening here:
This is still a circular dependency:
.my-border {
@apply border-2;
}
.bar.my-border {
@apply my-border;
}
Because you are applying my-border
in function of my-border
.
The goal of @apply
, is to make sure that you can substitute the new selector with all the things you are applying. Therefore we have to apply all known definitions. I wrote more about that here: https://github.com/tailwindlabs/tailwindcss/issues/6451#issuecomment-997034450
@jstrangfeld the short answer is, don't use utilities in the selector and in the @apply
, a longer answer can be found here: https://github.com/tailwindlabs/tailwindcss/issues/6451#issuecomment-997034450
For your specific use case, update:
#cms-output .clear-left {
@apply clear-left;
}
To:
#cms-output .clear-left {
clear: left;
}
@RobinMalfait
I have found a false positive.
The following worked in TailwindCSS 2, but is broken in TailwindCSS 3:
@layer base {
.rte a[href]:not(.cta) {
@apply text-magenta; /* Note: text-magenta, not bg-magenta. */
}
/*
* False error in next selector below:
* You cannot @apply the bg-magenta utility here because it creates a circular dependency.
*/
.bg-magenta.text-white .rte a[href]:not(.cta) { /* line 11 */
color: theme('colors.white');
}
}
I get the following error reported:
@parcel/transformer-postcss:
/src/tailwind/custom/base/rte/hyperlinks.css:11:4: You cannot `@apply` the `bg-magenta` utility here because it creates a circular dependency.
This must be a false positive, because in line 11 I do not @apply bg-magenta
at all.
In line 11, tailwindcss might dereference .rte a[href]:not(.cta)
, which does apply the foreground color @apply text-magenta
. But it does not @apply
the background color bg-magenta
. .bg-magenta.text-white
here is just a selector. (Flipping/inverting from a common color on white scheme to a special white on color scheme.) No @apply bg-magenta
and no @apply text-white
either.
Side note:
The entire section is wrapped in @layer base
, which, I thought, might protect the selector from being dereferenced. But in TailwindCSS 3, this does not help. The selector is read as if it was an @apply
anyway.
Am I getting a false positive here?
.input {
> div {
@apply bg-dark;
.bg-dark & {
@apply bg-body-light;
}
}
}
This gives me this error message:
You cannot `@apply` the `bg-dark` utility here because it creates a circular dependency.
316 | @apply bg-dark;
317 | }
> 318 | .bg-dark .input > div {
| ^
319 | @apply bg-body-light;
320 | }
@robocub you should open a new issue, also yes it's an infinite loop, what did you expect the generated CSS to be?
In general it's better not to extend tailwind classes and create one own's classes
I've found a way to get around this as well
This should work
*:has(.bg-dark) .input > div {
background-color: theme(colors.body-light);
}
Just interesting fact that such code causes error during styles compilation, because CSS class flex is reserved by Tailwind
.field {
.control {
&.flex {
background: red;
}
}
}
But like workaround you can just replace .flex
with [class="flex"]
and compilation works without errors.
.field {
.control {
&[class*="flex"] {
background: red;
}
}
}
Describe the problem:
After upgrading to Tailwind v2, my webpack build started hanging during the building phase
It seems to be that a compound selector is causing an infinite loop and is not triggering
RangeError: Maximum call stack size exceeded
. Also not triggering Tailwind's circular dependency detection.Secondary issue
Why is this a circular dependency? https://play.tailwindcss.com/lS1DnjwS6g?file=css
Link to a minimal reproduction:
https://play.tailwindcss.com/UO2eaaZ0AD?file=css
tailwind.zip