Stefan Judis Web Development

Stefan Judis Web Development -

How to style element descendents with Tailwind CSS (#tilPost)

I'm maintaining a project built with Tailwind at work. I'm no daily Tailwinder, but usually, I manage just fine. But recently, a trivial task took me quite some time to get right. I wanted to rotate an SVG icon depending on the details element's :open state. Getting started with Tailwind is straightforward (a CSS property just maps to a class name, right?), but I still have to wrap my head around advanced features like class-based element relationships. How would you achieve the following CSS in Tailwind? details:open svg { rotate: 0.5turn; } Option 1 — don't use Tailwind and go vanilla CSSWhen googling around, you'll find the advice to "just use" CSS and import a CSS file somewhere. Sure, this works, but what's the point of this? Tailwind promises to solve the CSS maintenance problem, so I don't have to think about class names and where to put which parts of my CSS. I'm not gonna sabotage myself by adding custom CSS. So this option was a big "NO NO" for me. 👎 Option 2 — Use the group selectorThe second option I discovered was to rely on parent-based styles. <details class="group"> <summary> Open me <svg class="group-open:rotate-180"> <!-- SVG stuff --> </svg> </summary> </details> You define a parent boundary (group) and then style an element depending on the parent state (group-open:rotate-180). The selector translates to "If an element's group parent matches the [open] attribute selector, rotate it by 180 degrees". Here's the resulting CSS: .group[open] .group-open\:rotate-180 { --tw-rotate: 180deg; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } The group class doesn't have styling and only matters when used with the group-modifier (group-open). At first, this approach felt a little icky to me, but it is very smart! Here's a Tailwind example to see the group selector in action . Option 3 — Use arbitrary variantsWhile the group selector works, it twists my brain because it's somehow backward. Could you somehow style elements more like in the CSS way? Arbitrary variants allow you to write custom combined CSS selectors that aren't included in Tailwind. If you want to style all paragraphs in a div and avoid adding a class to every p element, use this funky Tailwind syntax — [&_p]:text-xl. It roughly translates to "Increase the font size (text-xl) of all paragraphs in this element ([&_p])". Here's it in action. <div class="[&_p]:text-xl"> <p><!-- paragraph stuff --></p> </div> And here's the resulting CSS: .\[\&_p\]\:text-xl p { font-size: 1.25rem; line-height: 1.75rem; } To solve the problem and rotate our SVG, we could rely on another arbitrary variant — [&_svg]:open:-rotate-180. <details class="[&_svg]:open:-rotate-180"> <summary> Open me <svg> <!-- SVG stuff --> </svg> </summary> </details> And this is the compiled CSS: .\[\&_svg\]\:open\:-rotate-180[open] svg { --tw-rotate: -180deg; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } The more I dive into custom Tailwind features, the more I'm amazed. Some features are very funky! Odd, but funky! Here's a Tailwind example to see an arbitrary variant in action . ConclusionIn the project, I went with the arbitrary variant solution. But after reading more about it, I'll try to get my head around the group selector. Why? Tailwind doesn't only help with CSS maintenance but also with CSS performance. Large CSS codebases tend to grow and grow over time. Do you need another component? Great, add another 300 lines of CSS! Do you need a button variation? Easy, add another 50 lines... Hand-written CSS is hard to maintain but also leads to slower sites. The longer you work on a project, the bigger the CSS becomes. And CSS blocks rendering. The more CSS you ship, the longer you wait for the first paint. In Tailwind, all classes are already defined, and the CSS size remains somewhat the same. Sure, the HTML can look terrible, but if the render-blocking CSS isn't becoming enormous, I'm happy to take the ugly HTML. Tailwind parses project templates to remove unused CSS classes. If you're starting, your CSS will grow because more Tailwind classes will make it into production. But I think the argument holds: if you used enough Tailwind classes your CSS bundle size will grow less than with hand-written CSS. But what happens when you use fancy arbitrary variants like [&_svg]:mt-4? Tailwind has to parse your markup and make up the CSS on the fly. This new class variant is then added to your compiled CSS and it increases the overall CSS size. And I don't like that. 😅 So for me, the winner is option 2 because it feels like the natural Tailwind approach and doesn't increase the CSS size. Win-win! 👏 Do you know of other options that I could have used here? If so, I'd love to hear them! Reply to Stefan

本文介绍了如何使用Tailwind实现根据details元素的open状态旋转SVG图标的CSS样式。作者提出了三种解决方案,最终选择了使用group选择器。Tailwind的优点包括CSS维护和性能方面的提升。

CSS SVG Tailwind group选择器 性能提升

相关推荐 去reddit讨论

热榜 Top10

LigaAI
LigaAI
Dify.AI
Dify.AI
观测云
观测云
eolink
eolink

推荐或自荐