`.card-header__buttons` that example makes no sense unless you use global CSS/SASS, which very few projects do anymore. Component CSS/SCSS or CSS-in-JS are very common which resolve this scoping problem.
So why bother with a DSL like Tailwind over Component CSS/SCSS for example?
By having a style guide with variants, StitchesJS pioneered this but there are others like Vanilla-Extract. With TypeScript, you can then enforce that only a certain variant can be used with a certain component at compile time, basically making sure that your design style guide gets mapped 1:1 to your code.
Unlike other CSS-in-JS though, the way it's made, via object properties, enforces compliance to the design system. In things like styled-components, it doesn't.
Which is indistinguishable from any other CSS-in-JS which has hundreds of these one-off things scattered everywhere. With a theme somewhere exposing another hundred or so variables of varing quality. And all these solutions basically converge on Tailwind (or other utility-first CSS approaches):
Which is indistinguishable from any other CSS-in-JS which has hundreds of these one-off things scattered everywhere. With a theme somewhere exposing another hundred or so variables of varing quality. And all these solutions basically converge on Tailwind (or other utility-first CSS approaches):
This video from Stitches shows their API well, which VE copied with their Recipes plugin, code example below (timestamped to 31:07 in case the link doesn't work) [0].
/// Define variants for a specific component, such as a button
export const button = recipe({
base: {
borderRadius: 6
},
variants: {
color: {
neutral: { background: 'whitesmoke' },
brand: { background: 'blueviolet' },
accent: { background: 'slateblue' }
},
size: {
small: { padding: 12 },
medium: { padding: 16 },
large: { padding: 24 }
},
rounded: {
true: { borderRadius: 999 }
}
},
// Applied when multiple variants are set at once
compoundVariants: [
{
variants: {
color: 'neutral',
size: 'large'
},
style: {
background: 'ghostwhite'
}
}
],
defaultVariants: {
color: 'accent',
size: 'medium'
}
});
/// Use in code
<button className={
button({
color: 'accent',
size: 'large',
rounded: true
})
}>
Hello world
</button>
Basically, unlike other CSS-in-JS libraries, you can encode your design system into something called variants, then you use them by calling the function `button()` to generate a class name.
Notice how `button()` takes in certain properties and only those properties with their corresponding values (enforced by TypeScript). If you try to put in `button({ color2: 'testColor', ...})`, TS won't compile.
In this way, you can take the design team's ButtonSmall, ButtonLarge, NeutralButtonLarge etc and codify them into TypeScript such that you literally can't make a mistake. You simply can't do that in Tailwind, unless you use some outside plugin I assume.
(Note that VE also has a Tailwind-like atomic CSS API called Sprinkles, but since I don't like Tailwind I don't use this either).
> How do you enforce consistency in CSS-in-JS? Paddings, margins, sizes, colors?
JavaScript variables, css variables? Both can be used. It's pretty trivial tbh.
I prefer a global set of styles and more specific selectors to override styles where needed. It may not work well on projects with many teams but for the projects I typically work on it's fine.
The thing with Tailwinf is that it already has a decent design syste encoded in its utility classes. It's very easy to slap a p-2 for a standardized padding than trying to remember what it was when you write the next component with `{ padding: 2 2 2 2 }`
> I prefer a global set of styles and more specific selectors to override styles where needed.
That's kinda what I mean. In all projects I've seen you have a global stylesheet with a bunch of classes that no one remembers, and hundreds of one-ofs in every component either reimplementing stuff from scratch or serving as an `!important` of sorts
Unlike the yet-another umpteenth bespoke `.card-header__buttons .card-header__button--secondary` that no one can remember and create an umpteenth+1
Tailwind works great when your site/app is a collection of components