It sounds like you're fighting Tailwind instead of working with it. Are your designers aware of the presets and design with them in mind?
I'm curious what you're adding to your custom config to make it so bloated? I've been using Tailwind on a number of sites, big and small, and have yet to run into any situations like you've described.
It's not like Tailwind is SAP or something. It's just CSS. You shouldn't need to re-work your entire process around it.
The custom stuff in our config was mostly the need to create standard styles for components. Eg. button large, button small, etc. to correspond with our design system.
For example, here's tailwind code required to create a button large:
bg-violet-100 text-violet-700 text-base font-semibold px-6 py-2 rounded-lg
How the hell does that help with consistency? You have to copy paste that mess every time you create a new button, and then guess what happens if the button you copied from needed special margin? Try debugging that if something looks wrong. Also try turning that into dark mode.
Now you've got to search through the spaghetti to find what's custom about this button and fix it every time.
You know what's easier? Creating a ".btn-lg" style to fit our design system, and just typing .btn-lg each time. It also has the bonus of making your code actually readable.
Maybe this is solved with the groups functionality in the latest tailwind, but this is just one of the frustrations I eventually developed.
> It's not like Tailwind is SAP or something. It's just CSS. You shouldn't need to re-work your entire process around it.
No, your designers should already be working to scales for size, colour etc. which you can implement in Tailwind. If they don't, now's a good time to start.
> How the hell does that help with consistency? You have to copy paste that mess every time you create a new button
You're extremely not supposed to copy-paste that. You're supposed to extract it somehow, either with your Javascript component framework, or by making a semantic class with the @apply directive.
The difference is that Tailwind allows you do some quick work without coming up with abstractions. So you work bottom up instead of top down.
> then guess what happens if the button you copied from needed special margin?
That's the beauty of it! You have a button class, and then if your button needs "a little extra" you add the button class and the margin utility.
At my previous job, when this situation came up, the normal way was to make a BEM class specific to the location, import the button in that (with a SCSS mix-in) and add the margin. So the HTML would have a class name that was specific to this one button, but you didn't know what it added: class="info-page__navigation__button". With Tailwind, you get 'class="btn mx-2"' and you can basically see what it's going to look like.
If I’m using React components, tailwind makes even less sense.
I’ve already separated my button large out as a component, guess what happens in a mature design system? The system gets updated and changed to fit the needs of the product.
So what happens when you need to change button large in tailwind? You need to restyle the button with the spaghetti mess (maybe add something to the config), then re-extract the mess into a tailwind component. Now you’ve got components within components just to emulate the abilities CSS has right out of the box.
Guess what you could have done? Just had a .btn-lg class in an old school style sheet where you updated to the new font weight and padding and you’re done!
There is no need for this layer of complexity and abstraction of CSS. CSS is literally the easiest thing in the entire stack. Why do you want to make it so complicated?
Rube Goldberg machines are extremely elegant in their beauty, but they are not the most efficient way to get something done.
I'm guessing you haven't actually used it. It's a fantastic fit for React or similar frameworks. There's honestly nothing spaghetti messy or Goldbergian about it. It's just generating a stylesheet.
I absolutely do have a .btn class in my Tailwind projects, that's a given. For consistency, it's built from the utility classes that Tailwind provides, but buttons are kind of a pathological case in many ways, they're really not how you should evaluate a framework. When I put two buttons next to each other, I don't make a new class for one of the to get some spacing, I just slap a "ml-4" on one of them, and that matches all my other spacings.
But the real magic is when I'm building up my mid-level components, I don't have to try to come up with names or abstractions for the CSS, I just make things look and work right, and as I notice patterns I can break them out into semantic classes as needed. It's a great way to work and the results have been good for me.
In my mind, the real mess is a bunch of poorly named CSS classes that end up being specific to the place where they're used. Specificity battles, 40 character BEM selectors, mismatched margins sizes and randomized colour palettes. Setting up a Tailwind configuration is a very ergonomic way of turning your basic design system into CSS.
In regards to you needing to change your button when the design system needs to change I think you may be thinking about how to apply your current naming conventions or methodology as something like sass for instance what you could do is create the default button component and anything that you think you may need to change about that button you have props with defaults already set this way if you have one button requirements you just include it in the prop of that button, if you need to change all of them then you update the default prop.
In other wards instead of doing <button class=“btn-lg><button/> you're doing <Button {...specs}/>.
The point of react components is to centralize all instances of something for consistency and easy updates.
This is also what CSS does for you natively. Tailwind is a beautiful, elegant, and ultimately unnecessary layer of complication.
It feels powerful and fast to beginners, and then you go through a design system overhaul with it, and start wishing you had just used bootstrap style class names and avoided the whole mess.
If you are using Tailwind then your designers need to be aware of its presets and be designing with them in mind.
When it comes to code reuse, either extract the button to a component that you reuse, or extract it to a class in tailwind.
.btn { @apply px-4 py-2 rounded }
Now you can just add the btn class and you’re done. If you ever want to change that button you can just update it and be done. If you want a button with different padding add btn px-8 and you’re done.
If you’re using components then you just create the button in a single place and reuse it. If you have custom requirements for the button then you override it.
It’s really quite simple and easy to do everything you’re describing. I’d read the docs and watch some videos on it and start working with it instead of against it.
Or don’t use it at all, makes no difference to me!
On the surface Tailwind seems quite great and whenever I stumble upon it I like the idea of good defaults, but since I don't use React or a component-based UI framework I'd mostly work with Tailwind's @apply directive, I assume, and at that point I wonder why I shouldn't simply stick to
.btn { padding: 4rem 2rem; border-radius: 2rem; }
rather than
.btn { @apply px-4 py-2 rounded }
It simply feels like an additional, unnecessary layer and, frankly, somewhat wrong.
>How the hell does that help with consistency? You have to >copy paste that mess every time you create a new button, and then guess what happens if the button you copied from needed special margin? Try debugging that if something looks wrong. Also try turning that into dark mode.
Agree with that. Wish the custom theme mechanism becomes mature enough like React components.
Until then the best bet i found was to use our own styles along with tailwind class names
As with all compositional programming, refactor your classes at the point of generation. So you most certainly do have a “large button” concept in your code, as a function/helper/method/partial/template/component.
Otherwise you’re just fighting against the framework.
I'm curious what you're adding to your custom config to make it so bloated? I've been using Tailwind on a number of sites, big and small, and have yet to run into any situations like you've described.