2021-03-05
A hack for missing @at-root for Tailwind CSS Plugin
tailwind, tailwindcss, hack, SASS
tailwind, tailwindcss, hack, SASS
I was creating a Tailwind CSS ("TW") plugin, @downwindcss/debug. for a utility outline-{n} to apply outline.
The utility should apply to a whole page when a user adds the utility class anywhere in the DOM tree.
Basically @at-root in SASS.
When you add a utility, you can use a CSS-in-JS syntax, to refer to the parent with & (ampersand).
My attempt was to do was to apply to descendants of <body /> (line #5, "body *, &").
1const numberedOutlines = Object.entries(values)2 .filter(([key]) => key !== "DEFAULT")3 .map(([key, value]) => ({4 [`.${e(`outline-${key}`)}`]: {5 "body > *": {6 outline: `${value} solid red`,7 },8 },9 }));
But TW appended .outline to the output.
1.outline body > * {2 outline: 1px solid red;3}
That's not the selector I wanted. I wanted a simple body > * to apply the outline to the whole page!
As & refers to the parent selector, .outline, I was adding & either to the left or to the right separated by ,.
1"body > *, &": {2 outline: `${value} solid red`,3},4
5// or6
7"&, body > *": {8 outline: `${value} solid red`,9},
But both of them still appeneded .outline in front of body like,
1.outline body > *, .outline2// or3.outline, .outline body > *;
Ok, frustrated I was, I decided to hack it by excluding the current & and including it again (body * > :not(&), &).
1const numberedOutlines = Object.entries(values)2 .filter(([key]) => key !== "DEFAULT")3 .map(([key, value]) => ({4 [`.${e(`outline-${key}`)}`]: {5 "body * > :not(&), &": {6 outline: `${value} solid red`,7 },8 },9 }));
You can see that outline-5 was applied somewhere in the DOM tree and outline was applied to the whole page.
(disregard the fact that it's showing outline-4 cuz it's WIP 😅)