Hacker News new | ask | show | jobs
by hbn 1694 days ago
I get why people are skeptical of Tailwind, and I was too when I started a job at a new place that used it for their frontend, but now I'm totally onboard and use it for all my personal projects. Incidentally I'm wearing my TailwindCSS shirt today!

It really fixed a whole slew of my biggest pain-points with CSS. The biggest one being that you have to jump between files when modifying a single UI. Which isn't just annoying while developing, but it's also even more frustrating when refactoring and you have to come back to some files you haven't touched in a long time, trying to cross-reference ID names and styles between the template and the CSS.

It's also just way more concise than typing CSS which helps with the fast iteration. e.g. jumping to a different file and typing

#id-name { margin: auto; }

vs just being in the tag and typing

`class="m-auto"`

Maybe it doesn't seem like that huge of a difference, but I find it saves me so much mental overhead when I'm in the flow of putting together a UI, and I work way faster now. It's also really not that difficult to learn the syntax, which stays pretty consistent throughout all the different CSS properties you can apply. Also the responsive syntax is so much nicer than the typical "@media screen blah blah" syntax is vanilla CSS

On top of this, it's not even just a different way of writing CSS - you inherently end up working in a built-in design system that you can tweak to your liking. For example, the margins go up in units of 0.25rem, it comes with a pretty good built-in color palette (that you can add to/modify in the config), etc. Which keeps you on something of a consistent grid, and is really good for teams where you don't want some new guy coming in using weird sizings or units.

If you don't like the idea, I'd urge you to give it a real shot, even on a small application. Try converting styles on a page to Tailwind. I think it's worth it in the long run.

5 comments

On conciseness (and possibly scale), isn’t the css “bloat” just being shifted to the html file instead? Has there been sufficient studies in comparing tailwind to say something like:

.MyHeading {color: red; font-weight: bold} // Left container <h1 class=“MyHeading”… // Right container <h1 class=“MyHeading”…

Think about it in terms of components.

// Left container <MyHeading />

// Right container <MyHeading />

What's the point of a .MyHeading class in this instance? Why are you spending so much time naming things solely to reference them in a separate file?

In my Tailwind projects I can have an entire components/ directory with just .jsx files. No more having to spend time naming one-off elements, or cross-referencing class names with separate definitions in separate files.

> No more having to spend time naming one-off elements

Doesn't this make them untargetable if you ever use it somewhere else? Plus, it already has a CSS name: whatever you named the component (and therefore its folder).

UI code should be modular, component-based, and lends itself to being logically grouped into single folders or files:

MyComponent ->index.tsx ->style.css

Or for vue just MyComponent, etc.

Now, this component has all the abilities that we tap into these frameworks for in the first place: it's composable, it's targetable by a known & unique name, we can use it anywhere without restriction.

I don't even want to imagine a world where I render some component and it has no targetable name... Terrible for reuse

What do you mean by targetable? The only thing that should be modifying the styles of MyComponent is itself. Any necessary changes should be exposed through the component's public API. Because of this, whether the styles live inside the component itself or in an adjacent css file doesn't matter.

What he means by naming one off elements is that within MyComponent there are multiple native elements that may need to be styled.

Maybe I don't understand your concept of reuse well, but I certainly don't think all components can just be slapped into the flow of an arbitrary parent container and have the right positioning and styling for free, and if you have to target those off of emergent behavior (i.e. Tailwind classes making it look some way), you are doing something very error-prone.

I also don't think it makes sense to imply the component's creator can know all possible circumstances it will be rendered in and can therefore make an insightful API to control these things. Instead, we can target the fact that CSS is a public API to control styling choices, and expose the classic handle into that API...

I disagree that you commonly need to style component internals from the outside. But when you do, exposing html class name injection points works fine. By no means should you be writing css to target a component's internals from outside of the component's own css file. That leads to a mess and is the opposite of reusable. The HTML structure of a component is private.
A point that is not immediately front of mind in these discussions is that Gzip/brotli makes these comparisons moot. Similar strings will be referenced with a pointer and take basically zero extra bits down the wire. That's one place where tailwind get's a huge boost. It's a ton of repetitive code that compresses extremely well.

If you use a plugin to sort your class names like Headwind[0] then it can be optimized even further.

0: https://marketplace.visualstudio.com/items?itemName=heybourn...

> The biggest one being that you have to jump between files when modifying a single UI.

This is why I still like Vue files over React ones. Vue files can have a <template> tag containing the HTML structure of the component, a <script> tag containing the functionality, and a <style> tag containing the CSS.

That's one of the things I like about Svelte and Vue, everything is together in one file. Here's a simple example from the Svelte tutorial: https://svelte.dev/tutorial/numeric-inputs (click the "Show me" button).
Wait until you try styled components
I've used both. I prefer Vue for the continuity between other projects using CSS. Styled components is fine but it adds just a little more friction and ambiguity.

With Vue I know exactly where the CSS goes. With Styled components, Im still in JS land where things can be defined wherever whilly-nilly as a template string; imported, passed around, and manipulated. It's a small thing, but those add up.

Yeah, I don't get styled components, the syntax and organization looks like a mess. I love using Stylus with Vue single-file-components, it lets me use a lot of CSS-specific patterns and macros.

Using Stylus blocks, I like making things responsive just by defining a media query in a block and then doing like:

.container

  flexRowCenter()

    +desktop()

      flexColumnCenter()
Better, but still needs that linking, and you loose your glancable html structure in.
> It really fixed a whole slew of my biggest pain-points with CSS. The biggest one being that you have to jump between files when modifying a single UI.

I’ve heard this before, and I’m always confused by it. The way I build components is that the component has one co-located scss file that lives right next to the jsx. MyComponent.jsx has a MyComponent.scss. It may import other mixins, functions, or variables using @use, but I usually don’t have to actually navigate to any of those files. So, I’m usually just looking at that one component scss file. How are people structuring their css that they’re dealing with multiple files for a single component? Will one part of the component have a class from one file and another have a class from another file?

OP means you are looking at both the structure of the DOM (JSX) and the CSS (className).

The “tailwind” effect is due to fast feedback and iteration - there is no jumping between two files (DOM file and CSS file).

Of course this also leads components eventually having huge lists of classes.

But I think the fast feedback loop is worth it, because with 2D visual artefacts and the complex CSS language, often the only way to learn/get what you want is change a little, reflect, change a little, … etc.

> there is no jumping between two files (DOM file and CSS file)

I don't view this as any more difficult than navigating a long file. Maybe I actually view it as more simple upon making that statement. What development environment are you using? Hotkeys to switch tabs is fairly base-level stuff

> often the only way to learn/get what you want is change a little, reflect, change a little

Which surely any person who is arguing for "fast feedback" would do using the browser's dev tools so you can edit CSS and instantly view the result in the same window as your actively painted view...

I would look into getting a proper editor like VSCode, setting up hotkeys, and learning to use dev tools if I was you. It sounds like you are using VIM to make your website

It’s not just the “jumping between files” that takes longer.

It is also mentally computing the “CSS cascade” to determine the final rules for a given DOM element, and keeping in mind all classes that apply.

The dev tools often cannot save styles back to your source code when you use a build step.

Even if I get my file switch down to 16ms, it is 16ms more than 0.

If I can view the JSX and see all the final styles on the element or on a nearby parent, it results in a faster feedback loop.

I am not for or against Tailwind, as I have mentioned this directness causes a lot of classes on single elements which can be hard to read later, but is often faster to edit whilst you are writing it.

> It’s not just the “jumping between files” that takes longer

This language you've used is imprecise and suggests jumping between files is a problem. The alternative is jumping from your IDE to Tailwind docs unless you are a tailwind expert no? This sounds like I'd measure it in seconds and not make a facile 16ms estimate so I could write 16ms > 0 and look smart...

> The dev tools often cannot save styles back to your source code when you use a build step.

... 5 seconds ago you were arguing about speed of iteration, now the fastest possible iterator is a problem because you have to manually curate what you save in the end. How is this not a problem when you're just slapping classnames onto something and hoping it looks right? You have to go back thru your save history or to git when you fuck up, again something I'd measure in seconds

> If I can view the JSX and see all the final styles on the element or on a nearby parent, it results in a faster feedback loop

> It is also mentally computing the “CSS cascade” to determine the final rules for a given DOM element, and keeping in mind all classes that apply.

I just feel like you must be really bad at CSS to feel this way. CSS should interact with a component's private structure only in that component's CSS file, it should expose styling & sizing variables thru a CSS var API, and its top-level container's style & position are the only legally targetable things by someone else rendering it. This does not leave any room for having to "keep in mind all classes that apply", that is a drawback only to Tailwind.

Anyways, I don't get why you argue in this fashion just to walk it back at the end as "faster to edit whilst writing" when you discarded the fastest possible solution because of externalities to it that you're unwilling to consider here. For example, loading up a normal component, I simply glance at its CSS file to see all styles applied to it; not so many fancy layers. This means it is very fast to resume writing it. For Tailwind, you clearly need to first build the mental model of all the styles applied and any interactions between them, and then second you need to go to Tailwind docs to see what styles are actually being applied in terms of CSS. It has a layer of misdirection that drastically reduces speed if you don't just sweep it under the carpet. "Dev tools can't autosave for you" is an absurd complaint in the face of brushing all this aside

I can work with or without Tailwind to be honest, I was commenting on the principles that are making Tailwind popular.

> The alternative is jumping from your IDE to Tailwind docs unless you are a tailwind expert no

No, as the class names directly map to CSS key/values and the IDE auto-completes the classes. If you know vanilla CSS, you would pick up the Tailwind classes quite quickly.

> "CSS should interact with a component's private structure only"

> "that is a drawback only to Tailwind"

CSS specificity/cascading is part of vanilla CSS.

And what happens to deeply nested components? Are you are using your build step to prevent CSS cascading, giving each of your component classes a UUID?

Instead of using the Chrome dev tools, I am currently using live reload to refresh the page after any HTML/CSS changes.

When you edit your HTML + CSS in the dev tools for fast feedback, are these edits written back to your CSS source files (I assume this is not possible, as they are part of the build process)?

What's your CSS build set up?

I guess I've never seen the problem with switching files. I have two tabs open and use cmd-shift-] and cmd-shift-[ to flip back and forth quickly. There's no friction at all. The benefits of keeping the concerns separate outweighs any benefits to only having one file open.
No, I agree, I develop with one .scss file per component. The issue is bouncing between markup and styles.

If I've got some outer div that's a container for other, inner things, why do I need a name for it? It's much easier to just say how it should look within the context of that component than it is to come up with a name and put the styles for that name in another area of code. I want a 1rem horizontal margin? I set a class of mx-4. No need to name it, no need to jump to another area of code, I just put the styles in the context of where I'm laying out the element.

> The biggest one being that you have to jump between files when modifying a single UI

Can you expand on why you were doing that in the first place?

Your comment reads like CSS just finally clicked for you (e.g. reusing classes instead of specific IDs, and the entire principle of cascading/inheritance) and are attributing that to Tailwind or something.

It’s a completely different approach from the normal way CSS is used. With Tailwind the classes describe what it should look like directly rather than what it is. Yes, it is still accomplished using CSS, but it’s definitely not the way most people use it.
Bootstrap and numerous other popular CSS frameworks, notably any with grid layout and/or utility classes, have done that for the past decade+. So Tailwind is the modern/popular CSS framework?
No, they haven't. Tailwind is basically just a lot of utility classes which you use to set css values.

Other frameworks generally combine multiple properties with their classes.

It is a very different design choice with it's own up and downsides but equating it to bootstrap is just silly.

It's more realistic to compare it to directly setting style attributes on html tags then bootstrap, but that wouldn't let you use responsive modifiers/dark mode nor be as concise.

Bootstrap has 98% of utility classes that you need for most projects. And if you use a design system or one of their themes, than the only 2% of css you have to modify is the color pallet and a few extra classes to cover edge cases.

Reinventing the wheel by subdividing all of your css into individual classes and combining them in html again just doesn't seem like a step forward to me.

> Bootstrap has 98% of utility classes that you need for most projects.

Including responsive classes? i.e. make this div X rem on mobile, Y rem on tablets, and Z rem on desktop? With 3 class attributes that require no config?

Bootstrap also comes with a hole bunch of unnecessary components.
Pretty patronizing comment. With Tailwind you get rid of the CSS file altogether. You're talking about something different.
can i get another 2-3 paragraphs expounding on this... the way you wrote that i just levelled up like 3x on my inner-tailwind-foo comprehension.
I’d recommend this blogpost from the creator himself!

https://adamwathan.me/css-utility-classes-and-separation-of-...