That's why there is this endless flow of snake oil frameworks like Tailwind and all the others.
People see some fancy demos and think "wow, so cool so easy" and "This is the newest framework, so it must be the best" and go for it.
Then over time, they get caught in a web of problems that the complexity of the framework produces.
Then a few people go for the vitamins route (plain html+css+js) and most go for the next painkiller on the market.
And I’m not dissing on CSS - just those tools try to solve different problems.
CSS is the ground truth, and it kinda has to support all the weird edge cases and uses that tailwind doesn’t.
Tailwind is like usability overhaul of css, but still allows you to “drop down to css” everywhere you want to.
It can compose like css, but it also constraints you to what you can do. It also gives you tools to group, adjust, refine styles, but in a usable way.
It’s a transpiled language on top of css, but more ambiguous than sass or less.
Given enough time most projects I work with slowly gravitate towards small composable utility classes anyway, tailwind is just logical evolution of that.
And since design peojects usually gravitate towards design systems in the long run, tailwind is really good at facilitating that.
Would be nicer if you could do it like selector > color-xyz text0xyz paddifng-xyz and never add those classes inline
I personally believe the js model is completely wrong for the browser and something like an actor model would fit much better.
I’m not saying we should jump on every hype train, and personally really dislike the react ecosystem but I also think we should encourage exploring new approaches. CSS, html and js evolution is driven by the exploration of these new frameworks and they’re very different than what they were just a few years ago
I'm puzzled to see the popularity of such frameworks while boring technologies often are well documented, well tested, highly stable, provide acceptable dev efficiency, readable by any dev, and often comes with much better performance.
I'm probably just a grumpy old man yelling at clouds.
CSS is not static. It has been getting better and better all the time and keeps improving.
For a long-term project that will require lots of development a more thorough approach would be justified.
With that said, your premise is correct. Prevention is uncool, and safety seems overbearing, preparation is met with "YAGNI". Until people need it.
There are frameworks that genuinenly improve the development experience for certain uses cases. As with many things, it's important to still now the basics (in this case, CSS), but why not use Tailwind if the philosophy aligns with yours and makes you more productive?
Sure, switching frameworks ever few months to try the hottest shit out there is also not great, and many people overuse frameworks (e.g., React is an overkill for many (most?) applications I have seen). But that doesn't mean there isn't merit in frameworks.
I'm very much in agreement with the author (regarding Tailwind, I'm Web Component-curious but yet to be convinced to the degree is obviously is...). I started with Adam Morse's "Tachyons" library which is the pre-cursor to Tailwind. Conceptually that worked for me, particularly because I was all-in on the JS ecosystem, building a startup with React and Meteor (story for another time). I wrote up my thoughts on a now-extinct blog [1].
Over time though I found JS to be a fragile and brittle ecosystem to work in; I'm sure as many others have. I not only moved away from SPAs and JS as my backend language of choice to avoid npm dependency hell, but also any JS build tools because using the latter is functionally equivalent to the former.
When my choice of language/framework at the time (Elixir & Phoenix) added support for Tailwind by default, without a JS build tool (handled by an Elixir lib) I was conflicted. I had gotten used to vanilla CSS again with all the new additions such as custom properties and wasn't convinced I needed Tailwind. Even though it didn't bring the JS build chain I hated, it still represented a hard dependency to replace down the line if required, and still required a build tool. It was potentially a decision future me would regret. These days I'm all about not snookering future-me.
I think Tailwind has it's place where you're already using a build tool that can support it (JS or otherwise) and you're working in a team that needs a design system straight out of the box. It gets you up and running quickly (particularly with their TailwindUI components and themes) and provides a point of reference for everyone working on the project without coming up with a design/token system of your own. But that can be said of the older frameworks like Bootstrap or Zurb Foundation (remember that?!).
Personally I'm very happy writing HTML, CSS & JS without any build tools, bar a bit of templating to bring in partials here and there. Admittedly I'm working on very different websites now, but I spend years thinking that the foundations of the web needed augmenting and abstracting away (they probably did at that point...), but now I'm quite happy to work with it in it's natural state.
[1]: https://github.com/jamiedumont/personal_zola/blob/main/conte...
I haven't used tw yet, but I intend to because I was blown away by how much sense the authors' book Refactoring UI made.
Which condition do you intend to treat by taking multivitamins?
Have you looked at randomized controlled studies and found that they support your idea that taking MVs has a positive effect on that condition?
Have you got your bloodwork done? Did the doctor then suggest that based on your situation MVs are the right approach? I never have heard of such a thing happening.
So yeah, TW and MVs are similar. Both appeal to people who think "Hey, why do the work and figure things out and act appropriately? I can just swallow this magic pill!".
Tailwind removes the thinking around CSS, naming, preprocessors etc etc, it just lets me write good CSS and focus on components and other engineering problems.
I seem to be one of the few people who can read CSS properties horizontally as well as vertically, so I'm all good on most peoples major complaint.
Tailwind on the other hand looks like a hellish nightmare, horizontal reading, proprietary syntax, no selector targeting of other components.
Is "horizontal reading" worse than reading two files?
What if the other file is actually 30 files compiled with SASS?
What if they're 30 files, compiled with SASS, and written by a bunch of devs who don't know CSS well, didn't use BEM or anything to name things well, and didn't organise them at all?
Tailwind isn't better than great CSS, but it's significantly better than bad CSS.
<button class="
flex
bg-blue-400
p-4
">Submit</button>
And you actually can target other components. There are lots of sibling selectors, including named groups: <label class="group/field">
<input type="text" />
<span class="order-1 text-black group-focus-within/field:text-blue-500">Name</span>
</label>To be honest, I don't find that a problem. Most frontend development is done in a higher-order abstraction like React. For the most part, I don't read HTML and I don't write HTML. If you use the right level of composition, "div soup" should never really be a problem.
Example is Tailwind. Which in the end is same as inline CSS.
Inline styles have high specificity and are often the culprit of specificity clashes.
Inline styles don't follow a design/theme, tailwind has sensible defaults for spacing/colours and consistency etc.
Inline styles are even more verbose than a tailwind class list.
Tailwind has responsive classes out of the box.
Inline styles don't really support pseudo classes....
What do you mean by this?
I have written custom css since the year 2000 and using tailwind just makes me much faster (is like setting flags) and simply by reading it, I understand how an element looks like. No matter if my past-self wrote it or another engineer.
It can pollute the HTML (although @apply helps a lot to define your reusable .title, .card, .btn, .btn-lg, .btn-primary etc), but at least it is written in HTML and not in JS, which is even harder to transfer to other eco-systems.
Also extending styles (tailwind config) is amazing if you want to reuse your styles in other projects.
- Do you care about how your html output looks? - I personally don't, just like I don't care about what my Webpack bundle looks like. Web standards will always be slower to evolve, which is why we build tooling on top.
- How do you think web components will be used? - I believe they will be used sparsely, only by libraries. But if you want to replace your frontend framework (I currently don't see why), Tailwind will not work.
We've opted to work with CSS Modules (which give you many of the Shadow-DOM advantages), but I would be lying if I didn't see the appeal of Tailwind every day. For me, it's the redundancy of having to give semantic names to elements that are already described by their React component names.
Tangentially, developers often are tempted to use classes for things that should be components. CSS classes must not be used for code reuse on a large scale, because CSS and HTML are bidirectionally coupled and you will end up search-replacing large sections of html because the design team wanted the text to align in a way that is somehow impossible without adding a div.
I don't follow. I don't see how frameworks or tools have anything to do with standards being slow.
As in: it took years to get something thats even remotely comparable to framework components. Tooling can move fast and course correct, the standards have to get things right the first time.
It's not a good comparison. You won't ever read the output of your Weboack bundle, but you will surely read the html you write (or worse, is tasked to modify or debug).
- Do you care for bloat user needs to download?
Unlike, say, Youtube which ships 2.74 megabytes of css. With amazing non-compressable unique names like .`yt-mini-app-container-view-model__loading-icon-animation` and `.yt-spec-button-shape-next--size-l.yt-spec-button-shape-next--icon-button.yt-spec-button-shape-next--segmented-end`.
And re-inventing utility classes, badly:
.yt-spec-button-shape-next--size-xl .yt-spec-button-shape-next__icon{width:24px;height:24px}
.yt-spec-button-shape-next--size-l .yt-spec-button-shape-next__icon{width:24px;height:24px}
.yt-spec-button-shape-next--size-m .yt-spec-button-shape-next__icon{width:24px;height:24px}
.yt-spec-avatar-shape__button--button-extra-small{width:24px;height:24px}
etc.
And Youtube is just an example of a symptomatic issue: everywhere CSS ends up growing beyond anything reasonable, with multiple repeated and duplicated styles that everyone is afraid to touch.Tailwind helps with this a bit: there's a fixed number of utility classes, you're supposed to use them inside components (so they are collocated, but unlike CSS-in-JS you don't write what are essentially inline styles, but chose from a fixed set of classes), and only those needed are shipped.
Of course it's easier to use. Pressing the bold button in MS Word is easier than setting up styles etc, but one makes it easy to create an impossible to maintain mess that could have been made by a primary schooler, and one makes it possible to create a consistent style that looks professional.
The only reason I think Tailwind is becoming popular now is it's exposing a bunch of things like rounded corners and drop shadows that are still cool but unlike Bootstrap you can slightly tweak your rounded corners easily. It'll still lead to everything looking the same, then people will probably ditch it and go back to really minimalist styles like HN to look cool again.
You may not like its choices but saying it creates a mess has been the opposite of my experience.
One of the main pitfalls I have noticed no longer running into is that the structure tailwind encourages prevents issues with CSS selector specificity. As a result I’ve definitely noticed fewer instances of ‘!important’ in code review.
Tailwind is a mess by default. People didn't invent separation of style and content for no reason. They did it because what they were doing before was as mess. This is that same mess.
Personnaly, I love the cascading part when used correctly, along with the 'latest' evolution of CSS such as 'calc()', variables, on top of using CSS selectors.
I think it just matches the way some people think. Nothing more than that.
It's one of many approaches that works well for some people and not for others.
Mainly that its polluting the HTML so much. I went the opposite route and am using PicoCSS now which works with semantic tags and can even work without any classes. Feels much cleaner
"The behaviour of a unit of code should be as obvious as possible by looking only at that unit of code"
https://htmx.org/essays/locality-of-behaviour/
Some people want "cleaner" and that's fine, I much prefer things to be "right there" as much as possible. Must be how my brain works
And having said that, when using Tailwind with some kind of component-centred framework, those classes will be local to a <Button> component anyway, which is exactly the same as some kind of custom component the author praises (that also needs styles within.)
That isn't even related to Tailwind, or any other CSS framework -- just that Tailwind allows you to stay in the HTML (or component) context, without having to switch to a stylesheet there.
Your JSON comparison doesn't fit: We're talking about styling, not business logic. But if you mean that I would need to define `"userAgeOver21": true` in a JSON file instead of having some `{{ %if user.age > 21 }}` in the code, then yes, I'm firmly in the latter camp. Not having to switch context often overrules pedantic purity every time.
Then your second paragraph is a great point against the need for Tailwind and the long class attributes, as you’re going to encapsulate all of that in a component (and “switch back and forth” to see its styles) anyway.
I can’t stress enough how easy it is using Tailwind, it just works! I don’t care about the long ass lines because for how I’m used to format html pages, I’d have to go to a new line anyway, it’s just that now I can understand what’s happening in react components without too many troubles.
Another plus is that by checking other people’s html code, I can immediately see their tailwind tags, without searching through files for css definitions, I see how they change their stuff there and I can immediately learn how to replicate their patterns. Imagine how fruitful saving time is, especially when using framework like nextjs, you can literally launch a prototype in few days of work with these technologies.
Don’t get me wrong, I know that you’re not going to build the next Facebook or Microsoft with Tailwind and Nextjs, they have their drawbacks, but their impact on the critical path from the idea to a working MVP can’t be ignored.
And really 20-50 tailwind classes in a single element is VERY hard to read and keep in mind. No - it does not make things clear or understandable. One tends to need to re-read and scan over from the beginning and eyes glaze over. Esp if some elements only vary with a few classes missing. I guess it works for people with very high attention to detail and high amount of working memory. I only find it personally frustrating. With a CSS class applied to that component, one at-least has a singular NAME to refer to that piece of composite styling and your memory can be used for other matters.
Maybe tailwind css works well for some bright, big-memory developers. I did try it for a couple of projects, including needing to maintain someone else's tailwind project - and only felt stupendous pain.
However, the "atomic css" philosophy behind tailwind is great. I find frameworks like https://open-props.style/ a far better application of that principle.
For example: using loops, breaking things into smaller reusable components, etc.
Tailwind devs specifically recommend against making your own abstractions in your CSS that coincide with your abstractions in your programming language.
So for example instead of CSS classes for buttons just make components for the buttons to be used directly.
The author says this about using @apply:
> Therefore, it’s simply the truth that CSS files built for Tailwind are non-standard (aka proprietary) and fundamentally incompatible with all other CSS frameworks and tooling. Once you go Tailwind, you can never leave.
How true is this? At worst you could use your output.css and at best I'd expect an automated tool that could do this conversion.
"I think the folks building Tailwind are talented and nice people. But at a pure technical level, I simply don't like Tailwind. Whoever it was built for, it was not built for me."
Instead of learning/memorising CSS properties and values, you learn and memorise Tailwind classes which are just abstractions to regular CSS properties and values and you need to write them inside class tags. I think the lure of Tailwind comes from IDE integrations and its documentation. But it doesn't add any "new features" that enables rich web applications which CSS lacks in anyways.
Recently, I started a new project for work with Blazor, and I felt at home again. It was weird, just a relief to work with what I know best.
I'm not saying Blazor is good or you should use it, but for me, coding was fun again. I truly hope I do not have to work a lot with JavaScript ever again. I just do not enjoy it. Maybe I have to go to full backend after so many years of full stack.
Don't we need to define the custom element <whatever-you-can-dream-of> using javascript first?
All my knowledge about custom elements comes from this Mozilla doc: https://developer.mozilla.org/en-US/docs/Web/API/Web_compone...
If custom elements is the way to go, it sounds like a lot of javascript and coding overhead that I have to take. Doesn't it?
If all you want to do is prevent the "div/span-tag soup" as he calls it, you don't have to register anything, though. You can just write <ui-card><ui-card-header>My header</ui-card-header></ui-card> and style that using regular CSS à la ui-card { background-color: red; }.
This is a hill I will die on: Blog posts should have a date at the top.
And yeah. That <fancy-component> that is seemingly not an eyesore? It's not because Tailwind is bad and "pollutes HTML". It's because web components hide any and all ugliness from you so that you can pretend they are beautiful.
Because in the end there's literally nothing on the web but divs and spans
[1] From web component report by people making them: https://w3c.github.io/webcomponents-cg/2022.html
It's worth noting that many of these pain points are directly related to Shadow DOM's encapsulation. While there are many benefits to some types of widely shared components to strong encapsulation, the friction of strong encapsulation has prevented most developers from adopting Shadow DOM, to the point of there being alternate proposals for style scoping that don't use Shadow DOM. We urge browser vendors to recognize these barriers and work to make Shadow DOM more usable by more developers.
I guess it drills into a part of human nature where we are always measuring ourselves and our things against others.
Technology-choice as fashion needs to die. There are suitable tools for the job, and unsuitable ones. Deciding between them gets harder when loads of amped up juniors are selling each other on the benefits of the latest and greatest without actually putting them to the test over the course of years/multiple projects/iterations.
Every design system build on top of HTML is just an abstraction that adds layers of complexity whilst reducing the inherent flexibility of HTML. It's much like the years when every SPA framework rebuilt the concept of a back-button and page history, or standard HTML form inputs. All were shittier versions of what the browser provided (even if imperfectly at times).
In Svelte, There is less need to use Tailwind, because HTML, CSS and JS (or TS) are all encapsulated in a single source file. Editing CSS alongside the HTML is easier than bloating the HTML with a class hell. You can use native syntax highlighting, IntelliSense, early compiler error catching and linting plugins of your editor.
I can understand and appreciate what Tailwind is all about. It's a standards approach to naming conventions and puts all the details in the markup. Which has its value.
I've found a happy balance to be:
1. utility classes for layout and structural details
2. custom classes for look/feel details
3. after x utility classes, its time to combine into a single class
x is very much based on situation and intuition not a hard rule.
I'm still using LESS because of nested css, and classes can be composed.
One benefit of LESS is the style code is decoupled from react/angular components and more importantly the shadow dom.
After a while of using Tailwind at work, I have started to love it. It it just so much more productive and I rarely need to step into css-land anymore. You still need to know and understand how CSS works in order to get the most out of Tailwind.
Tailwind is just like CSS but with shortcuts ready there for you to use.
And THAT right there is the core problem of such frameworks.
The trinity of frontend technologies, by design, have a clear separation of concerns: HTML structures, CSS styles, JS implements logic.
Of these 3, JS is, by necessity, the most powerful, and the one that can change the other 2 the most. So, as programmers like doing cool things, the temptation is always there to just write some JS that grabs the other 2 and does whatever with them.
This would, in theory, be fine...if there was a universally agreed way to do this. The problem is, there isn't. We still pretend, and can even implement it in a way, where the concerns are actually separated (thanks to serverside rendering we can even do so dynamically), and we have not one method of violating this separation of concerns, but a gazillion ways, spanning the full range of compatibility from "no problemo" to "are you crazy?".
This needs to stop, I say desperately, while being fully consciouss of the fact that it never will, since the genie is already out of the bottle and has been for a long time.