So now it's the worst of both worlds: an abstraction layer and dirty code.
When you use inline styles for everything, you're making the initial development a little faster by making future maintenance and changes a lot harder. (Like, if you decide headings should be italic instead of bold, that's a one-liner fix if you're using CSS properly, but if you're using inline styles you have to individually fix every heading on every page.) So most people have internalized "don't use inline styles for everything" as a general rule.
But if you don't actually care about that sort of future maintenance (or you're charging hourly for it), then using inline styles for everything looks really attractive to you! But you can't literally use inline styles for everything because even non-experts know that using inline styles for everything is bad for future maintenance. So instead you pull in Tailwind so you can say you're using a CSS framework.
Once the components get too bloated, you start forking them, and you are back to each page looking subtly different.
You should have utilized a template engine in the first place. So you'd only have to change the layout/partial/component that is responsible for rendering the heading. Moreover, you could also have extracted the component with css by creating a .title class and using @apply.
I think this masks a lot of complexity that you have to manage when taking on this approach. And it's not because the approach is good or bad, more what it is or isn't suited for.
The example on the homepage is very slickly presented, but the end result markup is extremely verbose. If I have a Card component, I would like to update them all at once when needed which is what css classes are generally good for. I find BEM naming conventions much more friendly to come back to than markup full of miniature class names.
Yes, you may have more than one card in your system, but in all likelihood you aren't repeating the HTML for that card more than once, rather you have it in a template of some kind which is called. So while you may have more than one card on your site, you probably don't have the template for it defined more than once. (at least ideally you don't)
For those cases where you do want to extract that code, Tailwind makes that easy to do.
Tailwind is a weird thing and like I said I really thought it was insane at first. But after rewriting a site in it in a few days I have to say it is better than the standard semantic CSS by a mile.
Though, you can still use BEM with TailwindCSS through the @apply directive. Adam calls the directive a kind of "trick" to get more devs on board with utility-first but it does help a lot of you're used to reasoning about CSS with BEM.
I will stick to BEM + colors and sizes maps because this feels almost like using the style tag on each element.
For non-css expert engineers writing spa components, tailwind can be useful.
I can also see that it’s not trivial to mix tailwindcss and scss processors so it’s a no for me.
It has the benefit to limit spacing and color sets to presets but I already do this in my BEM codebase.
Then you update the styles of the card again but the new styles clash with the ones in those tailwind classes and you end with broken styles in some elements.
Mixing components and utility classes is a recipe for future chaos.
edit: thinking more, you can override classes. So yeah, maybe utility/atomic classes are not as effective here.
Or, if it is a minor change, then conditionally include / exclude a small subset of tailwind classes.
The point is to not write your own CSS, you only use tailwind classes. In this way you can look at the template for each of your components and reason about / edit their style and layout easily.
It also makes responsive styling a lot easier in my experience.
With Tailwind you'd have `bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative`. Then I'd have to change my HTML everywhere to update the appearance of alerts & its not always obvious that I'm looking at an alert in code.
Nope. Once you see same (sub)set of classes repeated, you would instead define .alert and .alert-danger using Tailwind's @apply directive, and you now have a single place to change how your `alert alert-danger` looks :)
<Alert type="danger"> Are you sure? </Alert>
Of course this solution would work in other templating engines as well.
The alternative would be extracting css components:
.alert { @apply px-4 py-3 ... }
.alert-danger { @apply bg-red-100 .. }
<div class="lg:flex lg:items-center lg:justify-between">`
Isn't this why we have CSS preprocessors? So we can do:
<div class="description-of-what-this-is">
.description-of-what-this-is { .lg_flex() .lg_items-center() .lg_justify_between(); }
Assuming there's enough complexity beneath the mixins to justify their use -- some of these might just be CSS properties.
// in JS, then build .btn-blue { @apply bg-blue-500 text-white font-bold py-2 px-4 rounded; }
What you find to be clean code might go the opposite way for someone (i.e. why would I use scss if utils are all I need?).
You might work with large scale apps where BEM may make more sense. You might work on a site builder where utils might be better. You might be creating splash pages for marketing purposes where going for element selectors may be enough.
So you can move really fast and experiment when you need to, and then extract to something shared when you're ready to DRY it up.
button { @apply border bg-white; // ... }
Tailwind recommends PurgeCSS, but i'll plug my own lib here:
https://github.com/leeoniya/dropcss
i have a specific section on how to handle tailwind's unorthodox classnames:
https://github.com/leeoniya/dropcss#special--escaped-sequenc...
<div class="lg:flex lg:items-center lg:justify-between"> <div class="flex-1 min-w-0"> <h2 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:leading-9 sm:truncate"> Back End Developer </h2> <div class="mt-1 flex flex-col sm:mt-0 sm:flex-row sm:flex-wrap"> <div class="mt-2 flex items-center text-sm leading-5 text-gray-500 sm:mr-6">
Personally I would prefer Bootstrap over this approach.