Play with TailwindCSS in the Browser
play.tailwindcss.com
play.tailwindcss.com
I couldn't fathom why anyone would ever use it. And then I used it. It seriously makes CSS significantly easier to maintain, dramatically reduces your CSS build size, and is really good for teams if you're trying to use consistent CSS throughout your UIs. You also don't need to go back and forth between CSS file and HTML file.
If you're on the fence, try it out. I think it's the future of writing CSS.
If I'm working with a designer rather than designing my own UIs, that they have a default color palette isn't helpful, so what do I gain from Tailwind?
EDIT: Reading some other comments, I wonder if part of the reason I don't see the utility is that I use Vue, not React. It sounds like Tailwind solves a lot of the same problems that Vue+SCSS does.
The native libsass is much faster. The headaches come from people trying to distribute binaries and libraries through NPM.
> npm (originally short for Node Package Manager)
Acronyms can make sense to switch case, but initialisms... en-pee-em... I guess it happens. I originally was introduced it as Node Package Manager, but I'm gonna make an effort to correct this now.
This is awesome, really glad to see things have progressed from the node-sass days. Might have to give it another look.
Does your tooling even support embedded Sass?! Vite does not. Our version of webpack does not.. The Cenobites would LOVE Sass; never ending performance pain.
Same for spacing and font sizes if you need these standardized and haven’t done it already.
Which we always did way before tailwind was invented.
then i tried learning it and it turns out that Tailwind's constraints both help my design and help with the learning curve
wrote up full thoughts in an old post https://www.swyx.io/why-tailwind
I am pretty conservative in terms of "use boring tech", because I see so much reinventing of the wheel and making the same mistakes, but Tailwind is not in that camp!
I was never happy with any of the CSS in JS solutions in React land – all of them felt tedious or boilerplate-heavy compared to Vue's CSS model, which is excellent. Writing css and getting component scoping for free are great.
But with tailwind I've minimized usage of Vue CSS too. I pull it in occasionally when I need specific overrides of the tailwind component lib I'm using, but other than that I don't even need to touch css.
I know you can define your own component classes in TW, but then you've just recreated Bootstrap/Bulma/etc, but with no 3rd party components available. (Tailwind UI is just some limited copy paste code snippets last I looked.)
There are a bunch of great 3rd party components available in tailwind now. https://daisyui.com/ is one I've been using. They're usually a tad bit lower level than typical framework component libs, but the flexibility is great.
A great thing about that is they're not React-specific, Vue-specific, etc. You can use them in everything from raw html to your JS library flavor of choice.
I had to do it with a BEM codebase, and I also had to do it with tailwind. The tailwind situation was by far the easiest one. And it was because I was not afraid to remove things that could break unrelated parts of the application. Not allowing developer to hand write CSS is a great restriction for a good bunch of developers. The messes out there are unbelievable.
I agree, main point is that I think there are better tools for large codebases. We had a "no CSS" rule where we used bootstrap components and utility classes only.
Yes, many times, with normal CSS. It's basically the point of cascading style sheets. Sticking to proper class names and elements makes reskinning a breeze.
The "cascading" part is what makes it incredibly complicated. Keeping the "cascade" in sync with the actual markup is not a trivial task in teams with many people of different skills levels.
Not everyone is a top 1% dev, so we need easier and safer tools so that everyone can work and maintain a codebase.
> Sticking to proper class names and elements makes reskinning a breeze.
This is more easily said than done. It's like saying "Just don't write bugs". Every single project I find that has been built with BEM and similar patches after a couple years are just a mess and their CSS becomes "append only", as there's no guarantee that removing something won't break in unexpected ways.
"We all use 'cascading sheets' now. If you're working on a CSS file longer than a couple hundred lines, properly formatted, you're not abstracting enough or it's a one off marketing thing."
Sorry, but this might just mean one file-include per tag if you use tailwind-css. The in-line CSS exceeds the HTML content by sometimes an order of magnitude bloating the page HTML to ginormous size.
It's an acceptable trade off. Nothing is perfect. In exchange you're guaranteed those changes only affect this markup, and not some other li > ul > a whatever somewhere else.
> Might as well go back to doing inline styles
No, it is not. This has been explained thousands of times anyone says "tailwind is like inline styles". You can do responsive, you're limited to a consistent subset of rules, minimal output css file, caching, etc, etc. For example, here [1] is an explanation why it is not the same, but there are thousands.
By reading your answers I deduce you've not used it yet. And this is exactly what is being discussed here. Fanatics closed inward looking people will never like it, nor anything that defies what they've been taught for years. Like religion almost. You have to try it for real to see the benefits. It is not perfect, but the net result is very positive for a lot of people as you can see from the usage statistics. Just be a bit more open minded to new tech and give it a try. At least you'll understand why it is not the same as inline styles which is a pretty basic thing you understand after 1 hour of using it.
[1] https://frontstuff.io/no-utility-classes-arent-the-same-as-i...
https://tailwindcss.com/blog/automatic-class-sorting-with-pr...
Same. I always said they'd pry my stylesheets from my cold dead hands. But then I tried it, and I'll never go back. I feel like it's time to let go of those last vestiges of the old "web development" paradigm, and start treating the browser as what it is; a universal VM for application development.
Also, I'd go so far as to say that if you're not using a component based architecture for your web app's view layer, you're creating a ton of extra work for yourself.
My take on ViewComponent: it’s what helper functions become when they grow up into proper objects. Great for larger projects, may be more infrastructure than necessary for smaller ones, adopt incrementally when they seem compelling.
To fix the css + jsx in one file, just write your styled components at the bottom of your component.
If you ever seen a react component completely riddled with Tailwind, you'll realize how messy and uncoordinated it looks.
Even I would consider switching between two files just to avoid that style of css.
Furthermore the necessity to utilize horizontal scroll because adding 10+ more rules will inevitably break your prettier printWidth rule is, by far, the most annoying aspect of Tailwind.
absolute inset-0 bg-gradient-to-r from-cyan-400 to-sky-500 shadow-lg transform -skew-y-6 sm:skew-y-0 sm:-rotate-6 sm:rounded-3xl
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
linear-gradient(45deg, #fff, #000);
box-shadow: 1px 1px 1px 0 rgb(0 0 0 / 0.05);
transform: skewY(60deg);
border-radius: 4px;
transform: rotate(60deg);
Consider these two snippets, after time of not looking at your css code, do you think 10+ rules on one line is maintainable?Not even close, ask yourself to change a css property - you would have to iteratively go from left to right until you find it, whereas looking from top down you can immediately catch the css rule you want to find.
Succinct doesn't mean maintainable, and sometimes verbosity does.
Tailwindcss isn't even close to being the future.
The difference between your 2 examples is that TW allowed you to handle media queries seamlessly but you couldn't do that in your styles example.
but a media query in styled components would just be
@media (max-width: 700px) {
css here
}
it's not that much harder.Also, the lack of address of real problems of tailwindcss of OPs comment in terms of mantainability is something you consider.
reading iteratively from left to right especially if it has 10+ css rules, in terms of legibility, is not really all too great.
I would absolutely hate to adjust something in tailwindcss, after not seeing the codebase in a month's time.
Whereas regular css properties, i can easily find by eye.
Not sure what you mean by that. I've been doing this since we did layouts with tables and shims in the 90s. I've found TW pretty nice to maintain myself.
"It's not that much harder", but a) it's a simple example and b) now you're going to litter your code with a load of hard coded media widths?
Let's talk about something concrete. Let's take a really simple layout that changes border and margin responsively (this, for me, is seamless).
<div className="m-8 lg:m-0">
<div className="border-2 md:border-4">
Content
</div>
</div>
How would you do that? const inputWrapperClass = classNames(
'flex flex-col gap-y-1',
'group-focus:border-blue-500',
isDisabled ? 'opacity-50' : null
);
return (
<label className={inputWrapperClass}>
{...}
</label>
)
In practice our "full-stack" developers are writing less and less CSS because they're just using the components that encapsulate all of this, our frontend developers get code completion for our design system tokens, and we haven't had to ship any new CSS classes in the last few months.Our new hires are able to just use the design system tokens rather than going in and saying `padding: 5px` and `padding: 4px` because the designer didn't think it was a big deal. They just write `p-1` and that covers it.
All the components get tree-shaken and only ship the styles they need so bundle size gets reduced as well.
If I had my dream team of 10x frontend developers and a perfect design team who always follows the rules they create then yes I would use regular css with css variables, but I don't.
I am more than happy to sacrifice "separation of technologies" for a happier team, more consistent styling, and faster delivery times.
And you can split, and sort classes with editor plugins which makes it almost equally good as your example.
Regardless of where place your tailwindcss or where you split / sort classes, reading iteratively from left to right, especially if the css rules are numerous, is not legible.
just looking at the two examples above, and already I can tell how much it would be easier to maintain verbose css.
I can go as far as using some of its standardized constants in my BEM codebases.
Snark aside, I believe the future of CSS is closer to ITCSS - working with the cascade to minimize the need to modify styles.
It's much more difficult to scan a list of classes in a single line. With CSS I can quickly scan the declarations from top to bottom until I find the thing I want.
Complex nested declarations are also super easy to scan when using SCSS. When you start adding pseudoclasses with TW it becomes a shit show.
And it really makes the markup an absolute mess for anything other than trivial examples.
People complain about not knowing where the styles are, which was a valid concern when doing old school CSS (everything in a couple of files) but I haven't had that issue since I started using SCSS in almost a decade.
When doing front end with components I store the SCSS for the component in the same directory of the component file. Eg: MyComponent.svelte and MyComponent.scss. Super easy and clear. I've also written a small VSCode extension that allows me switch between the component and its SCSS file with a shortcut. I don't even have to open the SCSS file or look for it. I configure Webpack or whatever I'm using to automatically include the .scss files in the component folders. I have all the convenience and control I want without relying on something as convoluted as TW.
.class1 {
.class2 {
&:hover {
font-family: value;
}
body.some-thing & {
color: woooooo;
}
}
}The problem with Tailwind is there's nothing you can do to avoid the much more difficult to scan and understand syntax described above. I personally don't understand why people are drinking this koolaide. I really think this is a fad a lot of people are going to come to regret when they go back to maintain older projects based on it.
Yeah 100%
But if you look at the State of CSS survey, TW is still relatively not as popular as Twitter or HN would make you believe.
a) maybe you don't really know how far up the chain that tag gets called from.
b) it creates new selectors for class1 and class1.class2, as well as class1.class2's hover
c) creates a hyper specificity
now, I'm not advocating this usage of SASS - but it can be a handy hatchet when you need to support multiple themes with minimal changes/effort, much to the chagrin of specificity and maintainability
I think the reason a lot of ppl think they need tailwind, is because a) they aren't familiar enough with more current CSS techniques like CSS modules and linting which can limit stuff like nested descendant selectors and/or b) they're tricked into thinking they won't have to learn as much about CSS (a dangerous fallacy unless you're sticking to the most basic of prototypes!).
Which is technically true but irrelevant. TW doesn't prevent you from understanding fundamental CSS concepts such as the box model, cascading, etc. Anyone with even basic CSS knowledge would not write this nonsensical and malicious example you just used.
It tends to make the code pretty ugly.
There are ways to improve things somewhat (moving "bundles" of classNames into properties of a local or global cssClasses object and adding those to your elements' className), but you lose the intellisense when editing classes and it often ends up feeling like the extra friction isn't worth it. Having the styles right there seems to be a key part of what makes using tailwind so productive.
We have enough decisions to make regarding design as it is, adding organization, naming, selection, and attempting to maintain a sensible hierarchy into the mix leads to a fog of decision fatigue that I didn't realize existed until I tried Tailwind and it lifted.
I've tried multiple times to use it, but I always end up using something like bootstrap. Funnily enough, I paid for tailwindui and take the styles and reproduce them in bootstrap css.
Bootstrap community seems to have given up. They only want to sell templates. The default is ugly. Sometimes I think about going back to bootstrap 2.
Tailwind didn't invent utility classes. We've done this since the '90s.
> significantly easier to maintain
Disagree totally. Utility classes are good for rapid prototyping. But they clutter your code, mix semantics with presentation, and are a pain in the ass when it comes to code reuse. The cascade part of CSS is, believe it or not, actually useful for code reuse. Need to change a font deep in some nested component? Not a problem with CSS. Tailwind, you're fucked. You'll need to modify each component layer to pass down a class prop. Or do some ugly context hack.
* HTML has always mixed semantics and presentation.
* It’s terrific for production applications because we don’t lovingly hand-craft each DOM node. Far from being an enemy of reuse, it enables refactoring at the point of HTML generation, and aligns particularly well with partials and view helper functions/objects.
* The cascade is still there; you’re not fucked. Not even if you’ve been suckered into using some react-like framework.
no, we really didn't. tho i'll agree that utility classes have been a thing for longer than tailwind/bootstrap/tachyons/pico/etc have existed
> mix semantics with presentation
there is nothing semantic about class names: nothing, zero, zilch - using IDs are even worse due to specificity, with none of the "semantic" benefit. focus on the correct top level wrappers
part of me wonders about the extent of what HN commenters actually do on the web regarding styles, or if they just slap together some homogenous web app or static site where its rather easy to not have a design team needing flexibility on every little thing.
case in point, our main "button" has about 15 different base variants (that *3 currently) depending on context, not counting the interaction states.
But the thing is you can always do that if it’s needed. There’s no one forcing you to strictly adopt the utility pattern. It’s all just vanilla CSS at the end of the day. If a hybrid approach works best for your project then do that.
Personally I find the need for this to be quite rare, and there are actually some good arguments against writing too much specificity in to your css even if it’s more convenient up front.
I also started out thinking the whole idea seemed backward. Now I think of it this way: it works extremely well in practice, even if in theory it won't.
I’m a huge fan but maintaining tailwind projects is actually a huge pain in the ass. I could maybe improve it by factoring out the classes from my html into a separate sheet using @apply when I’m “done” a project, but I don’t, and it defeats the convenience value anyway.
The markup is so overwhelming when there’s anything remotely complex. And sometimes components are almost identical but with slight variations. I miss seeing an element with a simple .classname to let me know what’s going on. Admittedly this is due to a lack of foresight on my part but moving forward I’m either re-thinking tailwind or ditching it.
I even have a pre-release 0.6v or something running on a production site I need to maintain. Which is stupid and my fault but demonstrates 1) that I’m a huge fan and have been using it forever and 2) it can suck maintaining if not thought out properly.
Don’t forget now you need to configure webpack for node sass and purge css and blah blah blah.
Tailwind is great for building something you never need to touch again.
I do it by refactoring my HTML.
By the way, you don’t need webpack to use Tailwind. It works great with lightweight asset handling too. In particular, there’s a stand-alone compiler.
Isn't this at the cost of dramatically increasing HTML size ? I have seen tailwind littered HTML increase by 2x-3x the page size with all that extra-ordinary repetition.
PS: I agree it makes CSS coding quite faster due to less typing involved when designing something thanks to succinct atomic CSS classes. I am not sure less typing is better though, especially for maintainability and performance.
<input type="text" value="tbone" disabled class="mt-1 block w-full px-3 py-2
bg-white border border-slate-300 rounded-md text-sm shadow-sm placeholder-slate-400
focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500
disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none
invalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500
focus:invalid:ring-pink-500" />
How is mushing every single style into a class attribute supposed to help with readability and maintainability? Even if you use `@apply` to reduce the clutter, you are basically venturing back into "vanilla" CSS territory, and which their docs expressly said to avoid (https://tailwindcss.com/docs/reusing-styles#avoiding-prematu...).And even if I decided to march forward with tailwind CSS despite all of this, how do I format the code? Break up the classes for different states into separate lines, like so?
<input type="text" value="tbone" disabled class="mt-1 block w-full px-3 py-2
bg-white border border-slate-300 rounded-md text-sm shadow-sm placeholder-slate-400
focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500
disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none
invalid:border-pink-500 invalid:text-pink-600
focus:invalid:border-pink-500 focus:invalid:ring-pink-500" />
Yeah, I do not see how this is more readable than plain CSS. Is all of this worth it, just to avoid having the developer think up of class names, or defining their own theme using CSS variables?Yes. You're starting out with a well thought out set of variables & themes. You can tweak if you need. You can add extensions. There are lots of HTML/CSS components written for Tailwind online you can copy/pasta into your project.
But for me the biggest win is just having a ton of variables I can use. I also only use it when building component type architecture & I try to keep my components small & focused.
Where it shines is when you're not looking at primitives. Most dev work is pushing pixels around for layouts making things responsive, padding, margins, flex direction stuff. And in those cases Tailwind shines because you aren't constantly trying to come up with class names around div and sections. You are authoring you're css right with your markup. The productivity gains is unlike any other tool you can introduce to an org.
Going back and reading a component and making modifications is incredibly nice too because I can just understand everything that's happening right out the gate. I'm not going back and forth between 2 or 3 files and trying to un nest complicated SCSS in my head.
[1] https://adamwathan.me/tailwindcss-from-side-project-byproduc... [2] https://web.dev/state-of-css-2022/
input {
margin-top: 1rem;
width: 100%;
padding: 2rem 3rem;
background-color: white;
border: 1px solid slate;
border-radius: 25%;
font-size: 1rem;
box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,
rgba(0, 0, 0, 0.05) 0px 4px 6px -2px
}
now, most of that is pretty straight forward - but you're just going to end up with a whole lot of copypasta when you need to implement outline/focus/shadow/etc state on many elements. and maybe on some specific instances of them you don't want that, so then you have to create a class just to override your global defaults .example {
@apply text-base font-normal text-gray-800;
}
And there you go.I don't think Tailwind's value proposition is "more readable than plain CSS", even though I think it is competitive in that area.
I know it is conceptually "wrong" and a bunch of well crafted CSS classes would be more elegant. In the end it works, works really well and makes collaboration dead simple. Commonly used groups of classes can either be aliased by @apply or used in a (react) component. I used CSS way before Tailwind was a thing and in hindsight I created a lot of utility classes that resembled a weakly-structured, somewhat incomplete version of Tailwind.
It might be a bit verbose, it might be easy to abuse but it works damn well. On top of that there are some design guardrails built in that really help with the consistency of e.g spacing, colors and fonts. Easy to achieve good looking results without risking stuff always looking the same like with Bootstrap or Material.
It is a bit like Github Copilot. The only way to "get" it is to try it.
I know a lot of people who have tried but didn't like Tailwind. I think most people like it on a greenfield project, but that number drops off when they go back to a Tailwind project after some time.
Just like everything, it would depend on the project, team, and individual.
I personally was against it until I used it.
Same applies for my own code that I come back to after a year or 2 of not having touched it. It's way easier to parse a template that declares its own styling than a template with references to style classes that may be across multiple CSS/SCSS files and are probably badly named
For me Tailwind barely make it anything faster but I have to learn all their classes and then I am stuck to have to relearn CSS when their is custom stuff. Maybe for greenfield or MVP sure. But if you are on a big project you have one or more designers and 99% of the time you have things that needs to be customized.
This is completely nonsensical because Tailwind classes are almost all just shorthand aliases for single CSS properties. You cannot use Tailwind without understanding CSS; it is CSS.
Tailwind seemingly affords an easy way of writing inline styles, but it 1) clutters the HTML, 2) leads to repetition and makes people break the DRY principle (yes, you should extract to components, but people don't always do that), 3) uses names that can be similar but are not identical to CSS properties and feels like a bad abstraction.
If you use something like Svelte, where you can write local CSS within a component I fail the see the benefit of Tailwind. For me Tailwind is the most ill-conceived frontend tech I've had to use in later years.
Or, it makes your HTML far more representative of the state of your application, rather than having to open up a CSS file and match to the class name + whatever madness you have going on in your SASS with mixins and conditional style logic.
> 2) leads to repetition and makes people break the DRY principle (yes, you should extract to components, but people don't always do that)
Blindly following DRY is dogma. Not everything can (or should) be a component. The number one mistake I see with new React developers is "over componentization", where everything is a sub component, and now I'm digging through 5 different files to work on a feature. Use the "rule of three" here. The first time you write something, don't even think about making it a component. The second time you write it, start planning how to generalize. The third time you need it, make it a component.
Copy/pasting is OK. Declaratively laying out your UI rather than generating it through configuration is OK. Having no abstractions is better than a bad or even mediocre abstraction.
Also, this is the first I’ve heard anyone proficient in both consider React more productive! I’m curious, do you think that has more to do with the amount of experience you have in React over Svelte?
Oh I think the other thing was Svelte doesn't work as well with Typescript (or I couldn't figure out how to make it work as well). I wouldn't get type hints in situations where I would with React.
Perhaps I just didn't take the time to get things set up properly. If you can link a Svelte project that uses Tailwind and Typescript I'd love to give it a clone and see if things work better.
Regarding productivity, I don't think I'm "less" productive in Svelte, especially for smaller apps. I think I've been really conditioned by React and have an easier time splitting out components and making things more modular, which makes a big difference with larger apps.
Mainly I get the benefits from setting the tailwind config file for things that apply across my components.
Not all of my repeatable markup lives as utilities, e.g. <a> and <buttons> — I define those classes in the scss file. Oh yeah, combining scss and tailwind also gives lots of composability options
We're converting our app components to using Tailwind. But there was some initial resistance as the current setup of css-in-js was fine. Fine but not great, and we had ended up with a lot of weird custom css blobs over time.
One side benefit is you can just install Tailwind and use it in isolated way. Which is what I did. Converted a couple components to using Tailwind and demoed them. Got positive feedback. Most element only need a handful of classes. And the elements themselves are just normal HTML with a class.
Components feel quicker to scan now. Initially skeptical devs have noted the ease at which they can build out a new component. Without having to get bogged down in writing css.
Which to me is the real goal of Tailwind, improving DX by abstracting the boring and error prone way of writing CSS for applications.
I exclusively write server-side templates with minimal to no javascript. I don't like Tailwind because it doesn't work for that.
Boy I felt like an idiot when I started using it.
I spend way less time going from idea in my head to actual concept now.
Foolish boy.
1 - It encourages styling on the fly. Because it is faster initially, you don't have to constantly switch between a CSS file and your markup, it feels good to style it as you go, and gives you an initial productivity boost. But it can cost you in technical debt later, so be careful.
2 - It makes your markup really messy. You end up repeating the same utility classes over and over. Then you can forget which utility class you used for things that should be defined globally like spacing or colors, and have components with different styles and not one place where you can change it.
3 - It makes debugging styles in the browser difficult (you change the style of one class, it affects everything, not just the tag/component you are working on. Having component-based classes allows you to debug styling on individual components much easier. I find myself debugging by actually adding the utility classes to the markup.
4 - You have to memorize another name for every many css properties (e.g. line-height => leading), or just be constantly in the docs. VSCode extensions are helpful, but it does not always detect that you are trying to type a Tailwind class, esp. if it's dynamically generated classnames. It can also make VSCode run slower.
5 - Some CSS properties are missing values as options, so you have to customize it out of the gate (e.g. min-height) or use the custom m-h-[value] syntax, but why not make all of tailwind like this?
6 - Trying to sync Tailwind configurations between projects (e.g. between a component library and an application) can become tedious.
Like anything, I think good styling is probably a combination of global styles, utility classes, and component classes. Something like Tailwind + Bootstrap + SASS on top of your own custom classes might make for a good tool, IMO.
2. If you need to use the same group of utility classes over and over, extract to a class - either with @apply (if you want to keep the flexibility of config updates) or vanilla.
3. I'm not sure I'm following here - if you're changing the value of a tailwind class, you should do that via the config
4. I've found the naming differences easy enough to follow - line-height vs leading makes sense if you come from a design background. I think the biggest gotcha I had early on was everything is mobile first by default - so sm:* is actually _larger_ than the default.
5. the JIT is a wonderful addition, but does come with overhead currently - so that's why it (i assume) isn't just the default way of doing things.
6. not a problem i've run across, but why would a component config supersede an app config?
to your last point, we use tailwind in conjunction with a fair amount of legacy sass to do what we need (many small nuances, spread across 4 different sites, that are otherwise the same) - I would urge against mixing tailwind and SASS if only for the build speed, PostCSS should be able to do everything you need there and it'll just make the builds a bit faster.
tho I feel like what myself and my team works on is a far cry from your standard HN web app - so my experiences are probably very different.
In all fairness, I've never actually tried it.
I was of your opinion until I tried it. Been using it for over a year on my current project, now.
I recently built a little prototype without using Tailwind, and man… I didn’t realize how big a quality of life improvement Tailwind is until I stopped using it. It’s really hard to imagine going back.
Edit: I’ve been building websites since 2000, and know CSS quite well, and hope to never write much CSS again.
That's what you're missing. Try it.
In my experience, tailwind is pretty close to the real CSS properties. What I found to be wonderful and freeing about it is that it stops the middle step of engineering and naming classes and naming elements with class names and let's you just do styling. There's also a really great plugin for VS code that adds intellisense. Personally I found the modifiers that allow you to target pseudo selectors like :hover to be a superpower. I totally understand the other side of the argument though. It's a lot.
I get that it is aesthetically ugly, but if you can stop caring about that then you might find that it’s better on most other dimensions.
Like others have said, the selector logic is top-notch and not having to build your own styles is great as they are pre-defined. You can always modify the styles any way you want and add your own custom ones too.
It looks "gross", but it's very practical. If you follow the best standards for component sizing, you should never really have much of a problem with the styling getting in the way.
This phenomenon encourages me to try something out before forming an opinion.
If you don't don't get it, either try it out or move on.
These comments add no value to the conversation.
The browser's built-in CSS support is the framework, I don't understand why people try to build things like this on top of it unless they're adding real value.
It's a design system as well as a set of utility classes. Consider the difference between
<span style="color: #cccccc">Gray text</span> and <span class="text-gray-700">Gray text</span>
In the former, you can't just redefine what gray means. You've hard set it to a value you need to keep track of and keep consistent. On the right, you can configure what "700" means, switch between a cool gray or a blue gray, etc.
<span style=“color: var(--text-gray-700)”>Gray text</span>
Or use Sass or something. This problem has been solved for like 15 years.Here's how to make a div have 0.5rem of left/right padding on mobile, and 2rem on any screen larger:
<div class="px-2 sm:px-8">
I'd much rather do this than mess with CSS's horrible media query syntax myself. And when I come back to this later, I don't have to cross-reference between (probably badly named) classes across 2 files to figure out how that div behaves.I disagree with your preference; all the classnames are not easily parseable and obscure the markup, and I much prefer the CSS media query syntax. But that’s, like, just my opinion, man. If you like it better, don’t let me stop you!
How?
<style>@media (min-width: 100px) {}</style>https://tailwindcss.com/docs/customizing-colors#color-object...
Utility CSS is by far my favorite way to write CSS, especially in teams. It allows you to extract out multiple classnames that encapsulate all styles into a single classname.
Why would you use Sass when plain CSS does the job better? Tailwind is just normal CSS, all the build steps are ways of making your stylesheets more efficient and removing dead code but it's all still CSS no preprocessor necessary.
Aside from creating a standard naming scheme for your style guide, they also simplify specific CSS tag features by ensuring they can be consistent across browsers without you having to tweak each style.
Outside of that, they acknowledge that you're not going to use custom CSS tags that often because 9 times out of 10 you're going to style something in one place in a template and your programming language will repeat it for you...so there's no real value to creating a dedicated class.
Another that I've found over the lifecycle of a project is that developers forget what CSS is where and end up simply creating new classes for things that they need rather than trying to reuse existing ones...which leads to your CSS growing constantly over time. With Tailwind I rebuilt my entire personal site, brightball.com and ended up with 20 lines of custom CSS. This after restyling the entire site and making it responsive. And I was able to do all of it in an afternoon without ever having even made a responsive site before.
What they've done is created "Rails for Style Guides" and it works beautifully. The Refactoring UI book (fast read) from the authors of Tailwind goes into the importance and reasoning for everything they do and it makes absolutely perfect sense.
<submit-button>Submit</submit-button> using whatever tooling you prefer.
If you don't use this style, maybe you won't like it.
I've found it's a waste of time to extract classes for items that are not repeated. And putting utilities in components lightens your "master" CSS file and makes it a lot easier to work with CSS.
I've found that the "cascading" part of style sheets almost always breaks down in larger projects. Small components seem to avoid those breakdowns while allowing for reusability.
People that haven't used Tailwind come along and say, "this is silly, just use css". The people who have used it say, "you should try it, it's not what you think."
There are a bunch of subtle differences with Tailwind that make it quite a different experience.
Really, it's closer to inline-styles++ than anything else. The style only applies to the element you're styling. This is by design as it means you can change that one style without wondering what else you've broken across your app.
But you get variations that inline styles can't do (and aren't fun to do in css either): `text-green hover:text-red dark:hover:text-white` (interaction states, light/dark mode, responsive etc etc). This makes a huge difference when you're actually building this stuff.
Personally, from a DX point of view, I really like it. I find it faster than anything else when I'm building and it's easy to debug too; no need to fish for the styles, they're inline on the element I'm styling.
The biggest wart is the inability to functionally build up styles. For example, you have a bunch of js and you need to flip between several different colour states (say for an input that has "disabled | errored | valid | pristene"). There's no great way to force one of your classes to "win" because they're all just classes and the way they were added to the page will determine which border colour wins, for example.
Even when you do that, you're still delivering the long, repetitive mark-up to the browser, rather than relying on the CSS engine to handle this for you. You're making the DOM MUCH MUCH heavier than it needs to be and ignoring the rendering engine that's optimised to handle this role. It seems wasteful all 'round. I confess I'm guessing here, and haven't tested it, but I suspect a simple, axiomic CSS file and simpler HTML file would produce faster rendering than Tailwind, and travel over the network faster.
Tailwind improves the developer experience at the expense of badly optimised code bloating and slowing the user experience. The developer experience benefits are debatable, too: I freaking hate using CSS toolkits and would much rather just write CSS or SASS bespoke to my apps. I have more control and can tailor a solution for the problem.
Things like ads or heavy images actually slow the user experience. This type of thing isn't worth worrying about.
Maybe you shouldn't make unsubstantiated claims like this then?
> Tailwind improves the developer experience at the expense of badly optimised code bloating and slowing the user experience.
I only say this because if your claims about performance are wrong, your comment seems to boil down to "I don't like CSS frameworks," which is fine, nobody's forcing you to use Tailwind.
The crazy repetition of classes gzips away though so there really isn’t any extra overhead.
I haven't found a convincing explanation of why exactly this is better until I've used it in a project, and since then I'm completely sold. The semantic CSS concern separation pipe dream has always been snake oil in real projects.
Long live Tailwind.
Combined with either Flexbox or CSS Grid, the speed with which you can put together a good looking web page is crazy fast.
Took a little bit to get the hang of, but once I did I was working WAY faster without the mental overhead of having to cross reference 2 text files (HTML + CSS) to build the same UI, keep them in sync, come up with names, etc. I iterate so much quicker, refactoring is so much faster cause you can literally just cut and paste a block of elements, throw them somewhere else, and they just render properly cause you brought the styles along with them. Screen size breakpoints make it so much easier to make responsive UIs. You get a free, built-in layout and color system.
It eliminated basically all the major painpoints of building UIs that I had before. I use it in all my personal projects now.
No, I still know CSS but I can’t imagine coming up with class names for everything then going to a different file to define rules. Feels so long winded and hard to keep on top of.
But the experience while writing the code is pretty excellent. It made me realize that what I really want (personally) is to have my css inlined in my editor when writing / editing it, and otherwise remain out of the way in my css file.
Would be interesting to see what an experience of being able to toggle between classless and class-only jsx looked like.
"Add the option to hide class attribute in vscode plugin" https://github.com/tailwindlabs/tailwindcss/discussions/7922
That's exactly what it is.
But... you have to do that regardless of what you use for CSS layout. If you're not using Tailwind (or something like it) then you're going to end up creating classes using the raw CSS, and then naming them yourself, and then having to remember what you called them. Hopefully you're good at that and you can remember, else you'll duplicate things. Hopefully your entire team are aligned on the same naming conventions, or your project's styles will be a total mess.
Maybe you'll use styled-components or another CSS-in-JS solution, which helps a bit by making your styles scoped to components so they don't interfere with things outside of where they should, but then you'll have to keep a set of constants to use across all of them anyway, which puts you back at the same problem as plain CSS - you need to remember what's been set, and not duplicate things.
Ultimately, Tailwind is a really well designed abstraction of inline styles that means you don't have to worry about inconsistency and duplication of things any more. It's another thing to learn but because it's so similar to raw CSS it's not actually a lot of effort. It works well.
This is true. But if we better taught the cascade and promoted the idea of global styles rather than pretending it's a problem then more people would be better at this and the problems would gently recede.
We (the high-end front-end dev community) have fallen into the habit of using class names where we really wanted IDs and using components when we really wanted global styles. I feel we have been pushed in this direction by developers who didn't understand the technology properly. The Tailwind author clearly understands it, so I'm not targeting them... but they are supporting the people who don't see why the cascade is useful.
We have megabytes of code to create the impression of global consistency (components, style libraries, CSS-modules...) shipped to millions of users every hour. Browsers do that for us already. Embrace the simplicity of
button { border: foo; color: bar; } .callout button { color: aux; }
It's so clear, so elegant. The obsession with modularising everything, and then applying a DSL to get between the modules, makes the language's inherent convenience, elegance and clarity so much harder to work with that it boggles my mind.
<Button class=`border text-gray ${override}`/>
<CalloutButton /> extends <Button override="text-blue" />
I'd argue you have less markup to write overall if you are modularizing component logic/styling
for example if the corresponding css file is this: .text-blue { color: blue; } .text-gray { color: gray; }
Then in your above example, both Button and CalloutButton will have gray text because .test-gray has higher specificity than .text-blue
The thesis of Tailwind is that the cascade actually becomes very unclear and inelegant at scale, and I would say the reason it's so popular is that many devs share that experience.
But the opposite is largely true for UI elements. For one, I’m probably using some external templating or component framework to repeat them, because they mostly likely have behaviour attached and HTML by itself has no good story for that. For two, I pretty much never want their styling to be modified by the context in which they’re used.
But that’s what you’re doing when you use scoped styles, components, Tailwind etc.
Just set it once, on body and forget about it for the lifetime of your app.
> I pretty much never want their styling to be modified by the context in which they’re used.
I guess we have worked on different projects. To me this sounds like the edge case. Most projects I’ve worked on want all the components/widgets/thingies in one consistent style that works together for a cohesive overall experience. For such situations (which to me feel like the majority case) the cascade is the simplest tool.
This is the distinction to me. New methods in composing a page approach this differently: style consistency is maintained through dependencies and a build process rather than relying on context. To understand the styling I'm applying to a given HTML elemnt, I can look to the packages going into the build (just as a I do with other aspects of the code) rather than needing to understand every context my component could possibly be invoked within.
A program can read what looks like inline css and produce class names for youand put those in class files.
When developing your see "height 20px" In your app its compiled to "h-20" with a css file "h-20: height 20"
This is better because you don't have to learn another way to express the same logic.
I don't see the advantage over inline style tho. I see abbreviations as a disadvantage as its just as fast to type background as it is bg but background is clearly more intelligible.
How do you deal with side effects for example I think bg-red is the brand red but some one has modified that class so it now has a border. You could prevent this with convention but then you have the same issues as using css with specificity and people not understanding the conventions around it.
I think its easier for every one to just force your frontend developers to just learn CSS and use it.
The biggest advantage over inline styles is that you are constrained. The idea is that you set up the primitives for your application's styling system: which colors are in use, which font weights, all the way to things like which border radii are valid. Your devs can then only use those.
You are correct that theoretically you can modify them to do anything, but in practice I find that people are extremely unlikely to violate the scheme (in ways like you described, adding a border to bg-red).
As for abbreviations? I think that's probably just eye of the beholder. Since you tend to add a lot of these to your HTML it helps it not get too ridiculously out of hand.
I spent years working with more traditional CSS schemes (including my all time least favorite, BEM), and it was pretty consistently a nightmare within the context of component driven applications. For a while now I've worked with tailwind and it feels like a massive step in the right direction.
I think it's one of those things that really doesn't make sense until you try it and feel the difference for yourself.
Really? I'm not sure I could take someone seriously if they called themselves a frontend developer and did not understand CSS specificity.
Which is why this is basically reinventing inline styles. With some shorthand.
How did we go from removing <u> and <b> to calling it <div class="bold" an improvement?
You could do it with a cascading approach, but if you're building a component based application (this is what Tailwind is really for) then you already have an abstraction for re-usability. Trying to layer another one on top usually results in a really difficult to reason about mess of interlacing components and style classes.
In short it's a way to use an inline-type styling approach, which is suitable for component based apps, without giving up the ability to constrain developers to a limited design language.
There are a TON of other benefits for utility classes over inline, but I think what I described is the biggest one (media queries, pseudo selectors, stylesheet caching for reduced page load, etc.)
> How did we go from removing <u> and <b> to calling it <div class="bold" an improvement?
You can still use <u> and <b> if you want to. Adding a utility bold class also works fine.
- CSS classes can be named on a per-component basis, according to one of the well-established naming conventions (BEM, SMACSS, or whatever). This does not require remembering the names of other classes.
- With the arrival of web components, styles can be scoped within the shadow DOM; and the name collision becomes a non-issue; as well as keeping track of _all_ the CSS that's written in the project. If CSS classes don't leak, you can focus your attention only on a given component and ignore the rest.
- Instead of CSS-in-JS, one could use CSS modules, which are just regular CSS with a build step. The relevant project-level (site-level, page-level) constants can be defined as CSS constants on the root element.My lived approach to inline vs. not-inline is: why not both? Inline is great for prototyping, and for edge cases, like specific margins for wrapper divs. Where CSS classes really shine is when it comes to mature / often used components.
A few of the other advantages of Tailwind: - reduced noise in the markup compared to raw inline styles, with the underlying styles getting cached by the browser - utility classes can contain multiple properties that should always go together - media queries!
You should learn what CSS is actually doing as well, but realistically Tailwind is, like you said, a pretty thin wrapper on CSS. Learning Tailwind usually just means learning CSS, with some different property names.
You get fast iterations without ever having to leave your markup to hunt down to find all the classes elements are using which uses their own structure & nomenclature, esp. if you need to support responsive layouts which every project implements differently that usually grows into some unmaintainable mess. With tailwind's utility classes it's all right there on the element, using intuitive prefixes and shorthand class names derived from the CSS properties it uses.
It's also the only framework I've used where you can copy markup from a number of different sources and it will look exactly the same as the preview where you got it from without it being distorted by the websites leaking cascading CSS styles.
Everyone that complains about tailwind is because they didn't use it yet.
Yes, looks weird at first. That's not everything that matters.
This is not how you use Tailwind. Back then there was no such concept as component, so people need to write CSS classes to encapsulate and reuse styles.
Now Components are everywhere, and when you write components and CSS classes at the same time, you're non-obviously duplicating structures (Write components, then write classes corresponding that component).
In essence, Tailwind (or styled components and such) makes component mechanic as your single source of abstraction.
- CSS was created so no inline styling would be necessary. By assigning CSS attributes to classes we are back at inline styling. The html just explodes if you don't put the tailwind classes somewhere else, but then again, CSS is already here for that
- one wastes time learning new naming conventions. Most frontend developers have internalised CSS attributes
- it runs through a javascript lib. That makes the setup more complicated. Browsers support CSS natively so why build something on top of that
Second one is a reasonable enough criticism. Never bothered me, but I think it's fair.
Third: it's really designed for bundled, JS-based, component driven applications. In that context it's a breeze to set up, and really no more difficult than native CSS. By the way, the reason they do that is so it can do some clever things like removing the utility classes from the CSS that you actually ship to reduce payload size. There's no reason that you can't just build the entirety of Tailwind and just ship that as your CSS.
Unlike bootstrap where the button classname represents a collection of inherently opinionated and obfuscated css rules, the classnames map directly to the rules themselves - without any obfuscation behind a button class or opinions about what a button is. You can look at a tailwind classname and understand exactly what css rule is being applied. It's universally repulsive at first sight. Everyone who loves tailwind said "hell no" - but they pushed through it and ultimately understood the value in it.
The reason that Bootstrap can't continue to exist as it does currently is because our js implementations have taken center stage and bootstrap requires a js implementation for many of its components. This means to use bootstrap with react for instance, you need a third party lib like reactstrap.
Tailwind is JS agnostic and frees you up to use the react (ng, vue, etc) ecosystem's idiomatic implementations for things like tooltips without adopting an entire bootstrap abstraction like reactstrap. Any respectable UI lib will allow you to pass classnames as props. You just pass in some tailwind classes as props and call it a day.
If your initial reaction is "this is ugly" I encourage you to dig deeper. Imagine never having to think of a name for a css class or context switch in to a 400 line css file to figure out what button means. I like tailwind :)
https://tailwindcss.com/#:~:text=Worried%20about%20duplicati....
The huge benefit is, that you don’t split up HTML and CSS, you only write HTML.
Using a web framework? No.
It is clever in that half of it is missing: the componentisation that React (etc.) brings with it makes this shine.
You can also define normal CSS classes based on the utility classes if you so wish.
Tailwind after 4 hours of learning curve is so much nicer than cutting css or using old skool css frameworks. Some of that is because ready designed components exist that you can copy.
With an old skool css framework once you hit an edge case you can be snookered and spend ages diagnosing why because of some clever stuff they done.
Tailwind says “yeah css was a bad idea, let us abstract it away a bit” and does a nice job.
The moment the first important! or inline stuff creeps into the page you are doomed. Utility frameworks feel a bit like giving up at the start and just rolling with it.
The major problem i see with these frameworks is that it is harder to maintain a consistent style across teams or even a few devs.
The cost of tailwind is that you do a bit of upfront work, when defining your design system/tokens in their config. The benefit is high default performance (css is less bloated) and high productivity because you tend not to switch to CSS/SCSS and get a natural DRYness from working with it.
A named CSS class can contain any definition and even if you are certain of those definitions, they can change depending on what the element is contained within.
See: https://gist.github.com/vedantroy/80fb2feb21b07b6f53032b8725...
I wrote that. It allows me to do stuff like:
const Button = tw.div(`
bg-blue-500
rounded
`)
Any complaint about how tailwind forces overly long class names should probably look at this comment first.I even believe that their particular implementation is a total mess with way too much and continuous overhead, and that you're probably better off building your own system.
[1] https://github.com/unocss/unocss
If you mean build your own design system then I've built four separate design systems in SCSS since 2009. I've been fine with switching to Tailwind instead because I can get similar results customizing the theme, it's more comprehensive than my systems, and the network effect advantages of somethign popular vs my one-off thing.
The documentation is excellent, with working examples. It has taught me about CSS properties I didn't know existed. Instead of attempting to grok the entirety of the MDN docs, I can quickly use configurations that work. (The ubiquitous Seinfeld references are an enjoyable treat, too, though YMMV.)
The other important piece is that the tooling is great. I use the VS Code extension, and beyond the excellent intellisense, the extension gives me exactly which properties and values are generated by the Tailwind classes when I mouseover.
The only "complaint" I have is that sometimes in larger projects, I'd want to create reusable style components (almost like traits) that could be reused in components that appear similar but whose behavior is distinct. This is a minor complaint because Tailwind actually allows for this, but the syntax is slightly awkward.
In all, I'm much more productive, and I imagine my code is more maintainable. It's certainly smaller without dozens of lines of CSS including the commented out sections.
Also, it seems to me that Bootstrap started following the utility-classes approach more and more over the years (px-1, flex-column, etc.)
Bootswatch themes are nice too.
I think BS 5 is a nice middle ground between the older BS and Tailwind.
BS5 is pretty nice, but it could be smaller, haha.
Here‘s a nice green example button, written out of my head during my holidays: rounded p-2 border text-green-800 bg-green-100 hover:bg-green-200 active:bg-green-300 border-green-200 hover:border-green-300 active:border-green-400
It‘s long but somehow it‘s easy, readable, customizable and consistent. The limitations are still there though, just think of transitions and animations.
Personally, I would also be happy if inline styles wouldn‘t be with their limitations, but that entirely another topic.
I presume the use of so many divs is a stylistic choice and not a requirement?
One thing I wish Tailwind did with production builds is take all those CSS classes and run them through a css-modules transpiler. If they can detect the names in the files, can't they also use the same lexer to do replacements on the code too?
That would be the ultimate efficiency, in terms of bytes saved.
However, I do find it laborious some times, since I have to define properties for each div every time, instead of just selecting things by CSS classes. Or I am doing this wrong.
The only reason I use tailwind is that I can keep styles close to markup, I would just use inline styles if they had access to media queries and pseudo selectors
You can also do text-[20px] if you really need that specific size.
Popular now, huge pile of mess in a few years.
After seeing this example, I certainly never will.
Why submit this? Been part of the docs/demo page for years.