With Tailwind reaching 6,000,000+ weekly downloads on NPM, as well as becoming my personal go-to for hobby projects, I wanted to understand why it ...
For further actions, you may consider blocking this person and/or reporting abuse
Some Devs seem to love CSS (like me) and some Devs seem to not be such big fans. I think making CSS easier for people that struggle with it can only be a good thing.
I generally use BEM for class names and am looking forward to functions and mixins to make that code look and read easier.
It's an exciting time to be a web developer for so many reasons.
This begs me to question if CSS would've been better off if it was a programming language that was specifically for creating CSS rules, or at least had programming features from the get-go. Apart from the advancements that SASS made (CSS Nesting, includes, etc.), I have a feeling that it tries to emulate a lot of logical stuff like functions, if statements, variables, variable manipulation, logging variables, and so on...
I realized this when I tried vanilla-extract, a build-time CSS-in-JS library, the flow of it felt really familiar to SASS (apart from the arguably ugly-looking CSS objects), that could do everything SASS can do and more since it's with an actual programming language.
Tailwind is when I stopped hating CSS.
Its tradeoffs are tradeoffs, but I feel so empowered when I know I can change markup right as I'm looking at it and just know that class is available.
That is interesting. The idea of Tailwind is great, but not for everyone. But that's so great these days, you have the choice.
Tailwind is also when you stopped using CSS :p
"class naming is hard"?
Like, are you serious? That is literally the easiest part of creating components.
Ok, so maybe "door yellow" and "door brown" is too hard to think of, when maybe someone will want "door blue not-round" or something.
You add a class, it's not that hard, at all.
The actual CSS writing is the tricky bit.
Tailwind and every other css framework's biggest problem is their naming conventions, it's like you have to learn a new syntax for each one instead of just using one class name per unique object and be done with it. oh and the horrifying markup people create with them with divitis.
All of them are great for cookie-cutter sites, and most sites are just that. Website creativity went away once responsiveness became important due to mobile phones and css frameworks became prevalent because some backenders didn't want to write CSS in the first place.
Don't give me this "class naming is hard" nonsense, come on now.
Thanks for the feedback, I thought things through a second time because of your comment, and I feel like I was able to form a better opinion, as well as notice that I tunneled into the idea too strongly and have edited the post accordingly.
Idk about website creativity and all that, I just got here lol
Agreed! 👍
You might find this interesting: nuejs.org/blog/tailwind-misinforma...
Thanks for the link, I did find that very interesting. Before drafting the initial post I had thoughts on Tailwind's drawbacks.. primarily that it gets messy very quickly, even thinking that it should have a better way to use
@apply
directives! I didn't think it through much though hence I removed it.I still feel like a utility-first approach could be done well, I understand that Tailwind was pushed/marketed very heavily but it still provided something that developers felt was good enough to switch to such a radical approach, even if arguably they have went in a different direction that what I would like them to.
I did notice my post shills too much for the approach though, will update it shortly.
All the experienced(10+) feel including tailwindcss makes the code messier and unreadable. Structure(HTML) and styling (CSS) shouldn't mix up. They learnt the hardway of inventing the names for each class.
But new developers don't have to go through the pain. Tailwindcss speeds up our development no doubt about it. So headless css frameworks are headlessui.com on rage.
There are many amazing tools which support it - like clsx which helps us to group tailwindclasses, sorter and fold to make them readable.
Yeah, most job posts I've seen that target juniors mention Tailwind, and a lot of portfolio projects I've seen also use Tailwind.
I'm a little scared that a lot of trendy frameworks place so much abstraction to things that are arguably difficult but doable, it's getting more and more easier for developers to grab a package than create things themselves, which isn't bad, just that newer devs get better by doing those difficult things, but now the instinctual reaction to a problem is to pick up a package.
Who knows, I myself am relatively new, I and my generation of devs might realize that Tailwind's drawbacks are too much, and there would be a rennaisance of traditional methods.
There is a reason beyond class naming, that is based in the history of CSS. CSS was attached to HTML but they tried to be backwards compatible, so some of the initial misconceptions remained preserved. One of the misconceptions was the global scoping of any ID´s, regardless if you name a CSS rule or an element, all IDs are part of the same namespace. This is pretty ok for a simple page, but is very likely to cause naming conflicts on larger applications and any kind of toolbox.
Today we would need a much more advanced concept of scopes and namespaces in CSS, that is not based on global ID´s. Assume you could inherit CSS rules together with a class hierarchy. Any element derived from a class could inherit the class rules. It would absolutely make no trouble do use the same names in different classes.
I know, this is a fiction only, but that was the way this kind of conflicts have been solved in OO-languages in the past. ID´s had been valid in a class context only, so you knew which rule you had to apply by the class, an element was derived from.
Svelte tries to use a similar approach, but I suppose it is still a bit limited. But is eases the pain a bit, as it uses something like a module global namespace.
There are more misconceptions of CSS, but I suppose, a lack of precise scoping is the most important one.
This is a very valid and painful point. Your idea though, it's not a fiction anymore! See CSS layers:
css-tricks.com/css-cascade-layers/
Thank you for the hint. Interesting to see if this solves the problem. I will definitively check it out.
This would be most interesting if you could create UI-elements that implicitely belong to a specific layer. I´m thinking of WC-lib´s like shoelace
That is kinda the idea. To separate rules of the framework from your application.
This is a new layer of specificity rules.
There is also
@scope
to help localize changes. A lot of good has happened in CSS. It is time to write an article about "what to learn in CSS in 2024".So, this confirms: skill issues lead to things like tailwind.
I see the problem coming from many sources:
So, the tradeoff to naming will be a tradeoff of inherently larger bundle sizes, worse performance and worst of all redesign is going to be extremely challenging whack-a-mole work.
In a component based framework (so basically any modern frontend framework) creating anything more than utility classes is just pointless. If I need the same style again, that usually means I just want to reuse the component. And if I just quickly want to lookup a style definition for a component
Button className="primary"
is telling me less thanButton className="bg-blue p-3 text-white"
. If I need to describe more complex logic it's just easier to define a strings with utility classes for each case than putting everything in different classes in another file.Well I have a point for you here. Let's say you have a list of the same component 500 times. Now every one of them has a Catalyst button with this beautiful construct on them:
className="relative isolate inline-flex items-center justify-center gap-x-2 rounded-lg border text-base/6 font-semibold px-[calc(theme(spacing[3.5])-1px)] py-[calc(theme(spacing[2.5])-1px)] sm:px-[calc(theme(spacing.3)-1px)] sm:py-[calc(theme(spacing[1.5])-1px)] sm:text-sm/6 focus:outline-none data-[focus]:outline data-[focus]:outline-2 data-[focus]:outline-offset-2 data-[focus]:outline-blue-500 data-[disabled]:opacity-50 [&>[data-slot=icon]]:-mx-0.5 [&>[data-slot=icon]]:my-0.5 [&>[data-slot=icon]]:size-5 [&>[data-slot=icon]]:shrink-0 [&>[data-slot=icon]]:text-[--btn-icon] [&>[data-slot=icon]]:sm:my-1 [&>[data-slot=icon]]:sm:size-4 forced-colors:[--btn-icon:ButtonText] forced-colors:data-[hover]:[--btn-icon:ButtonText] border-transparent bg-[--btn-border] dark:bg-[--btn-bg] before:absolute before:inset-0 before:-z-10 before:rounded-[calc(theme(borderRadius.lg)-1px)] before:bg-[--btn-bg] before:shadow dark:before:hidden dark:border-white/5 after:absolute after:inset-0 after:-z-10 after:rounded-[calc(theme(borderRadius.lg)-1px)] after:shadow-[shadow:inset_0_1px_theme(colors.white/15%)] after:data-[active]:bg-[--btn-hover-overlay] after:data-[hover]:bg-[--btn-hover-overlay] dark:after:-inset-px dark:after:rounded-lg before:data-[disabled]:shadow-none after:data-[disabled]:shadow-none text-white [--btn-bg:theme(colors.zinc.900)] [--btn-border:theme(colors.zinc.950/90%)] [--btn-hover-overlay:theme(colors.white/10%)] dark:text-white dark:[--btn-bg:theme(colors.zinc.600)] dark:[--btn-hover-overlay:theme(colors.white/5%)] [--btn-icon:theme(colors.zinc.400)] data-[active]:[--btn-icon:theme(colors.zinc.300)] data-[hover]:[--btn-icon:theme(colors.zinc.300)] cursor-default"
.Even though you have neatly packed it into a component, the HTML rendered will have this very thing 500x repeated.
If I have on the other hand:
className="main-button"
or (horribile dictu) something like this in a larger codebaseclassName="blog-post--list-item--button action-button"
+ a neat CSS class my bundle size will be much less.Maintaining is way better when obsolete code don't exist at all
CSS by invention is the inline approach best. That's why it is appealing. I tried all methods and before Tailwind was created I found that "utility first" way too powerful. Have idea to create a similar solution but Tailwind just works™ . Naming is one problem - there are a great number of solutions for structure. One way is SFC in Vue that helps organize all in native manner with helpers created from JS and for the web. We are deeply rooted in solutions that bring the most clean approach.
Utility first use naming as web native convention and add responsive option as option that isn't needed. Adding code in the same place where it belongs and focusing on more problematic issues than naming convention.
This solution 100% fixes naming, maintenance and even when there is too much class it shows where the issue is. We even think about the number of css classes to count or add ratio for issue when 20-50 classes are added in one node. But that's optimization and not something to bother. Vue should now have some automation going on for parts and in the future to rename into short hashes.
Dunno if it's "dominant", but I think it's talked about a lot because it polarizes. Personally, I don't like it.
Yeah, in retrospect, the title was too clickbait-y and didn't reflect what I wanted to actually write about, I changed the title to better fit what I wanted to share.