Hacker News new | ask | show | jobs
by nirvdrum 1300 days ago
I've been doing front-end development in some capacity almost as long as you, but it's not my forte. I've looked at Tailwind and I can see its value as a way to quickly prototype, but it also looks to violate the deeply instilled belief I have about semantically named classes. I know front-end development has changed its set of best practices several times now. We went from unobtrusive JS and semantic class names to modular CSS and CSS in JS, along with heavily marked up HTML to help out JS frameworks. Maybe this is just the pendulum swinging again. But, I'd appreciate any insights you can share on how this helps lead to maintainable software. The string of utility class names on various elements doesn't click for me the same way a class named "sidebar" or whatever would. But, a lot of smart people like it, so I assume I must be missing or overlooking something.
4 comments

I've been writing FE for 15 years and I'm in love with Tailwind. I never have to worry about naming, which in and of itself saves me a mountain of time. I had no idea just how much effort I spent on it until I stopped. Also, what I love about Tailwind is that it isn't an abstraction - the parent comment makes no sense because you can't use Tailwind without understanding CSS. But for those who do understand, it makes you so much more efficient, especially with a plugin like Tailwind Intellisense.

Your HTML will be uglier and it will be more difficult to look at the elements panel to find the element you're looking for. Both of those things are super minor for me, and have almost no impact on my day-to-day.

This is so frustrating to read over and over. Tailwind uses PostCSS. You can literally wrap a bunch of utilities inside a semantic class name.

Or, if you're using containers/writing components you can literally do something like this: https://pastebin.com/qkdzGWNT

But that a { could just as easily be "tag"

Personally, I've always found BEM to be tedious and the sort of "roll your own" class names just doesn't scale. This approach scales. This is what we should be moving towards as an industry.

> This is so frustrating to read over and over. Tailwind uses PostCSS. You can literally wrap a bunch of utilities inside a semantic class name.

If it's being asked repeatedly, it should probably be addressed somewhere. I see no mention of it in the tutorial or any of the amazing starter videos I've seen. I also have never used PostCSS directly before, so that's not an obvious solution. I appreciate the example you shared. I've asked (the OP in particular) in good faith, so I'm sorry that the question frustrated you.

> Personally, I've always found BEM to be tedious and the sort of "roll your own" class names just doesn't scale. This approach scales. This is what we should be moving towards as an industry.

Can you please elaborate on this? We've had well-functioning applications that predate Tailwind or CSS in JSS, so I'm not sure what doesn't scale. Descriptive names might get messy if you jam everything into in a single stylesheet, but using the cascading part works pretty well. If we're going to say "no, actually we were completely wrong when we said class names based on styles like 'red', 'big', and '2spaces' were bad", I'd like to understand what fundamentally changed. If it's just a case of convenience, that's fine. But, what about this scales better? How does this approach improve maintenance?

Your PostCSS example where you compose rules looks like a good approach, but I don't see that widely in use. Instead, I see the same rules repeated across elements in a document. That's the style the Tailwind docs use, so I'm operating under the notion that this is the prevailing way to write frontend code with Tailwind. While I can see that as an improvement over inline styles by ensuring consistent spacing definitions and such, that was never the recommended approach anyway. The style used in the Tailwind docs strikes me as being more problematic for ensuring consistency across pages or an app, which I see as hampering scalability.

Anyway, I'm trying to better understand why and how this shift is better. The only clear answer I've had thus far is that it's faster to get started because you get nice styles out of the box without having to adopt something like Bootstrap. That makes sense to me for small projects. At least I can see why someone would make that trade-off. I'm less clear on the long-term maintenance aspect and how utility classes help that.

Also, I did look at the docs and there is an entire page dedicated to this subject that you can read and it does mention @apply.

https://tailwindcss.com/docs/reusing-styles#extracting-class...

Thanks. I did overlook that. Although, the docs are a bit foreboding.

"Whatever you do, don’t use @apply just to make things look “cleaner”. Yes, HTML templates littered with Tailwind classes are kind of ugly. Making changes in a project that has tons of custom CSS is worse."

Then it lists a bunch of reasons that seem to just be the author's preferences on things like naming and workflow productivity. I guess I don't think naming things is that hard. I generally need a name of some sort anyway so I can interact with the thing from JS. I haven't seen anyone argue not to use React or Web Components because naming a component is hard. I wonder if it's just a granularity thing. I tend to give a class name to a logical entity and then use ancestry selectors for nested tags, with SCSS mixins to avoid duplication.

I didn't think naming things was that hard, until I got a chance to try building a project without having to name things. I'll never go back.
I agree that some of it is preference, but the main point he is making is that the number of utility classes doesn't matter if you're using a framework and styling a component. Yeah, it's ugly markup but so what?

With that said, I think it's reasonable to roll some things up into general classes. They remain very easy to change.

>I haven't seen anyone argue not to use React or Web Components because naming a component is hard.

I think the whole point is that that UI element, or "interface", or "component" is the thing that should have a name. That entity doesn't need to have a unique CSS classname.

Got it. So this would be more of a hybrid approach and clears up that question on naming granularity. Give the "component" a logical name and use the utility classes for the component's entities. That makes a lot more sense to me. I didn't realize those child entities were the things people were giving names to. CSS has fairly rich ancestry rules, so I just assumed people use them.

Thanks for taking the time to clarify that for me. It does indeed change my perception on utility classes.

Fair enough. I've realized I am currently using Tailwind in a way that is not the default and maybe a lot of people don't know about it. I think I will write a blog post about it.

Also, I think I am wrong. It's possible to use Tailwind without implementing a build step like PostCSS, which would necessitate using it much like the documentation describes.

>We've had well-functioning applications that predate Tailwind or CSS in JSS, so I'm not sure what doesn't scale.

CSS has fallen victim to the same "cult of semantics" that HTML has, and it's disingenuous bullshit just like it is in HTML (mostly).

Yes, if you have someone who really cares and writes great CSS they will have everything broken out into custom variables and well designed and named classes. You still have the problem of how you scale that, right? After all, if you have a .card that is formatted one way on one page but laid out differently on another, you have to think up a different class name or refactor.

Enter BEM. Block, element, modifier. A consistent naming system for your large application. That is both subjective, requires a lot of extra mental bandwidth in a time when you're lucky if half the "front-end developers" you're working with know more than the basics of CSS to begin with.

I have seen some truly tortuous HTML that uses BEM classnames. It was awful.

So when I say it doesn't scale, it's that most large codebases end up with !important everywhere and z-index:9999999 etc...

So throw it out completely. Utility classes make sense when you accept that you are probably styling a component and that markup will be inserted everywhere the component is. You never have to think about what your class name should be, and if it makes sense, or if it conflicts with other scopes.

Yes, an HTML element with 15 classes is not ideal.

The example I posted would hopefully be the logical end (and is if you're using Svelte with PostCSS configured) - where we're no longer writing html documents full of elements and then a stylesheet styling them. Each discrete UI element has one document, markup, state and styling are tightly coupled, and it can be reused many times.

It gets rid of nesting being very important, it gets rid of having to write verbose media queries for responsive. It makes changing things really fast.

The part about Tailwind providing sensible defaults in terms of sizing, spacing etc... is just icing on the cake. The problem that Bootstrap had is that it tried to do too much. It came about in an era when doing layout in CSS was really hard. So it rolls its own stuff like modals, dropdown menus, grid etc... it also takes it upon itself to style actual HTML elements, which to me is a very poor choice. Including bootstrap will get you default styles for headings etc... but I believe in Tailwind it's all done through utility classes.

Tailwind doesn't do that. The focus is on removing semantics from styling. Look at the API surface: https://tailwindcss.com/docs/

There's a "Components" link, but that's to a paid resource showing common UI patterns built with Tailwind.

Don't follow the hype and trust your own experiences and tooling. Tailwind can be good, but I get the sense that many commenters (not in this thread, however) may be paid actors in order to boost its mindshare.
Semantically named classes is a lot of effort to come up with, and don't really help much. One of the big selling points is that you can quickly style things without having to name every HTML element.
Thanks. I've commented on this elsewhere, but I think there's probably a mismatch in my thinking on the granularity of naming. I don't literally name every single element I'm styling. I agree that would lead to some very contrived names. I've understood semantic naming to apply to what, for lack of a better term, I'd call a component and then use ancestry rules to style within that "component". If you need to customize it, you can use the cascading part of CSS or use a pre-processor like SCSS to mix in and override things. I've found that leads to easily identifiable rules.

Of course, the trade-off is if you completely change the structure of that "component" you'll need to update any ancestry rules. But on the naming front, I'd need to come up with an identifier or logical class name to find the element in JS anyway, absent something like React that sort of controls the world.