Hacker News new | ask | show | jobs
by littlestymaar 628 days ago
I don't understand the fascination for tools like Tailwind (or bootstrap before that). Sure when your doing very basic things it sounds cool to be able to use just a simple class to get a cool style, but then when used in hanger you end up with a list of class like this

    `fixed flex items-center w-full max-w-xs p-4 space-x-4 text-gray-500 bg-white divide-x rtl:divide-x-reverse divide-gray-200 rounded-lg shadow top-5 right-5 dark:text-gray-400 dark:divide-gray-700 dark:bg-gray-800"` [1] 
and then I really don't understand what you've gained compared to using CSS directly…

[1]: this class is taken from a flowbite component I've worked with no latter than yesterday. https://flowbite.com/docs/components/toast/#simple-toast

8 comments

I really agree on that one. Being able to define SOME (and I insist on that point) style directly in HTML is super convenient and can be a huge time saver day by day. But I think Tailwind went too far by trying to entirely replace CSS with countless classes and shortcuts. Just imagine the learning curve and the time spent by devs trying to find the right syntax for a specific transition or such...

I like the approach of tools like Perseid (https://perseid.dev/docs/ui/styling/classes), focusing only on layout design and providing a small set of built-in CSS classes (alignments, positions, margins, dimensions, …) for that purpose. All the rest (colors, shadows, fonts, animations and such) lying in good old CSS declarations.

Writing vanilla CSS often involves the hassle of coming up with proper class names, which can become tedious. That's where Tailwind CSS shines, as it allows you to apply styles directly with utility classes. However, repeatedly using the same classes and writing many of them can become cumbersome. To simplify this, FlyonUI introduces semantic classes to streamline your work. For example, instead of writing multiple utility classes for a button, you can simply use `.btn`, and your button styling is ready to go.
This is like a backend developer asking someone using a spreadsheet why don't they just build their own database. Or a sysadmin telling you why don't you just run your own Kubernetes cluster. Unless there's like a 10 person team working on the same thing, you gotta take shortcuts somewhere.

Not here to argue that learning CSS properly isn't better, but I legit have no interest in doing so. I can copy-paste that code and be sure it'll look exactly the same on my website. I can't do the same with CSS.

To be clear, you have to 'learn CSS properly' to make sense of Tailwind. I don't see how someone can not know CSS, but know Tailwind. Tailwind is just atomic classes for the underlying CSS styles.
> I don't see how someone can not know CSS, but know Tailwind.

I've met a fair amount of devs (specially younger, <30yo fullstack devs) who have not written raw CSS at all and just use Tailwind. They are employed and get paid decently well.

Tailwind is a massive time saver, and I can see the appeal.

I can honestly say that tailwind made me way better at CSS. Going through the docs to find classes I needed to do particular things and reading what they did had made me so much better at understanding what it does at a low level. I would still prefer not to write tailwind classes rather than struggle with naming bespoke classes and writing all the CSS but it's definitely made me a better and faster frontend developer
I had my doubts, but Tailwind's mantra "looks horrible, but you need to try it!" turned out to be true for me.

You can think of Tailwind as the "APL of CSS." A single utility class can generate a lot of CSS for you, which is one advantage.

The key benefit of Tailwind is that it co-locates your CSS with your HTML, reducing cascading issues and improving maintainability.

Like any codebase, you can use your tools to add more structure and meaning.

For example, I like using a tw function like this:

    export const tw = (...classes: (string | undefined | boolean)[]) => classes.filter(Boolean).join(" ");
Using the tw function, your example classes would look something like this:

    class={tw(
      "fixed top-5 right-5 w-full max-w-xs p-4",
      "flex items-center space-x-4 divide-x divide-gray-200 rtl:divide-x-reverse dark:divide-gray-700",
      "rounded-lg shadow",
      "bg-white text-gray-500 dark:bg-gray-800 dark:text-gray-400"
    )}
I like splitting the classes into logical groups. In this case, I’m grouping by: 1) base positioning, 2) flex behavior, 3) effects, and 4) colors.

Finally, the filter in the tw function allows for easy conditional classes:

    class={tw(kind === "something" && "m-4 p-4")}

I also use Biome, which has a work-in-progress but already quite good class sorter for Tailwind [1]. This keeps the code tidy by applying a logical sort order to each string passed into the tw function.

--

1: https://github.com/biomejs/biome/pull/1362

Hello littlestymaar,

Thanks for sharing your thoughts.

To deal with the huge number of class lists like this

`fixed flex items-center w-full max-w-xs p-4 space-x-4 text-gray-500 bg-white divide-x rtl:divide-x-reverse divide-gray-200 rounded-lg shadow top-5 right-5 dark:text-gray-400 dark:divide-gray-700 dark:bg-gray-800"` [1]

We've created Flyon UI, to combine the best of both worlds: the aesthetic appeal of semantic classes and the powerful functionality of JS plugins.

With FlyonUI you can achieve this with semantic classes like:

btn btn-primary

for more details: https://flyonui.com/docs/third-party-plugins/notyf/

> With FlyonUI you can achieve this with semantic classes like:

> btn btn-primary

That's obviously the better way, but then it's not Tailwind anymore. You're just using class and CSS directly.

It's more ergonomic than using stylesheets.

- No external stylesheets. No need to think about optimising the serving of CSS assets (e.g. with CDN)

- Co-locality: work on styling right where the element is, you don't have to figure out which stylesheet affects a particular element.

- No naming headache, as there's no need to give class names to elements in order to style a particular (or set of) elements

These days HTML is served compressed, with gzip/brotli, so long class attributes won't bloat the resulting file size by much.

Stylesheets still has its place of course.

A lot of people find tailwind easier to use because it cuts out the steps in CSS where you have to come up with all those names for elements/containers/wrappers etc and define the styles for them all.

The big long lines of classes are often only written once anyway as web development usually makes use of components or partials for repeated elements.

Obviously others can continue to use CSS if they prefer to do it that way.

you've gained:

- fine-grained design tokens (p-63 doesn't exist)

- freedom from having to name things prematurely

- not having to jump back and forth between index.html and styles.css

> freedom from having to name things prematurely

> not having to jump back and forth between index.html and styles.css

Nobody prevents you to have your style directly in the HTML files (or in the JSX components, AKA CSS-in-js). Even though with split screen and keyboard shortcuts to switch I fail to see how this is an argument …

> Nobody prevents you to have your style directly in the HTML files (or in the JSX components, AKA CSS-in-js).

Why not just use Tailwind in your JSX components?

> Why not just use Tailwind in your JSX components?

That just is out of place here: using tailwind means using inline style + having a CSS stylesheet (tailwind's stylesheet) at the same time. It's pure overhead.

I don't know, feels more natural to me. Tailwind was a godsend.