I used the JIT version recently on a new landing page with code completion for class names in my IDE and found it great. The distance between what I'm picturing in my head and what I have to type to see that on the screen felt so much shorter and less fatiguing than the standard CSS approach.
With the regular way, to style something that's probably not going to appear elsewhere, I'm having to: come up with class names, annotate the HTML with them, repeat some of this annotating in a CSS file, jump back and forth between files to tweak the styles, use the web inspector to figure out which CSS class is overriding another then jump to the right CSS file to fix it etc.
Tailwind classes are also faster to type and flip between when you're experimenting (e.g. editing "mt-5" to "pb-3" vs "margin-top: 4.25em" to "padding-bottom: 2.75em") and you get less distracted because it has sensible defaults and helpful guardrails (you rarely need all the possible attributes and range of parameter values CSS has available).
I also rarely had the super irritating and common CSS scenario where you edit a style and it doesn't change and you have to go investigate to find out why e.g. something is overriding something, your selector is wrong, and even after all that maybe you undo the edit because it doesn't look good. Plus you no longer have the fear that tweaking a shared class to going to break some completely different page.
I feel that beyond some building blocks, trying to create reusable CSS classes with cascading styles has similarities to using excessive abstraction and deep OOP class hierarchies in regular programming languages to avoid a little duplication.
I also don't have a problem with styling stuff appearing in my HTML files either as long as the right HTML tags are used around the data. HTML files are already full of class annotations and divs that are only there for styling yet this doesn't cause a problem to e.g. browsers, screen readers or crawlers.
> I used the JIT version recently on a new landing page
Yeah, that's kinda the poster child use case for Tailwind and similar frameworks. Landing pages are all about being jazzy and unique and eye catching, and not so much about code reusability/composability.
Where it gets less fun is when you want widget consistency across multiple areas of a site and across design tweaks over time, since now you have to deal with several `class="..."` strings across multiple files, possibly with class names in arbitrary order, possibly mixed with logic from other templating languages (be it from Django or JSX or whatever). So you can't just grep to achieve the objective of changing styles in one place to affect all instances of some semantic group.
Personally I think comparing Tailwind directly against traditional CSS as a whole is painting in too broad strokes. There's a lot of CSS methodologies and also a lot of bad practices (e.g. using SASS indentation as namespacing mechanism and then running into the old problem of specificity), and comparatively, there's a lot more than Tailwind in the atomic CSS space, and more broadly, in the compiled CSS space.
Utilities like Bootstrap (e.g. `class="btn btn-primary"`) for example share many benefits of both atomic CSS and "good" subsets of traditional CSS practices (namely, you get memorable short class names, which are also organizable along semantic lines). So there's definitely more shades of gray than just "atomic-css-is-the-best-thing-since-sliced-bread" vs "looks-like-lazy-style-attributes-lol".
In the context of component based development, react etc., I believe what you describe is actually very beneficial. Think about a case where instead of doing something <button class="btn btn-primary"> you write an atomic component <MyButton> which uses tailwind internally.
With this workflow:
* There are no global styles that can have an unknown or unexpected impact on the application when modified.
* The component's style is completely encapsulated. It can be placed anywhere in the application without worrying about inherited styles causing problems.
I use Tailwind utility classes extensively to create reusable components in a Rails app using GitHub's ViewComponent gem (https://viewcomponent.org)
Occasionally, I'll use @apply directives to DRY up something that isn't easy to encapsulate at the component level, but 95% of the time, I can easily get by with utility classes.
I try to avoid using hyperbolic-sounding language like 'revolutionized,' but Tailwind + ViewComponent has basically revolutionized the way I build user interfaces in Rails.
I had the same concern at first. I remained skeptical during my first couple days working with Tailwind, but came around pretty soon thereafter.
I realized that all of my semantic CSS classes might as well have been inline CSS for all the good they were doing me on reusability. Utility classes are faster to work with, and, as long as you’re componentizing everything, still going to give you consistent styles across your product.
The usage of utility classes only become an issue if you have unnecessary duplication of components. Say, two buttons that should be the same but are implemented in different places.
IMO one of the interesting parts of functional CSS is that we can apply the same tactics we use for organising code to organising the styling.
Also, with separated CSS, and especially with semantic CSS, there is often a fair amount of duplication that happens in the CSS code itself, which we programmers tend to be very forgiving of. Giving Tailwind more scrutiny than we do for our CSS ends up making our code more consistent, less duplicated and better in general.
My experience with Tailwind + ViewComponent has been great as well. I've also had a lot of success with adding Sorbet typing to the view components. I often use Sorbet enums as view component options. The extra type safety in the view layer is very helpful.
I mentioned downthread about a project called Styletron, which has styled-components-like devexp, but compiles to atomic CSS for the bundle size benefits.
Another variation I've seen is a combination of atomic CSS and Mithril.js' hyperscript selector syntax, which lets you do stuff like this:
I am going to give it a try. The argument against using it is that it defeats the purpose of Tailwind, but I think its useful to start by spraying classes until things work and then moving those classes into e.g. btn-primary once the styles become stable and need universality.
Yes, @apply exists, but is generally discouraged (and the rationales are given right on that page)
> If you start using @apply for everything, you are basically just writing CSS again and throwing away all of the workflow and maintainability advantages Tailwind gives you
Approaching it with moderation is probably worth trying though
It's the same as any DRY or optimised code: taking time and effort to make things overly DRY or optimised up front is a waste, building stuff out and then refactoring when you realise it's going to be repeated is a better workflow. With tailwind, that's simple because you take your string of class names, slap an @apply on it, and then use the new classname instead. No, it's not significantly different from just writing CSS then, but it's the workflow that's changed that reduces the friction between prototyping and then refactoring into a reusable design that makes Tailwind nice to work with in my experience (and I'm using it for a large-scale commercial project, not a landing page or static site).
I'm pretty sure the creator's intention is that you basically don't use @apply at all, except maybe edge-cases where Tailwind simply can't be used (for example, I think before v3.0 you couldn't set print styles, i.e. @media print)
The intended method of not repeating yourself in Tailwind is using a framework, and writing the styles in the template of the component.
We recently started using a combination of tailwind and BEM instead of bootstrap.
It means that we can have our own custom "button button--sm" classes - a single place to change general styling - and on top of that get all flexibility of the tailwind utils for edge cases.
I don't think it's perfect, but it's so far much more flexible than bootstrap, and we don't need to duplicate loads of classes for each similar component.
> Yeah, that's kinda the poster child use case for Tailwind and similar frameworks. Landing pages are all about being jazzy and unique and eye catching, and not so much about code reusability/composability.
It doesn't matter, you can have an entire newspaper and perfectly done in functional css with incredible results without having to mastermind any architecture.
The trick with CSS is to write semantic HTML and avoid div, span and css classes. You can of course inline css too (used mostly for optimization to prevent layout shift, but is also fine for elements/classes that are not repeated, such as the top menu, top banner/intro and header/footer)
> The trick with CSS is to write semantic HTML and avoid div, span and css classes
This experiment has failed though. CSS isn't powerful enough to style HTML however you want without having to add a soup of extra divs and classes that are only there for styling. No large website today works otherwise.
HTML is still semantic when it contains styling markup (in the sense that a computer can read and understand the structured data from it) so I'm unclear what benefit is being missed out on. Whether you call a class "home-cta-subheading" or "text-center" so you can apply some styles doesn't make a difference to screen readers, browsers or search crawlers either.
> CSS isn't powerful enough to style HTML however you want without having to add a soup of extra divs and classes that are only there for styling
Totally this. We say we've come a long way from using tables for layout, but for example you still can't use Flexbox without at least some non-semantic .stuff-container and .radio-with-label junk. Decoupled HTML and CSS have failed in the real world, outside of pet projects.
The example on the Tailwind front page is pretty good semantic wise. Here's my version:
<figure>
<img src="/sarah-dayan.jpg">
<blockquote>“Tailwind CSS is the only framework that I've seen scale
on large teams. It’s easy to customize, adapts to any design,
and the build size is tiny.”</blockquote>
<figcaption><b>Sarah Dayan</b>Staff Engineer, Algolia</figcaption>
</figure>
Now without modifying the HTML, how would I get the author's name only to appear on the right of the author image with the other text underneath? And add a line break before the company name? And make the word "tiny" use a small font?
And if you need to modify the HTML, were the extra tags added 100% only for semantic reasons and not for presentation reasons?
It's possible if you substitute "without modifying the HTML" with "without modifying the HTML for styling purposes." That's because the HTML is adversely and unnecessarily bare-bones, missing semantic markup that the CSS could hook into if needed. Specifically:
- There must be a logical reason for wanting to make the word "tiny" use a small font, so that word is missing a tag that represents that prosaic intent. I've used <small>, but depending on how you'd verbalize the word "tiny" (which is what you're representing both with making it use a smaller font and with wrapping it in a semantic tag), you might also wish to use <em> or another tag.
- Similarly, there is missing semantic markup inside the <figcaption> for the person's name, job title and company. Those are semantically separate concepts for each other, but for some reason the example HTML was written without semantically differentiating them. This is much like trying to represent two paragraphs of prose with just a couple newlines, rather than actually wrapping each in a <p> tag. To fix this error, I've added tags as necessary to implement the semantic hCard microformat -- independently of styling.
- I've also added the recommended attributes to the image tag, because it was missing. (And for the sake of the Codepen, I replaced the image's src with a placeholder so as not to hotlink from tailwind's site.)
Given those improvements to the semantic structure of the HTML, here's how you can make the author's name appear on the right, with the quote underneath, with a line break before the company name, and "tiny" in a small font: https://codepen.io/Kerrick/pen/KKXgPYw
> There must be a logical reason for wanting to make the word "tiny" use a small font
> - Similarly, there is missing semantic markup inside the <figcaption> for the person's name, job title and company. Those are semantically separate concepts for each other, but for some reason the example HTML was written without semantically differentiating them.
Presentation/visuals aren't always tied so closely with logic though. "To make it look nice" is a valid reason. As I said, this experiment has failed. All modern website designs use divs + classes everywhere for styling. I agree extra semantic tags would be useful but at some stage you're going to be forcing yourself to come up with semantic reasons to add a tag when there isn't one.
> I've also added the recommended attributes to the image tag, because it was missing.
Related: alt="" is best practice for when an image tag is for presentation purposes only because images don't have to be there for semantic reasons.
You don't use CSS to move stuff around. If you for example want to place paragraph-1 below paragraph-2 you simply move it in the HTML.
And if you want to add a line break you add <br> in the HTML.
If you want to make a word tiny, you can use the <small> HTML element.
The trick is to keep things simple.
Then when you have mastered the rules, you can break the rules. eg. when you can style semantic HTML however you want without adding div's and CSS classes, that's when you can start adding a little div and class here and there just to keep things even more simple.
Simple code is most of the time faster to load, and easier to maintain.
I tried it just for the lolz and without changing a single bit of HTML. It's absolutely disgusting and nobody in their right mind should do this EVER! Only tested in Chrome, it might fail in other browsers. And on mobile it will very likely break.
The original challenge includes questions that apply only if the resolution involves HTML modifications, which (contrary to the earlier text viewed in isolation) indicates that such modifications are not invalid in response to the challenge.
Take a look at the https://tailwindcss.com/ page and search for "div". Can you replace them all with more semantic tags? If not, can you remove them and still style it the same way?
You need divs all the time for layout (e.g. to group parents/children in the right way for flexbox), to target content for styling (e.g. putting a div around the name of the author to make it blue when you otherwise wouldn't tag it) and to get around CSS quirks (search for "wrapper div" for examples).
The discussion is not about the semantic expressiveness of HTML. There are certainly limitations, but these are limitations of HTML. The discussion is about whether or not "tag soup" (excessive HTML elements) is necessary for styling with modern CSS. I cannot think of an example of where it is.
> Can you replace them all with more semantic tags? If not, can you remove them and still style it the same way?
I looked at on the first four examples, but my responses are yes and yes.
Take the figure example. The first div, which groups blockquote and figcaption, is extraneous and unnecessary for the end styling result. The second div is not extraneous because it exists for a purpose. The purpose of the second div is to place emphasis on the name or make it stand out. Thus, it should be changed to em. The third div is extraneous. With the HTML in place, grid it up.
You have the container (figure) with two columns and two rows. The image sits in the first column spanning both rows. The blockquote sits in the second column on the first row. The figcaption sits in the bottom right-hand corner. Then tweak to get your img and other parts as desired (e.g., width, spacing, font-size, etc.).
> You need divs all the time for layout (e.g. to group parents/children in the right way for flexbox) ... to get around CSS quirks (search for "wrapper div" for examples).
Sometimes flexbox is the wrong tool. Sometimes floats are better. Sometimes grid is better. If you find yourself reaching for extra HTML elements first, you should stop and re-evaluate whether your approach to achieving that layout is appropriate.
On quirks, my experience is that "quirks" are rarely actual quirks. They are usually a limited understanding of HTML and CSS.
Can you link to any complex designs you've worked on that only use semantic HTML elements and minimal divs/spans? Are you saying that any modern website that uses wrapper divs is from lack of expertise?
> Are you saying that any modern website that uses wrapper divs is from lack of expertise?
That's a loaded question. CSS frameworks (or tables, or div based designs) are also used because they save time when iterating, not because of a lack of expertise.
You've never put a number of elements together in a div, and added a class and styles to that div rather than each individual element? You should try it out.
Just open up the inspector on any major website like Facebook, Twitter, Github, etc. How complex is the UI you typically work with? Once you get to a certain level of complexity, it's literally not possible to not end up with the div soup.
Not eparating concerns also fails VERY hard, but that bites you in the arse when you least expect or want it (unlike writing good CSS which takes only patience and studying).
There's a reason why inline styles and important! were to be avoided
Exactly. Also you rely on the development criteria and developers switch jobs and they have different mindsets for architecture. The CSS ends with a soap of architectures and technical debt.
Yes, you should always be using the elements/tags with the most semantic meaning you can. When you need to add divs, spans and classes for styling reasons though, they're going to be ignored by screen readers so there's no problem here.
I agree. I think the real crux of the issue is that people find CSS hard, and are embarrassed about finding something that's "just a style sheet" hard, so they flock to more complicated alternatives.
I'm really glad I just powered through that point and let myself feel dumb.
what does semantic html has anything to do with css. Doesn't this make the look and feel of the page easily break on any change on the markup structure and content?
Also does this comment even has a point? Like if we do what you suggest then no need of tailwind?
I tried Tailwind (and a similar project Windi) on a few projects now and have some findings.
Tailwind aggressively speeds up development time of components by allowing me to stay in the same cobtext when styling things. The brevity of class names also dramatically shortens the time spent writing styles. While working on the projects I'd setup with Tailwind, I felt far more productive.
However, those were new projects. After completing them and needing to go back and modify or maintain them, the experience has been horrible. The resulting style declarations (as class names) are completely unreadable and unmaintainable. I've tried organizing them and splitting class names onto multiple lines, but it has only cluttered things.
In my experience, Tailwind (and similar projects) produce styles that are effectively read only. They are superb when writing a new component and styling things from scratch, but maintenance is nonexistent.
Because of this, I've now switched to using a CSS-in-JS solution to gain the benefits of in-context styling and still have the ability to write CSS declarations in a structured and maintainable way.
We use Tailwind at my work and I personally find hopping into the template of a file I've never been in before super easy with it. With normal CSS I've usually got an HTML file and a CSS file side-by-side in my IDE, and I'm cross-referencing awkwardly-named classes in the template with a stylesheet. Sometimes these styles might be coming from a local, dedicated stylesheet, sometimes they might be coming from a global stylesheet that I might end up needing to grep through the project for in order to find where these styles are coming from.
With Tailwind, I see a <div>, and I see all the styles on it, right within the template. I don't need to follow class names, or cross-reference between files, it's just there, where I'm already looking.
I'm very surprised that people actually like tailwinds.
I wrote HTML in a time when you used inline HTML attributes for styling. Changing one bit of the style meant visiting every single page to update everything (then making sure to test because you definitely forgot at least one place).
CSS was an amazing idea for making just one place to put all your styling. You could now change one style and everything else would automatically update.
Tailwinds feels like it's just a trip right back to the old inline styling right down to searching bunches of pages if you're making a styling update.
Why not use both? twin.macro is an excellent library that compiles Tailwind (and adds additional, useful variants) in systems like Styled Components and Emotion, so you gain the benefits of quick component creation, but the same pleasant maintenance of colocating utilities and styles/classes/objects composed of these utilities with your components.
It's been an absolute dream in a decent-sized project so far, and even with some refactors.
Regardless, it's not everyone's cup of tea, but depending on the UI framework of choice and the flavor of CSS you use, YMMV when it comes to dev experience.
In Vue or Svelte, I wouldn't even use a CSS-in-JS solution because vanilla Tailwind to compose utilities into localized classes is a straightforward approach.
If you're using Svelte, you don't really need Tailwind (but are obviously free to use it), especially if you're using your own components.
Svelte's styling is already pretty atomic as it is.
With Svelte, I use a small global reset, and a global file containing native CSS variables (which I reuse across multiple projects).
Most of my Svelte CSS is component specific (and in most cases, no classes are even necessary) and they can be themed by simply referring to the CSS variables in my global variable file.
Yes, it's very similar to that. I looked at Pollen a while back to see if there were any ideas I missed, but while Pollen has a different approach to variable naming, it was very similar to what I do.
I found exactly the same with my brief experience with Tailwind. Great fun to write, couldn't make head nor tail of it when I came back a few weeks later. Perhaps this changes if you use Tailwind day in day out though!
I've stuck with styled-components for now, though I confess that I've started to wonder if the the verbosity of creating a (styled) component for everything, passing props, etc. is a bit excessive since trying Tailwind.
The only thing I appreciate Tailwind for is that I started to dig deeper just to have even stronger hesitation against it, so I believe I've saved a lot of hours in my projects just by not using it. But it also got me stumbling upon solutions based on the CSS global variables and that's what I think is the CSS next big thing. They allow to stay with CSS within CSS layer so no leakage to HTML or JS.
I'm not sure I get Tailwind still. Doing everything with utility classes and OOCSS / BEM are things we stopped doing literally decades ago. CSS modules still seem to solve every problem Tailwind solves, and better. CSS modules combine the power of global utility classes with locally styled components/locally scoped classes, and compile to static stylesheets, a requirement for performance. I'm not sure how Tailwind works, but any CSS that's built at runtime and JS and inserted into the DOM dynamically should be avoided, and is an example of favoring developer experience over end user experience. It's always surprising to me when the build process isn't front and center of any CSS framework, since that's the most important performance aspect. I'm not concerned about Tailwinds verbose CSS use since that's gzipped away, but the static stylesheet compilation aspect worries me if it's not front and center of the framework.
CSS modules let you use the full power and control of vanilla CSS, without having to worry about styles bleeding across components. Sprinkle in your global utility classes for your design system and you're good to go. Or sometimes even better, abstract design into components like `<grid>` `<column>` etc and not even worry about the classname implementation.
I know I'm missing part of the picture, because of the hype and joy that people report from Tailwind. What part(s) am I missing that move folks from the power, beauty, and simplicity of CSS modules, to all-utility-classes-all-the-time Tailwind?
Seems like you are basing your opinions on some misconceptions. Let me try to clear that for you.
"CSS modules still seem to solve every problem Tailwind solves, and better."
- Not necessarily true. Unlike css modules, tailwind removes the whole "think about a name for your class" mindset, reducing friction from the development process. It also unifies some base level design decisions like spacing and colors, which developers would have to rely on "best practices" otherwise, which don't necessarily get strictly enforced.
"I'm not sure how Tailwind works, but any CSS that's built at runtime and JS and inserted into the DOM dynamically should be avoided, and is an example of favoring developer experience over end user experience."
- You are right, looks like you are not sure how Tailwind works. Tailwind does not build anything at runtime, it all happens at build time. Tailwind will compile only the things you need (using the new JIT mode) into a css stylesheet which is sent to the frontend. Not much different from how sass or scss works.
"CSS modules let you use the full power and control of vanilla CSS, without having to worry about styles bleeding across components."
- Tailwind does not stop you from using vanilla css, but in most cases you do not need to. As per their website, you can think of it as an API to use parts of CSS, instead of CSS replacement. I think you are confusing Tailwind as a replacement for something like CSS Modules, but those two are completely unrelated. You can still use CSS Modules while using Tailwind. Think of it as an api to your design sytem just like you could think of an ORM as an API to your database.
Aside from all of this. Try to use tailwind for 1 side project. You’ll see the difference of productivity when you remember most of the tailwind classes as opposed to having to open another css file, create a class, then reimport them.
I used Emotion for a few years (CSS-in-JS). I was so in love with it that I never thought I'd change to something else. But Tailwind converted me. I can't go back either, it's too powerful.
You can use both and gain the benefits of Tailwind-in-JS to dynamically apply utilities and arrays/objects of utilities composed together, all using a nifty wrapper library called "twin.macro".
It sits on top of Styled Components or Emotion (your choice), and uses your project's Tailwind config faithfully, minus a few of the plugin features.
It eliminates the need for JIT or PurgeCSS because it compiles Tailwind's utils with a drop-in Babel macro, eliminating the need for PostCSS.
As a lover of vanilla Tailwind in Vue and Svelte projects, Twin Macro has made using it in React 10x better and I haven't looked back! :)
+1, tried Tailwind and liked it, but when I found I was able to use CSS-in-JS with it with twin.macro i was amazed. Now is used on all my side projects.
It's Typescript-friendly, and if you use the Twin Intellisense extension for VSCode, it will autocomplete from all of the generated utilities in Tailwind, even the ones created from your own configuration of colors, spacing, etc.
Twin Macro has a few snippets of type definitions you can add to your project based on whether you're using Styled Components or Emotion, specifically to support these two props (tw and css).
They link to their Examples repo from the official readme with several projects using many different combos, with a handful of TypeScript ones.
JIT mode basically means it recompiles your styles before you can press reload on your browser.
Before they didn't have all colors enabled by default, because generating classes like `bg-blue-500`, `text-blue-500`, `border-blue-500`, etc. for all colors would increase the resulting CSS way too much. They did the same thing with variants.
With the JIT none of that is necessary anymore. Plus you can use arbitrary values because it's being compiled now.
And even that is less magic than it sounds. Unless it’s changed in v3, there’s just a regex matching stuff that could be a class name and building a rule for it.
The other thing is, building css the traditional way, after refactoring and renaming things a bit, I usually end up with something that looks very similar to tailwind syntax anyway. So might as well have a flavour of that we can all refer to and agree on than each person having their own set of utilities and naming conventions. That way I don't have to explain or write elaborate comments - I can just point the person to the tailwind docs. So it solves that kind of problem for me.
> You can still use CSS Modules while using Tailwind
Recommended even. I use Tailwind with CSS Modules as a fallback when there's simply no way to achieve the result using Tailwind (rare) or it's prohibitively complicated/messy.
Also for CSS hacks if you need to support an older browser.
Based on what you've said, you're right, you don't understand it...the things you're comparing it to don't really make sense. Bem doesn't make sense to compare and neither do css modules. Tailwind is a stylesheet with css classes that do atomic things like changing border radius. It gives you a set of classes that allow you to build just about anything you need with just classes. When you compile an app that uses tailwind, it takes just the styles you use and puts them into a single stylesheet. So all of the things you claim to be wrong with tailwind aren't true. Tailwind is very performant because you only use the styles you need. It uses css variables for theming so there's no need to implement it in userland. It also uses css variables to do transforms which is very important because transforms are not additive in css yet. Even if you don't end up liking tailwind, the thing is executed really really well from the ground up.
> ITCSS (Inverted triangle CSS) works with the cascade and results in clean, minimalistic CSS files.
The real Tailwind lightbulb for me was understanding that the cascade and actual CSS files don't matter anymore - you don't need them. No more inheritance, no more naming, no context switching.
I'm a big fan of ITCSS and was using Harry's methods before he coined the name but we don't need to fight the cascade any longer.
> I do not build SPAs though and do get that quick styling works really well for that scenario.
Admittedly, if you're not breaking down your UI into small components then Tailwind will get real messy, real fast.
I think Tailwind is multiple very different ideas in one library. One thing that Tailwind is is a set of primitives and design tokens that’s just slightly higher level than CSS, but still lower level than a component library. I think it’s pretty good at this.
Another thing that Tailwind is is an opinionated delivery mechanism for your styles, in this case, as utility classes that can go straight into your HTML. This is probably a big cause of Tailwind’s popularity, not because any one person necessarily loves using classes, but because it makes it extremely easy for everyone to start using Tailwind in nearly any imaginable web project starting at plain static HTML files and going up from there. This aspect of Tailwind is something I’m not a huge fan of. To me it feels like a step back from a lot of higher-level CSS tools (like many CSS-in-JS libraries) to just go back to concatenating magic string literals into my UI code. All the official Tailwind tooling (AFAIK) either just watches your codebase looking for these magic string and generating the appropriate raw CSS, or doing it in real-time with their new JIT compiler (which I admittedly haven’t investigated yet).
I agree with this. I think the "set of primitives" part is an interesting, perhaps great, idea. Makes it easy to enforce consistency across your codebase. But I don't like the delivery mechanism--chucking all the styles in with the markup feels like it makes everything hard to read: the HTML/component declarations are harder to read both in code and in the browser, the individual classnames are hard to read (both because the names chosen are often gibberish and because parsing a dozen of them in a row is difficult), and the styles are annoying to debug in the browser (now you have to scroll through a dozen different utility classes to figure out what's going on).
Personally I feel like a better approach is taking that same philosophy of design system primitives and executing it via something like SASS mixins, paired with single-file components à la Vue or Svelte. Then you can use better names (no need for brevity now), keep the styling separate from the markup (but still paired with it), and have a better experience debugging in the browser.
what do you think "high level" css-in-js libraries do if bot string concatenation, just watching your codebase with magic strings and generally ng raw CSS?
CSS-in-JS libraries are not magic that summons CSS out of thin air. They basically do the same thing Tailwind does: they watch your code for changes, they re-build/re-create raw CSS by, yes, often using string concatenation etc.
> CSS modules still seem to solve every problem Tailwind solves, and better.
I agree with most of what you're writing, but in arguing this out with people who seem to be enthusiasts, what I think I've discovered is that while there are existing (hell, longstanding) unbundled technical solutions fully capable of solving the problems Tailwind does... they don't solve the practical problems of channeling a group into a good-enough design system, and in fact many people who've been doing CSS have never actually really used a design system (especially if their experience is solely recent, and definitely if their experience is only incidental in the sense that they're application devs first). And many organizations don't have roles where someone can focus on solving this problem.
Just-add-Tailwind may hit an interesting pit-of-success spot for a lot of people in this position, where TW provides the atoms of the design system to scatter in a just-in-time manner. Sure, not elegantly, but practically.
Personally, I'd prefer to work with people/orgs that don't see this is an optimum, but I might accept it as a situational local optimum.
Tailwind is great if you're a startup, or someone who is a webdev and also has to be the designer. But in a large organization, with a company-wide style book, and a design department, it's not a good fit.
Tailwind works for "I see this control in my head, and I'm going to code like this to make it happen." It's not really a good match for "I see this control from the design department, and I'm going to make it fit into the rest of the site codebase like this."
Let's be honest, there isn't much elegance to the non-Tailwind solutions either. At the end of the day it's text input used by a rendering engine to style layout, it and your customers don't care how it got there.
Tailwind is global utility classes too. There’s no runtime aspect. It’s literally just css classes. The nicest thing is that all your variations exist, so you can do things like hover:font-bold. So you can see the rules immediately like with inline styles, but they’re more flexible.
At least finally someone using the dirty word "inline styles". It's like all the other comments here stepped right over that point from the grandparent. Only it's not inline styles, it's inline styles and you are Dennis fucking Ritchie in 1970 and your fingers hurt from the teletype so you are making up crude abbreviations for everything.
Side note, most of the time you don't want to make a font bold on hover as most fonts this will increase its length to account for increased stroke width. It doesn't transition well either.
I'm in the same boat. Started using Vanilla Extract (https://vanilla-extract.style) earlier this year and it's the best CSS setup I've ever worked with.
> CSS modules still seem to solve every problem Tailwind solves, and better.
I don't understand Tailwind either; but I find myself struggling with CSS modules when I need to override a CSS rule of a child from a parent. Like, say, my button should always be green, except in this context I want it to be purple, its font-size larger and its padding a bit different. With CSS modules, the parent component is unaware of the class name of the child component; so it cannot target that. Perhaps this should all be done with CSS variables; but then hell, how many CSS variables should my components expose? and besides, I am not even sure even they will completely solve this.
Yeah, sounds sensible. What I've been doing so far was attempting to extend the base class like so:
import classNames from 'classnames';
...
className = classNames(styles.buttton, props.className);
But this leaves me at the mercy of the order in which webpack builds stylesheets (sometimes props.className will be defined after styles.button and my plan would work; other times it will get defined before styles.button, and styles.button will override the CSS rules of props.className).
Really wanted the extension of the base rules to work out; but I guess you are right: the className from the props should override entirely one of the classNames of the component.
I don't personally care for Tailwind, but I get the reasoning why people gravitate towards it: just as modern JS moved away from inheritance to composition, so is CSS.
There's a fundamental argument that inheritance is a mirage and things in large projects become much simpler with composition-based approaches. You don't really need to grok the inheritance chain with Tailwind in the same way you do typical CSS.
For my personal projects I'd continue writing my own CSS... but for teams, I'd go to Tailwind without a second thought.
> Doing everything with utility classes and OOCSS / BEM are things we stopped doing literally decades ago.
I don't understand what you mean by this. Literally decades ago would take us back to at least 2001. OOCSS, BEM, etc. were all created after that year. Wouldn't it be correct to say "Doing everything with utility classes and OOCSS / BEM are things we hadn't even started doing literally decades ago."?
just got parachuted into a tailwind project. have to say I don't fully get it.
the major stumbling block has been how tailwind is mostly just css translated into its own hard-to-memorize lingo.
For example, say I want to do something basic like "display:flex; justify-content: start".
In tailwind you would type "flex justify-start" instead.
Which doesn't really follow any rules as far as how to get from A to B, so it's just a matter of having to look the magic word up in their docs each time until you memorize. And there are a lot of keywords (many modifiable according to n-dimensional properties) to memorize.
I know there are handy slugs like "w-1/3" that encapsulate a best practice - but I'm a person who'd rather master the underlying mechanics of that best practice and be able to deploy, tweak and debug it myself.
* low specificity (tailwind doesn't do !important)
EDIT: It "does" important, but only when instructed so, in 1.x it was a global switch, apparently since 2.x its available as a per-class modifier. Thanks dcre
In this scenario, "@apply" is just "a css class", so i don't think it's appropriate to list that as a benefit tailwind has over inline styles. In both cases you'd be defining the styles somewhere else.
Media queries are a good call out, they're definitely a benefit tailwind's approach has to the built-in browser support for inline styles. Another benefit is hover and focus states, which are very difficult to apply with inline styles.
To be fair, one of the big perks of Tailwind (IMO) is not having to have a big ol' folder of CSS that you have to figure out what applies where in HTML, but rather just having all your styling inline (while still staying consistent, which is the usual downside of inlining styles manually). Having to have a tailwind-addons.css when you needed random bits of CSS they didn't have classes for kind of sucked; this looks like a nice QOL that would get me back to the original goal of uniting structure-and-style into singular files.
FWIW, I also hated using header files in C++ and also wrote a Ruby library for inlining all my tests immediately following the functions they test. I like having more context when looking at code without having to flip around from file to file to piece a bigger picture together.
This seems silly, but even this has benefits over online styles: it generates a scoped classname that wouldn't interfere with others, and you can use this syntax with JS conditionals to dynamically apply CSS with values interpolated if you need.
Not much different than injecting an object in a `style` attribute in practice, but there's a lot of creative firepower in the arbitrary styles API.
Then why not just type that, instead of having to learn a completely separate set of concepts to map to the underlying CSS properties & values? I program with inline CSS styles all the time when I'm prototyping something or building a page quickly.
It's much more concise than inline styles, variants and configuration give you a lot more power, and it's not a separate set of concepts. It's a subset of the same set of concepts.
Coming up with variable/class names is one of the most annoying aspects of programming, so any way we can eliminate that task I think is always going to be a productivity boom
So strange. Using good variable names is even better than docs in my experience. And having HTML where every div is named helps a ton. It blows my mind how different people's preferences can be on these things.
Memorizing and looking up names has significant impact on my productivity, especially on codebases that I do not touch frequently. I often losing my train of thought or momentum because of too much abstraction
the semantics of most html elements is useless to know for more devs (and classes don't help users)
in fact a class like .red conveys more useful information to a developer than .standout-link because when we go to change the colour of the button it's the colour we care about, not the "purpose" of the button
that gets long - especially if they are rendered inline, hard to scan through.
I'm often in a cycle where I am tweaking a complex class with 10-20 properties including flex, transforms, animations, etc. - and having them each be on their own line (and the class being in a separate file along with its parents, siblings and children, frankly) is key for readability to me.
I guess in the end I have come to have enormous respect for CSS as a powerful, mature language and I'm not looking to be buffered from it.
I put most of my Tailwind utilities on their own line in my HTML, and for elements that need more than 3 or 5, I do the same but in classes or styled components where I'm listing them off instead.
The beauty of it comes when you're working in a team of say 5 other front end devs of varying skill levels. There tends to be a large amount of duplication & overlap, people have different ways of doing things and achieving certain looks. If everyone agrees to use tailwind, you stop people from writing custom code which is ultimately a good thing because custom code requires custom comments and custom documentation etc which let's face it - nobody does or wants to do and even if they do, it's not maintained to the sort of standard tailwind docs are.
Not to mention, if your css isn’t scoped (and let’s face it, this is one thing traditional css sucks at) you just never quite know what rule some developer has put in somewhere at what else it effects.
> the major stumbling block has been how tailwind is mostly just css translated into its own hard-to-memorize lingo.
This is the only problem of tailwind, it relies on its own lingo, as all the OOCSS/BEM projects. When you involve semantics, you will always bring these kind of problems.
Spot on. Whenever you add a DSL like this, you need to carefully weigh costs and benefits. A hidden downside is that every new person who views your code base (And you in the future!) has to become proficient with the DSL. The base tech it wraps (HTML + CSS) is more fundamental; less overhead.
Another way of saying this, is that Tailwind adds cognitive overhead.
In my experience it's because any web app with complicated styling rules tends towards this anyways, except all the CSS names are custom, undocumented, and duplicated. The main tradeoff is that the CSS names are not domain specific, but honestly that's worked fine for me.
I hear you. I don't understand the reasoning behind frameworks propensity to abbreviate things, especially at "atomic"/utility levels. I think it partially stems from wanting to prevent ignorant knee-jerk reactions like "hurr durr why not just write inline styles".
I wish framework devs would just hyphenate (or even colon-ize) the CSS property names fully like "display-flex justify-content-start". I think Bootstrap does their own pattern like "d-flex", but all that does is require one to visit the docs to view some less common properties. Autocompletion pretty much makes typing these a breeze, and having less opinionated patterns for property names will make it less painful transitioning between frameworks.
One thing to consider is that being a bit more terse in tailwind is good because you effectively end up with media queries, dark mode, hover states etc all placed together.
> the major stumbling block has been how tailwind is mostly just css translated into its own hard-to-memorize lingo.
Autocompletion in your IDE makes this easy (the class names are similar to the CSS attributes, even in your examples, so you can usually guess them) and you use the same classes over and over again so you learn them quick. I barely spent 10 minutes in the Tailwind documentation the first few days because of the VSCode extension.
ah yes - that would be a big help. alas I am not a vscode user. I use webstorm and haven't been able to figure out how to get tailwind autocomplete to work with it.
Try using an IDE extension for autocompleting Tailwind's utilities based on your tailwind.config.js.
Twin Macro is a great wrapper library for Tailwind-in-JS with strong IDE support and it autocompletes all my utilities. I barely have to type anything to style everything in my project.
I can even hover over utilities to peek at its raw CSS.
I don't do frontend except when I have to and "flex justify-start" is way easier for me to learn and explore with than "display:flex; justify-content: start"
And the keywords all seem to make sense to me? It's "n-dimensional properties" but the dimensions are pretty consistent...
You have to learn the more verbose CSS properties in the first place, and the vast majority of tailwind's class names include the unique keywords of those anyway.
I'm ambivalent about Tailwind, but I've used it a lot. I will say the hypothetical advantages are mostly the following:
1. It's a step function over CSS units. This is the biggest strength, just standardizing that your design uses padding of 2, 4, 8px, but not 1px, 3px, or 1.23123em :). It provides more steps than you need, but still it's good that the core of Tailwind is a design system with defined unit and color variables.
2. Some of the utility classes are very helpful. Even as someone who likes writing CSS, it's nice to not need to give something a custom classname just because I want to put margin-top on it. class="mt-4", done.
I think the problem is Tailwind goes too far and tries to replace EVERYTHING with a stack of utility classes.
This works okay in extremely componentized web apps. It's a nightmare if your UI isn't highly componentized. I've seen projects where you make a button by copy pasting this ~80 character string of tailwind classes all over the place, and then changing the color names if you need to. Good luck fixing that when the designer decides that we don't want any buttons to have rounded corners anymore.
Personally I think the best parts of Tailwind are captured in Pollen[1], but I do wish it came with a subset of utility classes for colors, font sizes, margin, padding, and text alignment. I think the hard part is defining which subset is the right subset... I doubt you could find strong agreement from a large majority of developers on that.
>This works okay in extremely componentized web apps. It's a nightmare if your UI isn't highly componentized. I've seen projects where you make a button by copy pasting this ~80 character string of tailwind classes all over the place, and then changing the color names if you need to. Good luck fixing that when the designer decides that we don't want any buttons to have rounded corners anymore.
That app is done wrong. If you are using the same styles to represent a button you should use postcss and do
No, we don't want all of the buttons to look identical.
Some are big and some are small; some are bold and primary and some are muted and secondary; some have icons; some have shadows; some are disabled, etc, etc.
It's easy to make them identical. The challenge is to be as flexible as necessary in a mature application, while minimizing verbosity and complexity.
In my experience Tailwind hurts more than it helps here. It forces you to use your component system to abstract things which otherwise wouldn't warrant the extra level of indirection.
You should look more into design systems. It's not only for Figma files but can structure your whole frontend. To extend on the example above, you can do something like :
If you a 100 different types of buttons I can see your problem, if it is more like 5 then you just create them first and then makes the code more DRY.
For example when using React you can create 5 button components first and the refactor your code to make the 5 buttons use/call a generic button. Or have 2 generic buttons if the combinations are hard to handle. The thing with atomic CSS like Tailwind is that it very easy to quickly create a few different buttons.
How would you have done it without TailWind? You'd still have to create classes for each of them in plain css anyway, except it would probably be in a different .css file. The inherent complexity pertaining to your app is not taken away, it just moved the places.
to find all the elements that the .field.large declaration impacts we need to enumerate all the elements that have both .field and .large in any order.
Even then, I would still recommend using the postcss extend tag. Much easier to read that way. Also, postcss doesn't require any frameworks, you can still do everything with plain ol' html and javascript.
Yes, there is a right way to do it. But in the code I've seen in the wild, people are often not doing it right and those 80 char strings of utility classes are on the low side compared to some of what I've seen. I'm skeptical of Tailwind not for its own sake but because a lot of (most?) shops do not have the discipline to use it effectively. And what you are arguing here is basically a no true Scotsman defense.
Not at all. You design and iterate on the button using the individual classes, then you swap them out for a concise class once you are done. It's how tailwind is designed to be used.
postcss is literally how tailwind works. If you are using tailwind, you already have postcss. I get it, you don't like modern frameworks. Don't use it.
I agree. I used Tailwind for roughly six months on a few projects before I noticed that I was only using the basic utility classes. I didn't like all the screen sizes and state "bloat" classes so I decided to take the best parts (margins, padding, background, font, text alignment) and create a simple CSS framework.
I've been working with CSS for over twenty years, and Tailwind is the way forward for me. Some of the big benefits are:
* No more worrying about naming class selectors. This frees up so much cognitive space. The less you have to worry about naming the better. I used the SUIT CSS naming convention before, which allows a mix, and that just creates friction. You need the same level of abstraction all the way through.
* No more flipping between files. You edit your styles directly in the HTML. You will need to consult the TW docs, of course, but they're easy to navigate.
* Tailwind is more than just inline styles. It provides a nice syntax for targeting breakpoints and little utilities for conveying more abstract styles/stacking rules.
* TailwindUI is a great way to jumpstart a project and looks way better (IMO) than Bootstrap's components.
* JIT is awesome
I'd be remiss if I didn't mention some cons:
* Looking at a bunch of class names in your HTML is at overwhelming at first. It's hard to delineate the structure. Using proper HTML elements, roles, etc. helps.
* You will need to DRY up your repetitive styles by moving things to templates/components. So you still have to name things, but just keep it generic (alert, dropdown, badge, etc)
* Sometimes you'll have to create class selectors when working with web frameworks and JS libs that require a single class selector option.
I can just add that WindiCss is worth testing. In my small trials it worked a lot better than Tailwind with jit. Windi with Vite gives me a really fast dev experience.
I've been a Bootstrap user for a long time, but I recently made the jump to Tailwind. It's not the revolutionary upgrade I was hoping for, but it's nice evolutionary step in the right direction. It's quite intuitive, but it doesn't get rid of most of the frustrations that come from doing layouts, as those come from the design of CSS itself. `@apply` makes the upgrade worth it though, it's easy to make custom classes from the Tailwind elements.
The one thing I don't like is that the culture around Tailwind seems a lot more proprietary, like you're getting three quarters of a product that you need to buy the rest of, whereas Bootstrap felt like you got everything you could ever need for free.
If you're talking about Tailwind UI[1] — I use Tailwind extensively and have basically never looked at Tailwind UI. It's just useful snippets of HTML styled with Tailwind. It is by no means required to get value out of Tailwind.
I'm not sure what you mean by proprietary culture! Based on the fact that I've pretty much never seen anyone talk about it, I would guess (total guess, no real knowledge) that no more than 1% of Tailwind users have paid for Tailwind UI.
You have to do literally everything from scratch with Tailwind though, for example I never realised how much work is involved in a simple avatar dropdown / logout component (hidden full-screen button). Tailwind is much closer to raw CSS than Bootstrap. That's not a criticism, it's just a different value proposition.
My favorite thing about Tailwind is all the sites that offer copy-and-paste components, ready to use (since you already have all the CSS, you just copy HTML-and-classes and it looks exactly how you'd expect). Sure, you can pay for TailwindUI, but you can also just browse (free) components from e.g.
Most of the sites I put together this year used an amalgamation of components from those sites for basic structure, and then just get customized to the brand and site function. I hate writing raw CSS and I would also hate writing raw Tailwind.
That's what I mean, though. $250 for some styled HTML! I think that's crazy. Compare with Bootstrap, which has basically just as many snippets simply as part of the documentation.
I don't think it's crazy. It's a good business model for them and a way to monetize their work on Tailwind.
Spending $250 in order to get a well implemented and well designed HTML and CSS framework for your app sounds like money well spent to me, depending on the circumstance.
If you're an expert or pro at CSS, then yes, that's expensive. But if you have a little budget and need to make some quick progress on a new site, it's a great deal. Hiring someone who can recreate these designs and give you exactly what you want is probably going to cost more than $250.
I'm saying you don't need that and almost nobody uses it. There are tons of snippets in the Tailwind documentation. I just scrolled down the side nav and clicked a page at random:
Ok, I can see how if you're used to relying on the Bootstrap examples[1] you would experience the lack of such examples as a big hole in the TW docs. I guess I would argue that those examples don't go very far at all in a real-world application.
I paid the $250 and it's an incredible time saver for prototyping & making decent looking, fully responsive internal apps for clients. Based on the number of billable hours saved, it's paid for itself many many many times over.
It seems proprietary because there are ad links disguised as documentation links. You can't click "Components" anywhere on TailwindCSS.com or you'll end up on TailwindUI.com pricing page.
It's fine that they want to make money but it's very confusing for a new user. Ultimately, they might make more money by dropping the shady links if it's turning away enough new users.
I can maybe see how that could potentially be confusing to a brand new visitor, but how is it shady? It's a clearly labeled link that does take you to components made with tailwind. Are they supposed to link to all the freeware out there first?
Gotcha. Yeah, phrased like that, I can see your perspective better (and I even agree!). Maybe a little external site icon and moving that link to the end of the nav could clear that up.
Just started with tailwinds and similiar thoughts. A framework like this without components.
Try daisyui as a tailwinds plugin. It comes with the missing components. It also allows you to replace your 80 character style for buttons with btn btn-primary.
There is a dead sibling comment which I will repeat with a bit kinder words, and with a different caveat.
As a frontend developer I don’t like Tailwind for several reasons, it brings the styling into the structure. As a frontend developer Tailwind is at a forefront of what I would consider bad practice and encourages a code style which would be a nightmare for me to maintain.
That said. Tailwind seems to be loved be people who are not professional frontend developers. It seems to be just the right tool for people who are not necessarily proficient in CSS. And perhaps people like me (and the dead sibling) need to learn to let go and allow other people to have the tools which makes it easier for them to do the job which they are not experts at. For that reason I understand Tailwind, even though I don’t agree with it.
I think TWCSS' argument is that we always were bringing the styling into the structure.
Show me a site that has CSS Zen garden style replaceable stylesheets that totally overhaul the nature of the site. It's incredibly rare and almost always not worth the effort. What business says "I want to overhaul the styles of my application but change no structure at all. I'd posit it's near 0.
Even if that's your goal, and I'd argue that it shouldn't be, you can still do that with TWCSS and the @apply keyword. You can write your generalized names then apply whatever twcss keywords you want to them separate from your
document's structure.
If your overhaul amounts to changing a "theme" you can easily do that with twcss. In fact, that's basically the point.
I am a professional frontend developer and I love it.
I have said it many times, but I'll have a go at it again.
The reason why inline styles got it's bad reputation is mainly because we used to have no way of building reusable components.
Nowadays, everyone and their mothers are using some kind of frontend framework that allows you to reuse components, so your inline styles can be mentioned once and used everywhere. It's not a problem anymore.
Pair your tailwind with styled components and you can finally reach the dream of semantic HTML.
I like Tailwind because it brings styling into structure. Dealing with external CSS has always been really challenging for me, and I've always heretically used inline CSS.
I mean header files are OK, and professional C developers probably love them, but not having header files is kind of great too :)
I think your comment has a lot of merit. Personally Tailwind has been awesome but I think it's because it makes all these abstractions for you. It also forces less experienced developers to follow this abstraction rather than making their own, which usually ends up as a ball of spaghetti.
I have a similar comment elsewhere in the thread but it applies here too, I think: the main drawback of Tailwind is that it's extremely general. I'd imagine a well abstracted, focused, domain-specific set of CSS created by experienced frontend developers will be much better within that domain.
I am a professional frontend developer working on a large-scale react application and I love tailwind. I am proficient in CSS, but having colocated html (well, JSX) and css makes so much sense, and the design system really helps fast iteration while also keeping things looking nice.
do you prefer the structure in the styling or the styling in the structure?
i prefer the later. with styling in structure if i make a change in one place, it effects the one thing i intended it to
with structure in styling, if i change one thing, it may impact many other things, some of which i might not intend to and are sometimes unknowable at the time of the change
I usually do component scoped styles (e.g. shadow DOM, Vue’s SFC, React’s styled components, etc.) and the changes I do only affect the component where the changes occurred. So to answer your question, I like structure in styling, but with component scoped styles that structure can be pretty minimal.
If I change the structure I usually have to change the style anyway. And with component scoped styles, I know exactly where I need to do that (usually in the same file, or in a file referenced by the component).
As for shared styles I use the cascade which can penetrate the component boundaries, e.g. font-size, color, but usually --css-custom-properties.
> Be kind. Don't be snarky. Have curious conversation; don't cross-examine. Please don't fulminate. Please don't sneer, including at the rest of the community.
It’s not traditional css and you need to accept that if you want to work with it. It has a load of benefits in a different dimension to css, and personally I think they’re worth the trade off.
My main issue with it is the inability to control the order of precedence with the css rules. It’s mostly fine, but when you have runtime rules around, say, colouring text based on a few different variables, it turns into a bit of mess. Unfortunately because of the way it works there’s no way to implement “last rule wins” at runtime.
I use tailwind with Angular, and we solve this with using [ngClass] to add/remove the class. You could do something similar with plain JS as well, and I imagine in most frameworks. Although yes, that is annoying to have to deal with.
Say you’re balancing a bunch of colours where it’s say mostly black, but you need to change to green in some case and red in others.
In css this is easy because you can say “for this situation I want this colour”. And you can order your rules in a sensible way so the more specific cases trump the general ones.
In tailwind you can’t do that because “text-red text-black” etc is ordered by the order in which the utility classes are added to the page. So you have to make sure you don’t add two conflicting classes.
That case doesn’t seem so bad, but once you get a few different properties to control and a few different scenarios, it gets pretty messy.
As always when anything about Tailwind gets posted on HN… 200 comments so far and (almost) not a single one about the actual blog post.
Looking at the new features, I wondered why they went with a major version bump, but seems like it's because the Just-in-Time engine released in Mars as a feature flag is now the default engine, which is a pretty big change by itself.
I don't think this is a tailwind specific thing. I see this happen with almost every framework/language update. There's more people who know about a language than people who know the language. So it will obviously deviate more to them.
Tailwind always looks like a cool evolution of Tachyons [0] to me (with a build step). On the other hand, tachyons is really simple, you just drop it into your project with no build required (or drop the sass in), and I've never really felt like it was missing any features I wanted.
I wanted to love tachyons before Tailwind was a thing. I jumped to Tailwind as soon as it released because it was configurable. The tachyons way of changing the defaults, such as colours or breakpoints, last I checked years ago, was using search/replace or forking the repo and adding your changes. Eh, no thanks.
Tailwind is better in every way, and JIT is a killer feature.
> Tailwind is better in every way, and JIT is a killer feature.
I dunno, the smaller dev build from JIT is great, but it breaks my in-browser design workflow. Only the CSS styles needed are generated, so I can't make in-browser tweaks to see what a different padding/margin/other-property looks like.
I don't know that this solves their problem though. Even with the in-browser JIT, there is no class for the browser to autocomplete. One nice benefit of the old compiler, was every single class was available with autocomplete in devtools. Granted, if you already know the class you want to tweak and can guess the next correct step in the scale, it's fine, but for new code you're writing for the first time, I can see their argument.
For customizing it, we copy the sass files and replace variables for colors and breakpoints. It's not what you usually do with a dependency, but Tachyons is feature complete and has very few (read: human patchable) updates. It's an easy way to have a custom style-guide in sass within a few tweaks.
It's a pretty small and readable codebase, so while there's a downside that you can't upgrade it by incrementing a version, the upside is that you don't have an opaque upstream dependency and you can cut any fluff you don't need (though there isn't much).
Tailwind is more like an editorialized version of all the features available in "vanilla CSS" than it is a UI library. Tachyons is a small, tiny UI library that enforces (ugly) standard defaults.
Also, the naming of classes in Tailwind feels much more natural — the tachyons naming is condensed to the point of being abstruse.
I've had the feeling that Tachyons is a bit abandoned, no? The album component/example [0] has been showing 404 images for a while. The last release on GitHub is from 2018.
CSS frameworks don't ... need? to be state-of-the-art/updated all of the time (I get that), but at the same time, like anything else, once a component/css/etc. library falls behind, it (can) become harder to make it work with other tools.
i.e. it's hard to abandon the bandwagon of constant new releases, as the second that you do, "stuff" sometimes starts breaking. This is of course a very general observation that doesn't apply to everything.
Hey great question! I was wondering that as well!
They're both considered 'functional CSS' libraries.
I used Tachyons after spending 5 minutes trying to figure out the build process for Tailwind and Tachyons worked great for the single site I used it on.
For those wondering "but separation of concerns!" or "but code reuse!", the dev behind Tailwind wrote a post about his thinking around this, which IMO makes quite a lot of sense, a while back:
The problems he's tackling weren't problems, and his solutions are a bombardment of utility class names in your HTML, rendering it extremely and unnecessarily verbose. It makes the HTML less intuitive to read, too. A `<div class="user_profile">` is clearly a container for a user profile, a `<div class="here comes a shitload of tailwind class names because inline styles are now apparently cool again">` tells you absolutely nothing about what the hell is going on.
I fucking LOVE CSS and Tailwind is an insult to the craft.
Those who love Tailwind tend to not understand CSS beyond the basics, is what I've learned. Those who hate Tailwind know CSS inside and out.
To each their own, but this example from their own homepage makes me want to vomit:
Like what the actual flying fuck. This is inline CSS, period. And that's wrong, always. Tailwind makes me mad and angry because I love front-end development, I love CSS, and everything about this feels like a mentally challenged person spitting me in my face. Nothing I can do about it, they are challenged after all, but damnit it's annoying.
> A `<div class="user_profile">` is clearly a container for a user profile, a `<div class="here comes a shitload of tailwind class names because inline styles are now apparently cool again">` tells you absolutely nothing about what the hell is going on.
You know what's going on if you're in a component called user-profile.component.html
How often are you writing something like a user profile component in the context of something much larger? Also, what styles would the class "user_profile" even have? You say the second one "tells you nothing about what's going on," but I'd say it's the opposite. If you actually put real tailwind classes in the second one, I'd know exactly how that div is styled whereas the first one requires cross-referencing another file.
"user_profile" probably has CSS implementation that have almost nothing to do with a user profile. It's probably a container that has maybe a margin, a max-width? The important styling details all come from the inner HTML and stylings on those things. So your "user_profile" class is mostly just another generic wrapper that you had to come up with a name for.
This is less clean but has the same level of semantic detail in the HTML:
<div class="container"><h1 class="home-heading text-center">heading</h1><div class="m-10"><p class="home-body color-blue"><div class="first-name">bob</div> is a person</div></div>
Am I missing something?
I think people conflate semantic class names (read by programmers and maybe ad-hoc web scrapers) with semantic HTML (read by screen readers, SEO bots). Semantic HTML is HTML that uses the appropriate semantic HTML tags, but including wrapper divs and CSS class names on top of this doesn't make it less semantic to a machine.
For styling, when a utility class is all you need to style a particular tag and it's obvious from context what that tag is being used for, I don't see to reason to spend time trying to come up with a semantic name e.g. `home-hero-wrapper-inner`.
To me, this is people dogmatically sticking to a "best practice" without thinking about the pros/cons and reason behind it. This is also related to the pipedream that HTML is for data only with nothing about presentation and CSS should be able to style the HTML without you editing the HTML.
> This is also related to the pipedream that HTML is for data only with nothing about presentation and CSS should be able to style the HTML without you editing the HTML.
Which I also think is weird, because the hierarchy of HTML is inherently styling/presentation. If HTML was truly decoupled from styling, you'd just throw all the tags that you want into an HTML file and then arrange them around with CSS.
That's why when you're using child selectors in CSS (or the nesting in SCSS that's transpiled to child selectors), you're forced to keep two hierarchies in sync, which makes it a huge PITA to refactor.
> That's why when you're using child selectors in CSS (or the nesting in SCSS that's transpiled to child selectors), you're forced to keep two hierarchies in sync, which makes it a huge PITA to refactor.
Yep, trying to keep data and presentation separated like this comes with a lot of pain. Why bother? I don't see the practical benefits in real-life projects as long as you're still using semantic HTML tags.
There's this other pipedream that the HTML is generated/written by people that aren't concerned with the presentation and then the CSS can be swapped in to style it however you want. You can and should do this in a sense that you keep your data/articles/posts in Markdown, SQL databases, behind APIs etc. - I think trying to split this further at the HTML/CSS level isn't gaining anything.
I love Tailwind! It elegantly solves most pain points in writing CSS. However, it does this at the cost of readability, and you can easily end up with HTML that looks like this:
I moved to tailwind a month ago and it’s become incredibly easy to read and work with very quickly. It’s one of those frameworks that just clicks when people start using it, though I think a lot of people don’t feel that way until they put the time in to get familiar.
For Tailwind in particular, it’s easier to understand the benefit if you consider the three main problems it solves:
1. Naming things “semantically” is a giant pain. Sure “user-card” is easy enough, but when you have to start giving names to all the little bits of the user card it quickly becomes absurd. Yeah you can use child selectors and stuff to ease that a little but then you’re basically re-writing your HTML in CSS. Tailwind’s approach is to say “have a UserCard.{html,vue,js} component and move on”.
2. Most codebases have multiple people working on them, and those people are often not CSS experts. It is very common to end up with giant stylesheets that only grow with time, because people are too scared to ever remove or change things in case it breaks something seemingly unrelated. Utility frameworks (and other modern approaches like styled components) keep the styles directly attached to the HTML being styled. You can make any change you like, safe in the knowledge that you are only affecting the thing in front of you.
3. It pushes you into a design system. Sure this is achievable through Sass/CSS variables, but for Tailwind it’s right there with a sensible default out of the box, and easily configured if you need something different.
I think the important thing is, Tailwind doesn’t enable you to do anything you can’t do by writing well structured CSS, because ultimately it is just CSS. However, people aren’t perfect, and I believe that Tailwind does a genuinely good job of helping people avoid common footguns.
If your team is largely composed of CSS wizards who are fine to carry on as normal, that’s great, you probably won’t get much out of Tailwind. But for a lot of us, the price of remembering some (very consistent, to be fair) shorthand class names is well worth not wasting hours battling the cascade and suchlike.
For those that don't know, the laundry list of new stuff is probably all enabled by the first item in the list, just-in-time compilation. This means anything they can dream up can be included as a utility class, without bloating the compile time of the 99% of projects that will never use the feature (also without bloating the css package size, but that's not new since shaking out dead classes for prod has been a thing since forever).
Looks fantastic. My only concern using this in a full React project is its lack of interoperability with standard libraries. It seems like for the best experience, you either buy Tailwind UI to use with a tailwind project for anything except the most basic UIs, reimplement the Tailwind UI components yourself, or have a weird mix of css-in-js and Tailwind CSS. Although I love the idea of HTML-native inputs all the way through, I tend to immediately run into issues where using a native interface instead of a JS-based implementation harms the user experience.
Props to the team though - I feel like this is something I'll try out for a marketing site.
> Although I love the idea of HTML-native inputs all the way through, I tend to immediately run into issues where using a native interface instead of a JS-based implementation harms the user experience.
The way HTML forms (in particular, but also things like tables) are stuck in a not even good for the time '90s level of functionality is an under-appreciated drag on all web development, IMO. So very much wasted effort, wheel-reinvention, brokenness (a11y, especially) et c. for shit that should have been built-in years ago.
> The way HTML forms (in particular, but also things like tables) are stuck in a not even good for the time '90s level of functionality is an under-appreciated drag on all web development, IMO
It absolutely is, but things are changing! Come help us get better form widgets built into browsers at at https://open-ui.org/.
The website's a bit behind, the Discord and GitHub issues are where most discussion happens. We need people who know hte pain points to help us.
You may be interested in Chakra UI (https://chakra-ui.com), which has low-level details (including default theming) basically identical to Tailwind CSS v2 but is built around css-in-js via Emotion.
Shameless self-plug but if you'd like the same idea but that works with native as well and has an optimizing compiler that outputs clean CSS at build-time, try Tamagui (https://tamagui.dev).
I like Chakra...mostly. We have ran into some major performance issues with it all over our application though. The docs [1] make it sound like it's a rare issue, but we're not doing anything particularly wild and it became unusable at a point due to these issues. Now, we have a "no Chakra below this point" rule where certain parts of our application are not allows to use Chakra at all and use TailwindCSS + our own custom components instead.
You're right as it probably won't work well with MUI [0] (formerly React Material) and similar options like Ant [1]. But they all accept a theme provider that could hook in to the Tailwind config. Never tried it though.
But a swell of less opinionated offerings [2] [3] [4] (more and more the popular anyways) work well with Tailwind. In fact, when writing your own libs, exposing a className prop makes them painlessly customisable.
Thanks for these ideas! The react-aria seems quite interesting to develop a UI library library using Tailwind-styled elements while accounting for accessibility.
They do based on what I've seen, you're right. I'm speaking more to the consistency of styling across the project, but if the UI library is separated out from the rest of the project then it shouldn't actually be a concern to compose the components with tailwind-styled elements.
I've never used Tailwind CSS. I watched the video "Just-In-Time: The Next Generation of Tailwind CSS" and all of it seems like they're solving problems that are entirely of their own creation, and doing so in an impressively complex way.
The use case demonstrated was suppose you have a twitter button on your site, and it has to have a background color of #1da1f2 because that is Twitter's brand color. Instead of writing style="background-color: #1da1f2" like a normal person they have a class name called bg-[#1da1f2], and their "JIT compiler" generates a named class with that property.
In another part of the video, they use className="font-bold" instead of style="font-weight: bold". Apparently the advancement in this version is that instead of having all of those pre-defined classes they only generate the ones you actually use. The feature list for 3.0 includes the ability to use any color you want, and even arbitrary CSS properties that the framework doesn't explicitly know about.
Is this progress? I could use the style attribute in 1999.
You miss the point. Using the style attribute everywhere causes duplication; using css classes can quickly lead to bloat where you have lots of unused classes.
This is a way of paying only for what you actually use.
Assuming the content is gzipped when transferred (a good assumption), the non-Tailwind version's payload is smaller because there are no separate CSS definitions.
Your statement is true in the general sense (a page can easily load unused CSS with other CSS/styling approaches) but I don't think it's correct to say that using Tailwind results in smaller payloads vs. using style attributes.
Someone should make a compiler that converts inline styles to Tailwind so then you don't have to learn Tailwind but can still use Tailwind.
For example it can convert `<div style="background-color: white">` to `<div class="bg-white">`. Perfect! (Yes, "bg-white" is the Tailwind way to make the background color white.)
Yet again, inline css has no support for media-queries, pseudo elements, states(hover, visited, active). Tailwind does. Tailwind also works as a design system, limiting you to a predefined font-sizes, spacing, etc. generating a consistent look-and-feel that requires discipline to do with inline styles.
Alright. Now add a media query to change the button size based on the device size. Or maybe use a different color on hover. You can’t do that with inline styles.
Well using square brackets is kinda not preferred with Tailwind. You'd rather use something like `bg-blue-400`. And even from your example you see that you are writing less styles. I agree that going outside what Tailwind provides is kinda non-optimal but in general it provides nice building blocks that makes keeping the design consistent easier.
I was in the Tailwind is dumb camp also until I tried it. Then I realized I can ship my own prototypes faster because I wont waste time fine-tuning margins or picking colors. It isn't perfect of course but nice when speed is your top-priority.
Tailwind definitely solves a problem for me. I don’t like writing CSS, and Tailwind serves a (very) thin abstraction layer. I don’t have to worry about reusing CSS, figuring out how to name my classes, or what CSS selector I need.
I guess these features are helpful, but they’re hilarious to read. “Arbitrary color support” is a release note you’d see in the 90’s
The point of tailwind - well, one of them, anyways - is to provide sensible defaults. You then snap those sensible defaults together and have good looking UIs without a lot of effort. The square bracket notation is a fallback for rare cases when those defaults aren’t applicable.
By far Tailwind has been the fastest way for me to prototype UI.
I am a developer nerd and have a good taste for design. However, during actual development, I do not have the ability to visualize what I want in the first attempt.
So, I have to tweak the look and bring out the beauty I want through a 1000 cuts. TW makes that process extremely easy. Like, mindbogglingly easy.
However, I have learnt to be careful with my code, and I often limit the styles by splitting them off into sub-components.
It's more like a series of templates. You copy them into your project and customize them. I used them for a big project and found them to be absolutely fantastic. It's a lifetime license for unlimited projects - the time I saved was very quickly worth the cost.
Before you ask, as it happens in every Tailwind post, what is the point of this when CSS "promotes" reuse and separation of concerns, have a look at @
5e92cb50239222b comment: https://news.ycombinator.com/item?id=29501650
And let me repeat what every Tailwind fanboy (like me) states every time this project is on HN: don't knock it till you've tried it. Look at the animated example in the front page. You'll never be able to iterate that quickly with CSS.
What animated example? You mean the youtube video? I didn't see anything compelling in it over CSS. Stuff like "You can now style print media!". The only reason you wouldn't have been able to is because you were using tailwind. This new release is probably an improvement over tailwind v2, but I don't see any improvements over CSS.
It's true that I haven't tried it. And I probably wouldn't, at least until someone can formulate at least a hypothetical advantage.
Hmmm... as a non-tailwind user I just took a look.
Maybe this shows my age, but it kinda looks like an extension of <b></b> <i></i> - you know, that stuff that we moved away from a long time ago...
Isn't this losing the point of CSS - that our "content is separate from its styling"?
I know I know, we often have to adapt our HTML to allow the styling to work properly, but this is only really true for layouts, not for colors / padding / margin / fonts etc.
I understand that we now have people writing React apps and componentising everything, but if you litter your code with styles such as "font-semibold" and "font-sans", isn't that just going to mean you have a million places to change next time a designer decides to give your webapp a makeover?
> if you litter your code with styles such as "font-semibold" and "font-sans", isn't that just going to mean you have a million places to change
If, instead, you litter your code with my-brilliant-semantic-class you create a different kind of problem. Requirements change and my-brilliant-semantic-class won't be sufficient. Now the choice is; alter my-brilliant-semantic-class and suffer all of the unintended side effects or abandon reuse and make another-brilliant-semantic-class.
The likely choice is the latter and so applications become masses of ad-hoc, partially finished, inherently flawed styling abstractions scattered hither and yon among directories full of redundant styling artifacts, half of it long dead. How is that a benefit to some future re-designer?
> next time a designer decides to give your webapp a makeover?
I figure the odds of one approach vs the other being the greatest benefit to some future re-designer are about even, and my guess is as good as yours.
One underrated problem with semantic naming and classic CSS is having to repeatedly do one of the two hardest problems in computing, that is naming things, 5 times per minute while you're trying to be creative. You constantly have to context switch between "design/creativity" and "logic/pragmatism" mental modes. It's awful, exhausting and doesn't enable any state of flow. The productivity loss is enormous.
> "the curved sweet yellow food that grows on trees"
You have (some variety of) cavendish bananas in mind. There are red, pink and blue bananas. They're not all sweet. The plants they grow in are not always "trees" but rather large fern like plants.
And then that day arrives when you are required to style some variant of 'banana' you are forced to decide: do I break the world by messing with banana or do I make new-banana?
You can still call it a banana in Tailwind, but you'd do it with a component in your framework rather than a class name.
If you plan on using bananas multiple times throughout your app, aren't you going to be pulling that out into a component anyway? So define that it's curved and sweet and yellow in that one place, and then insert an instance of it wherever necessary.
In my experience the “one-off items” are far more common, simply because every one thing I do reuse will typically have several child elements. Why am I naming the styles that represent the title of a contact card if I never use it outside of the contact card—which itself is probably included by referencing a file called “ContactCard.html” or whathaveyou.
Of course, there’s no right or wrong answer here, and I suspect it very much depends on what type of web systems you are building. I feel the entire debate is basically a special case of the question “do you make websites or web apps”.
Any thoughts as to how Tailwind can handle dynamic plugins using Tailwind? Ie it seems Tailwind relies on tree shaking to produce sanely sized CSS. But if you have plugins which rely on Tailwind, you'd have to either ship the full sized Tailwind CSS or they'd have to duplicate CSS and ship with it.
So far with this plugin/extension design i've not found a way to use Tailwind and also retain nicely sized CSS.
> it seems Tailwind relies on tree shaking to produce sanely sized CSS
This 3.0 release has its biggest feature be JIT. If you read the linked blog post, CSS is no longer purged but generated dynamically by reading your source files and generating the TW classes you use. It's not tree shooken anymore
Appreciate the info! I'll have to figure out how the hell this works though lol, i watched the video and am still a bit perplexed, since i'm not using JavaScript. I'll be curious to see how i can hook into it
As far as I understand, the build system just scans for whatever Tailwind class names you use, and then generates them into CSS. Which is why you can't dynamically compose Tailwind class names and insert them into your markup, cause it wouldn't be picked up.
Whether or not you're using Javascript doesn't matter (I guess unless you use the new CDN script which I haven't tried), but it does need to be run in a build system.
If it just uses regex over source material i guess it would be fine, though seems like it might hit a fair number of false positives if it's too loose. Too rigid and it might not work if you don't write your css vars in something that looks html-like.
I've never looked into how accurate it is, but even if you get a few false positives, I'm not too concerned about a few extra characters being transferred in the grand scheme of things.
The creator of Tailwind posted a comment in this thread that the Tailwind website itself, which uses way more Tailwind classes than a normal size would use (for demoing everything), only spits out 36.9kB of CSS.
Some technical thoughts as someone who could care less about fanboyism:
- One point where atomic CSS frameworks are supposed to shine over conventional CSS is bundle size, since they (at least the good ones) compile to only a single rule for any used value, rather than potentially repeating rules for semantically different classes.
- Another point where atomic CSS frameworks shine is just sheer volume of banging code out. When the bulk of your output is visual, mastering tools based on shorthands like tailwind, emmet, etc can feel very productive.
- Purely atomic CSS frameworks can make some workflows more difficult, e.g. by having too granular call sites and not allowing "let's see what happens to the overall theme if I do this design change" iterative style of work, or because workflows that edit CSS on the fly via browser devtools can no longer be used to limit impact within semantic lines (e.g. "I want to change padding only on buttons, without breaking everything else that happens to depend on the same padding value"). There are both design-oriented and debugging-oriented workflows that are affected in similar ways.
- You generally don't get visual regressions at a distance w/ atomic CSS. This matters at organizations where desire for pixel precision and simultaneously fickle design teams are the norm. But conversely, "can we just change the font size to be a bit bigger across the site" can often run into issues of missed spots. On a similar note, designs may become inconsistent across a site over time due to the hyper local nature of atomic CSS oriented development.
- Custom rules may as well be written in APL[0]; they usually aren't documented and it takes a "you-gotta-know-them-to-know-them" sort of familiarity to be able to work with them (or get back to them after a while).
- There are some tools that mix and match atomic CSS with other paradigms. For example, styletron[1] can output atomic CSS for the bundling benefits, but looks like React styled components from a devexp perspective, and has rendering modes that output traditional-looking debug classes for chrome devtool oriented workflows.
The main theme to be aware of: proponents of atomic CSS rarely talk of maintenance, so beware of honeymoon effect. Detractors often omit that traditional CSS (especially at scale) also requires a lot of diligence to maintain. So think about maintenance and how AOP[2] vs hyperlocal development workflows interact with your organization's design culture.
As much fondness as I have for the pure separation-of-concerns CSS Zen Garden style, I have to admit I've yet to actually see it leveraged on a real project. In 20 years of working on the Web. I'm not sure I've ever seen a significant re-working of CSS to re-theme a site without also changing the markup substantially.
In practice, maybe coupling the two doesn't actually do much harm, provided consistency of approach is maintained and it doesn't go quite as far as inlining CSS all over the place.
If you have a hammer... I am able to iterate orders of magnitude faster in Adobe Photoshop. Back and forth feedback with the customer and then the end result gets coded in non-spaghetti reusable, themeable HTML/CSS. Seems you're iterating at the wrong phase.
Depends. I’ve never used Tailwind, so I’ll entertain your aside. If you are mostly doing flat design, truthfully you should be designing in HTML/CSS/JS. This is a failure of setting expectations for designers. If you can get developers to learn Leetcode, get designers to code their designs.
Design in the browser with browser technology, it’s just boxes, gradients and shadows for industrial level web design at the moment. You really shouldn’t even be designing in a tool like Photoshop or Figma given the current design paradigms.
You will not iterate faster than what I am suggesting.
Edit:
The reason why we are here, why something like Tailwind and MUI exist, is mostly because we need an abstraction layer to do what a designer does on a whim. You can flick a shadow on and off on a Photoshop layer and mess with the subtlety of a drop shadow with a slider. If a designer makes a fickle change, the developer needs this abstraction to make the fickle change as fickle as the thought that made it. That’s why you have all these quick utility methods. The designer is one layer (no pun intended) removed.
In 2021 (2022 really), it’s shocking the amount of latitude we give designers to still not be able to do CSS. A half competent designer could have a modest style sheet that mostly captures their design instincts, yet here we are, unable to capture their whims and must now have an albatross utility library to have manual laborers capture the translation - all because … they still won’t learn basic shit.
And for what ultimately? These aren’t baroque art pieces, it is ultimately boxes with an aesthetic applied, all very describable with semantic HTML and CSS. But alas, our brilliant artists can’t be bothered. Here, send me your masterpiece so I can transform it for you.
Take the bootcamp on web dev. You are literally the people I want going there. Not the Classics major that needs money because they picked a stupid major. It’s you guys that need it, and deserve it.
> Design in the browser with browser technology, it’s just boxes, gradients and shadows for industrial level web design at the moment. You really shouldn’t even be designing in a tool like Photoshop or Figma given the current design paradigms.
This is why all but the very best flat designs (which does not always correlate positively with the size or reputation of the firm turning them out—looking at you, Google) look to me like something I'd have turned out for a quick feature demo circa '05, with everyone at the table agreeing that, however nice the feature, a designer definitely needed to take a pass at it before it was released.
Perhaps. But hard coded colors, hard coded layout (flexbox etc), hard coded margins, paddings hard coded everything right in the markup. Tailwind and those adjectives are mutually exclusive.
Does nobody remember themeing forums software like vbulletin? Designers weren't allowed to touch the markup in the slightest and yet so many amazing themes were made. Why? Styling wasn't hard-coded in the markup. Hell, remember the insanely customized old.reddit subreddits?
All of the things you mention, including colours, are configurable or at least overridable at compile time. It's just not swapping a CSS file like the good ol' days.
Ironically, I had the opposite opinion on clicking the link to the blog.
Sure, a Galaxy Fold is a pretty niche user device, but its genuinely the worst first impression of a mobile website I've ever seen, with everything weirdly scaled to sit in a narrow portion of my screen (other dimensions linked to px values on the video embeds maybe?). Had to load the link a few times to confirm I hadn't just accidentally zoomed out, since if I do zoom in it looks like a normal mobile stylesheet
https://pasteboard.co/V0Cy3etIngpY.jpg
We've been using Tailwind for over a year now. We use it with Angular for our web application and with Gatsbyjs/React for our production website. I have nothing but love for Tailwind.
Tailwind feels like the correct abstraction on-top-of css which works for 90% of use-cases.
I struggled with css for many years but Tailwind has actually helped me improve my css - when I'm forced to write plain old css, my mental model of how everything works is much better. The fact that Tailwind has become so popular is a smell that css is slightly too low-level for most developers.
Every time Tailwind does something great and gets posted here, the conversation devolves into the same arguments: “I don’t get it. It’s just inline styles.”
What is it about CSS that gets people so offended and opinionated? If it were a new JS framework, few people would be saying “I just don’t get XYZ. Use React”. Is it because Tailwind is so drastically different and breaks people’s core ideas about separation of concerns? Maybe it’s because we all learned CSS very early and were told to do it XYZ and now challenging that is painful.
If you honestly want to “get” Tailwind, go use it in a project. If you don’t like it, don’t use it. Nobody is going to change your mind in a comment and you’ll never convince anyone to stop using it.
Idk. CSS is what I least care about. It’s a thing. I use it to do a thing. And I move on. I used SASS. Now I don’t.
When you first hear Tailwind's concepts, they seem to contradict everything you know about good software design. When you try it out and begin to remember some of the class names, you get into a great state of flow - it's the high developers are always chasing.
I can't help but feel that Tailwind detractors have never actually tried Tailwind or are too square to give it a chance.
regarding 'contraditing everything you know about good design' i feel this way about designing webpages using <table> elements. the constraint really forces you to be creative with using image elements to make everything fit on the page just right. styling with tables used to be popular, but then it went out of fashion, unfortunately. i'd like to see it make a comeback. i'm not being sarcastic either.
It was "popular", because there was no good option to do stuff. Now there are plenty options. Tables are for tabular content. Using it anywhere else is a spit in the face of accessibility.
i think we too easily fall for the heuristic of separate files == separate concerns
but your concerns arent really separate if, while in their separate files, they are concerned about the same things
and, so long as you want relative styling, they always will be. you can either (1) attach properties to your tree or (2) flatten your tree into a list of paths and attach properties to nodes that match the paths
in (1), changing the structure can only impact an individual node or it's children, only by the properties attached to the node and it's parents; changing the style can also only impact an individual node or its children
in (2), changing structure can impact the individual node, it's children, siblings or parents by any rules that now match any of the mentioned nodes; changing style will impact all matching nodes (not all of whom can be identified statically) and their children and may interact with other rules which apply properties to matching nodes.
either way, you cant escape the structure of the tree and one strategy lets you scope your changes easily, the other does not.
For me, the situation is: I gave tailwind a try. I hated it. I spent a lot of effort of ripping every last tailwind class out of my project.
And yet, a lot of people swear by it and think its great. This really confuses me, and I'd kind of like to understand: how can other people like this thing that I think is terrible?
> how can other people like this thing that I think is terrible
Cause it works for them? You cannot be the arbiter of what other people like or don't
I hate CSS and I find the TW classes being right there with the HTML more helpful than class-hunting through a bunch of CSS files. React solves that somewhat with styled components now. I like having design guidelines set loosely about things rather than writing reams of CSS myself. I like having media queries defined right there in the HTML. I LOVE the flexibility it offers me and how quickly I can iterate through concepts and styles
Well, obviously it works for them and they like it, I just don't understand why.
I'll agree with having the styling information with the HTML. But there are lots of ways of doing that such as svelte-style components, CSS-in-JS, or inline css. Tailwind really didn't seem to have useful design guidelines to me. Since the classes seem to mostly correspond 1:1 with css properties, I didn't seem to be saving writing styling information. The media queries are something you can't do in inline css, but you can do it with css-in-js or svelte components.
> You cannot be the arbiter of what other people like or don't
That's not necessarily what the GP said. The charitable reading is that they're genuinely, open-mindedly, asking what they're missing that's so great about it, so they too might get to love it.
Yeah, it flies in the face of conventional wisdom and I think that bothers a lot of people. It’d be like if a new JS library came out that said you should make every variable a global.
Since I learned to write semantic class names, and to compose using scss or react components, Tailwind feels like it would be a big step back. I get that it would be kind of nice to prototype in, but is anybody here using it for complex apps or UIs?
From reading the previous threads, large projects are where it (apparently) really shines. Personally I didn't find it useful at all, but obviously YMMV.
I work on a large Next.js project that has at least 100 custom made components all using Tailwind CSS. It is, without a doubt, the best way to iterate and make changes. I will never go back to manual stylesheets. Having a separate CSS stylesheet feels like context switching and breaks the flow of development in my opinion.
Super bizarre - I've found the opposite. I really like Tailwinds, it's great for getting up and running quickly if you're a one-person-team but as our team's grown, readability becomes quite a big issue (it's just not as clear as pure CSS/SCSS I find)
If you're using components, then it works great. The css is local to each component, and you only have to make changes in a single place. I'm just doing a fairly simple app, but I can see it scaling well to larger projects.
Funnily, I've experienced something of the same, but inverted. I was all in on semantic class names for years, then moved over to Tailwind for a few work projects and couple of years.
Now I'm back working on a project with a team that is staunchly against TW and I'm having a hell of time getting back into the rhythm of naming things. Everything just kinda looks like a box so I'm having to go back to the the designer or team to pull out names for things.
Definitely looking forward to when I can go back to using Tailwind at work and on personal stuff. The cognitive overhead is real.
I took a stab at using Tailwind a while back but I'm embarrassed to admit it didn't make much sense to me as someone with only the most basic CSS skills. And for some reason CSS to me has been something really hard to get any kind of foothold in and I've always ended up just resorting to big UI component libraries like Bootstrap. Any recommendations on skilling up in CSS for your average back end dev? Manning's "CSS In Depth" maybe https://www.manning.com/books/css-in-depth
I've always been a bit apprehensive of Tailwind but with the latest JIT compiler it actually seems usable. I'm happy to see it getting more use for mainstream applications but I wish it wasn't the "default" for a lot of open source projects.
For example, several of the next.js examples[1] use tailwind without explicitly stating so, because I guess it's just become a ubiquitous as css stylesheets or modules for some people. The problem I find is that it adds opinion and mental overhead for people learning related technologies or trying to get a head start without an opinionated styling solution. In order to use something like the blog-starter example for next.js I have to go and learn tailwind and then come back before I can use their blog starter, where as CSS is universal. CSS works with every project, without depending on Tailwind.
Anyway, looking forward to seeing newer improvements to Tailwind, but I hope that people will consider it an alternative to something like Bootstrap instead of an alternative to CSS.
> For example, several of the next.js examples[1] use tailwind without explicitly stating so, because I guess it's just become a ubiquitous as css stylesheets or modules for some people
I used Bootstrap for years and give MDO major props. I learned Tailwindcss actually because it was starting to show up everywhere and many of the Next.js examples were using it. Now that I have used it I would say it changes how you think about css and styling - it gives you more power and more guardrails and it also then ships a smaller css load to the client. It was always a struggle to carve away the parts of Bootstrap you weren't using.
I'm sure it's very nice to use (I've been learning it in the past week), and I think it's a great alternative to Bootstrap. Personally, I'm not fully sold on it as a 100% alternative to styling with css (not least because you can't do pseudo element styling and have to add another node to the DOM). As someone who knows CSS, when I look at a template which uses tailwind I get overwhelmed because I have to mentally process what the 20 classes per node do in combination, where as I can look at a CSS module and (usually) instantly understand what's going on. Sure, once you've done a few tutorials and installed the VSCode extension you'll be able to find out what they do, but the code becomes almost unreadable for people not familiar with Tailwind.
I used to use Zurb Foundation or Bootstrap for my personal projects but I found these two frameworks required me to use their javascript and their JS does not play nice always. So I moved to Bulma and that has served me well so far. I like not having to worry about CSS (it drives me nuts) and I would like to just focus on building components and functionality.
Kind-of. People usually pick one or the other, but they're not alternatives in the same sense as Bulma vs. Bootstrap vs. Zurb Foundation.
Bulma has opinions about structure and style, and its value proposition is providing out-of-the-box components so you can skip spending brain cycles on that design work. At a high level, Bulma believes projects reuse a lot of design patterns, and those shouldn't have to be rethought each time you need them.
Tailwind doesn't care what you want your project to look like, or how it's structured. Tailwind's value proposition is streamlining you choosing your own design, and removing footguns from that process. At a high level, Tailwind believes cookie-cutter styles are typically less reusable than you hope, that you should instead optimize for tailoring design patterns to each place they're used, and that style reuse is better implemented by e.g., React components than a CSS framework.
From reading the blog post, it looks like they took most of the things that were experimental or first class plugins and graduated then into being native.
If you would decide or have to use Vue for a complex project today, would you use Tailwind with Vue? If yes, why? If no, why not? Would your answer and rationale change in cases, when you decide or have to use a Web application framework like Nuxt or a UI component library like Vuetify and PrimeVue?
I love Tailwind but now with these updates I'm like "ok whatever". Information overload.
There is a point where there are so many utilities; it's just not reasonable to ask me to remember them... and at that point where I can't keep them in my mind, then the "framework" loses some of its appeal and benefits.
Of course I suppose it's up to the user to decide what they want to remember, and it is the nature of the framework to become exhaustive.
I don't really have an answer to this. Only that it further reinforces how TW is a tool, among others, and as it becomes more and more complex it can no longer become a "holy grail" sort of approach precisely because you lose the benefits of having "rails".
I have a subset of my more commonly-used classes memorized, and for everything else it has a fantastic docs site that I keep a tab of while working, which also got overhauled with v3.0
I really like Tailwind, and was excited to use it for a new application at our company. However, I find the lack of standard component classes (modal, card, button, wherever) pretty limiting.
This makes it difficult to have open source Tailwind components that can be imported and themed differently for your apps.
Even after buying Tailwind UI, they are basically just code samples that we'd have to copy into our own libraries and maintain.
Again it's a really cool library, but feel the approach is probably better for smaller apps and teams.
Daisy UI might help with this, but seems pretty small at the moment. https://daisyui.com/
Arbitrary Properties (inline styles) can now use constraints (css vars), media queries, and hover/focus states, the reasons Tailwind said you should use their utility classes instead of inline styles in the first place :)
I don't have the energy to explain to the naysayers why I love tailwind so much but I do have the energy to log back into HN just to comment that I absolutely love tailwind. Give it a try and maybe it'll stick!
If anyone is interested I just updated a bunch of my example Docker apps to use TailwindCSS v3. That includes examples for Flask, Django, Phoenix, Rails, Node and Play.
It took longer to rebuild the Docker images than making the v2 to v3 Tailwind specific changes. In my case it came down to deleting and renaming a single property in my Tailwind config file.
I finally got into Tailwind a few months ago after originally HATING the paradigm shift, but it's started to grow on me -- especially since most of the modern "material design" CSS libraries are starting to show their age and Tailwind fills a similar throw-together-something-beautiful-fast niche.
This comes at particularly nice timing with Rails 7 releasing at the end of the month. I can't wait to pair the two and see how well the new features of each work together.
I am the one who always has had issues with TailwindCSS. But now I know why. It's not because it's polluting HTML. It's because I am not one of those, who can whip up some cute buttons on the fly. I have no idea how to apply padding, chose fonts, colors or combine shadows. I'm better off with CSS frameworks which provide me with these things out of the box. TailwindCSS ir just a method for rapid designing, which I am totally incapable of.
Having used it pre-release, the JIT compiler is really incredible. It makes Tailwind a sea-change when compared to Bootstrap and the other, similar, CSS toolkits.
I want something like this which includes a few ExtJS-like grid (as in data table) and treelist classes for "enterprise" CRUD want-to-be-spreadsheets-when-they-grow-up apps. (point being, everything in a single toolkit)
So much of enterprise IT is little more than glorified form fill-in, and yet so few CSS/JS libraries solidly cover these use cases.
Coming from someone who mostly does platform / service work and usually avoids "the frontend", tailwind helped me to actually understand CSS, it made sense to me and has saved me a lot of time. The site I built looked professional very quickly and without much effort.
Thank you to the team and I look forward to using it more in the future.
Really happy to see this before the end of the year. The JIT improvements and comprehensive arbitrary value support will no doubt come in handy for quick one-off projects or bespoke landing pages.
I'm happy they have also expounded upon some of the more common FAQs on the homepage, including the extraction to components.
I like the idea of tailwind, I’ve dealt with raw css and bootstrap before but I’m certainly no frontend developer.
How can I learn tailwind enough to become proficient? Most of the documentation I looked at seemed to lack any tutorial on how to locate the correct classes I need, or any other sharp edges that might exist,
My process of learning Tailwind involved nothing but going to https://tailwindcss.com/docs, pressing Ctrl+K to bring up the search, and typing the class I'd use in "regular" CSS. Their search is great at picking these up.
Agreed. My team is doing this very process. If we run into not knowing what class to use, we just look it up on the docs. VSCode also has a great intellisense plugin for tailwind as well (https://marketplace.visualstudio.com/items?itemName=bradlc.v...). For the first day or two we used the docs pretty heavily. Now, we just make a best guess, intellisense generally tells us what the class name actually is, and if we can't figure it out then we go to the docs.
I tried Tailwind not long ago and really liked it, but setting it up with Create React App seemed a bit of a hassle as I couldn't do it without replacing the build, run, and watch scripts with something else I'd forgot the name of.
lol Its funny how this thread just turned into a review of tailwind.
IMO Tailwind is awesome (and cant wait to try out v3). It took me a second to warm up to it but now it makes so much sense.
You deal with a lot of minutia writing your own classes and since css is designed to be put in classes, it looks ugly when you add it to elements.
Minifying the styles into structured classes makes life so much easier. Once you map out like 5% of the lingo, you can instantly play with it like lego blocks.
I literally get the same feeling I had when I was first messing around with frontend. That feeling of power/possibilities/excitement when you can tweak a few words and shit changes on the screen.
Last time I tried the jit or purge mode, some classes were missing randomly each build and broke my site. (I followed their purge rules very carefully).
The worst thing is it ONLY happens on the production build.
I like Tailwind CSS and I really hope they make it stable.
Great! but the docs are on the offensive side:
- "Yes, send me all your stupid updates"
- "The new print modifier lets you style how your site should look when animals(in strikethrough) people print it."
Because by definition offensive has to do with how people receive something. I love the library, will continue using and donate, I would prefer the docs not to assume that people that print papers are animals. That's all! Take it or leave it.
i read that as sarcasm delivering a subtle critique on digital consumption in 2021 and how print has been killed by digital media (for most folks). obviously they acknowledge that people still want to read in print, otherwise, why would they bother to add this feature?
maybe i'm reading into it too much, but i don't think they think print readers are inferior.
I wonder what the future of code-splitting with Tailwind will be. With JIT and a large web app, it's easy to ship a massive CSS file even if 90% of the rules are unused on 90% of the pages.
Tailwind author here! Do you have an example of a site using the new engine that is shipping a massive CSS file where most of the styles are unused on most pages?
The Tailwind website is only 36.9kB of CSS and it likely includes more classes than any other Tailwind site on the internet by virtue of the fact that it has to provide visual demos for so many of the classes. I don't think 36.9kB is massive personally, it's much smaller than the CSS of almost every website I've checked.
I find it funny whenever Tailwind people tout that you "don't have to name things." You still have to name your JS-framework-of-choice components, and you still have names for each of the parts of a single component that get smattered with class names; it's just that the name is implicit in your head now instead of explicit in the CSS
If you're thinking of TailwindUI, that's a separate product that's just a bunch of premade components built with Tailwind. You don't have to pay anything if you're just using Tailwind to write CSS, which is all I want it for.
It's just regexes basically. All languages should be supported. If something that looks like a tailwind class is found, it'll add it to the list of ones it'll generate.
congrats to the team, they’ve been moving at a solid pace while keeping the quality high. funny that this also continues to be one of the most controversial topics on HN
Not OP, but I'm not worried about saving how many characters I type. We have autocomplete that fixes much of that problem anyways. I'm more worries about being able to read things others have written or even my own code when I come back to it. I tried Tailwind, and get the praise, but I still find it takes more time to read and understand than CSS. It just seems cluttered, and I couldn't get over that.
My experience (and the experience of thousands of others) is that in practice, an approach like Tailwind is much more maintainable, even if it's superficially ugly.
At the end of the day it's a lot easier to understand what's happening in a template where you can see all of the styles directly attached to each node instead of having to map things together in your head across multiple files.
For example, for me at least I can't believe how much more difficult it is to look at your average CodePen demo and understand what is doing what at a glance vs. looking at a Tailwind template. With traditional CSS there is just _so_ much indirection in comparison.
With no disrespect to anyone, I think it'd be useful if people bashing Tailwind would briefly list what their day to day programming consists of.
My impression is that most of the negative comments are coming from people that don't code for Web often (I could be wrong). To those folks: I'm not saying you don't know your stuff or that you argue badly - since I was on that side myself a few months back.
What I am saying is that the elegance and pragmatism of Tailwind might not be easy to intuit just by reading about it. Try to implement a simple landing page using Tailwind+TailwindUI and see if any lightbulbs gets lit.
I've been a web dev for about 10 years. My day to day now involves building out React-based applications dealing with both the backend and frontend. I put in the work and built a real side project using Tailwind and it was so annoying.
When you write anything substantial you end up with class name soup. The answer to this is to use `@apply` which is literally just a normal CSS class with extra steps.
The new vernacular just means that users have to learn Tailwind language rather than proper CSS.
CSS modules solve the main problems that Tailwind attempts to solve. The other things are solved with use of CSS variables.
The only thing that I find useful in Tailwind is the responsive design classes. Being able to do `md:<some other style here>` is pretty cool.
To me, Tailwind seems valuable to newer engineers because they feel like they don't have to learn CSS. They learn "Tailwind." It's like all those people who would say "I don't know JavaScript, I know jQuery." Like jQuery, there are benefits in having a unified language especially when you're newer. I believe that a better solution to styling is inevitable (my latest favorite heavily uses CSS variables). I do not believe Tailwind is the best way forward.
Sure. Frontend development, mostly on a single React-based project, for which we receive mockups from a dedicated designer. Using CSS modules, with SCSS (not sure we even needed the SCSS; we do sometimes use its nesting and ampersands; but I think we could have just as well written vanilla CSS syntax).
Other times, I would write web components with lit. With shadow dom, web components would have their own little bits of CSS, which provides sufficient amount of encapsulation that neither CSS modules nor SCSS are really necessary.
I don't have any problems with importing CSS from (S)CSS files or writing it inside of a LitElement-based web component. I don't have any problem with writing CSS by hand either. I find it strange that people would want to learn another domain-specific language for CSS, in addition to the CSS itself and DOM's camel-cased style dialect.
With the regular way, to style something that's probably not going to appear elsewhere, I'm having to: come up with class names, annotate the HTML with them, repeat some of this annotating in a CSS file, jump back and forth between files to tweak the styles, use the web inspector to figure out which CSS class is overriding another then jump to the right CSS file to fix it etc.
Tailwind classes are also faster to type and flip between when you're experimenting (e.g. editing "mt-5" to "pb-3" vs "margin-top: 4.25em" to "padding-bottom: 2.75em") and you get less distracted because it has sensible defaults and helpful guardrails (you rarely need all the possible attributes and range of parameter values CSS has available).
I also rarely had the super irritating and common CSS scenario where you edit a style and it doesn't change and you have to go investigate to find out why e.g. something is overriding something, your selector is wrong, and even after all that maybe you undo the edit because it doesn't look good. Plus you no longer have the fear that tweaking a shared class to going to break some completely different page.
I feel that beyond some building blocks, trying to create reusable CSS classes with cascading styles has similarities to using excessive abstraction and deep OOP class hierarchies in regular programming languages to avoid a little duplication.
I also don't have a problem with styling stuff appearing in my HTML files either as long as the right HTML tags are used around the data. HTML files are already full of class annotations and divs that are only there for styling yet this doesn't cause a problem to e.g. browsers, screen readers or crawlers.