Tailwind CSS is so hot right now. And somewhat controversial, but I guess that only makes it even hotter. I’m a fan myself, I think the predefined sizes provide just the granularity necessary but no more. It’s sort of like going from drawing charts on blank paper to grid paper. Also, I really like not having to switch back and forth between js and css files.
While that’s all great, I think my true productivity gain comes from being spared of coming up with names. If you are not aware, Tailwind CSS uses utility classes: tiny classes that define one styling aspect each. So instead of this:
<div class="profile-card">...
you write something like this:
<div class="m-4 p-2 bg-grey-100 border rounded shadow-md">...
Which is more akin to writing the style property explicitly.
If this is the first time you are seeing this, you will probably have a number of predictable objections. I won’t address those here, I suggest you start with Adam’s excellent blog post.
Semantic classes are pleasing in a way, especially when you come up with a brilliant name that really nails it. Conversely though, it really bothers my OCD when a name is too broad or too narrow or off in some other way. And the thing is, you often need to create classes for things that don’t really have any semantics. How many weird wrappers and containers have I made just to add a left margin somewhere?
I realized that I had a similar experience in Typescript when I made a function that took a table | view
parameter, using typescripts awesome union types. A table and a view (in databases) are very but not completely similar and while I am sure there is a perfect word for that union, I didn’t have to search for it. I think this contributes quite a bit to my velocity when writing untyped code, and I guess structural rather than nominal typing is a nice in-between. Slightly fewer names!
Designing software systems is to a large degree about setting up taxonomies. You know, like in biology. A primate is a more specific kind of mammal, all that.
This is intellectually challenging and often quite rewarding. But it’s time consuming work! It’s also the kind of thing that can make my brain deadlock because I know the word is out there somewhere, I just need to find it. Add to that the extra round trips for non-native English speakers like myself who may have to double-check that we grasp the word correctly.
Sure, all good developers are lazy and all that, but this sort of architectural stuff has the toxic combination of being virtuous and often important while at the same time being low-stress but not boring. That makes it a perfect procrastination activity.
At times, it’s better just not to go there. Using all those utility classes with Tailwind is ugly and repetitive, yes. Not DRY! That’s true. But with every level of indirection you introduce in your code, you are making a trade-off. It becomes easier to change all instances at once, but on the other hand, it becomes harder to make variations.
A similar pattern happens when you introduce new abstractions. It can help you not only to get rid of duplication, in the best case scenarios, it can describe the problem you are solving in a way that feel like a revelation. But it can very well set off a whole tangent of thoughts about what the future will bring.
The introduction of a new term that you need to come up with and your team needs to understand and remember is a cognitive overhead that must be considered in the cost/benefit analysis. It’s often worth it, but it is not free. And this is not even touching on the situations where you end up with the wrong abstraction which can be very costly — much more so than a bit of duplication!
Top comments (0)