Hacker News new | past | comments | ask | show | jobs | submit login
TailwindCSS v2.0 (tailwindcss.com)
927 points by sarathyweb on Nov 18, 2020 | hide | past | favorite | 463 comments



Tailwind is the most counterintuitive yet obvious-in-hindsight CSS tool (or of any class - no pun intended) I've worked with.

I know the general sentiment towards Tailwind is "I spent years getting my separation of concerns with HTML/CSS down, but now you're telling me all that is backwards and CSS Zen Garden is blasphemy?" I was in the same boat. Tailwind just felt wrong, and with 15+ years of experience, I've come to trust my intuition. After watching several videos, and reading all the canonical articles on Tailwind, I still wasn't convinced this was anything more than a fad full of bad practices.

But the one thing I'll let trump my intuition is curiosity. So I used Tailwind on a medium-sized project for a couple months and was blown away by the productivity and maintainability. It took using it for a couple weeks to "get it". I had a positive ROI on this project, even considering the learning curve!

If you still think "Tailwind feels wrong, what am I missing?" I'd suggest reflecting on the following:

1) You probably haven't actually delved into Tailwind on a non-trivial project. I understand learning a new framework isn't a trivial undertaking, but it's the only thing standing in your way of discovering your "truth".

2) If you feel Tailwind is too much like inline styles, think of the difference between the infinite possibilities of strings defining a "type" vs. a discrete enum type. Tailwind classes are the enum type values.

3) If you're struggling to abstract reusable higher-level classes/components, the problem might actually be with inconsistent and non-modular design, not CSS tooling. If every page or section is a "unique work of art" then you may have poor UX/design.


> You probably haven't actually delved into Tailwind on a non-trivial project.

This is precisely where Tailwind breaks down IMO. It's fast for landing pages and smaller sites--but when implementing a real design system across a complex web app, Tailwind is a nightmare. We've had to add so much custom stuff to the config file it's basically the same mess our CSS was before.

I've been-there-done-that with the whole CSS framework world (have used Bootstrap, Tachyons, Bulma, Tailwind in many projects) and have completely reverted back to custom stylesheets with a few select utility classes that make sense.

Padding, margins, widths, heights do not make sense as utility classes IMO.

Type scales, type modifiers (like font-weight), and commonly used things like margin-x-auto and 100% width do.

I wish there was a CSS framework that only contained a minimal set of common utilities (like the ones mentioned above) and required no complex build process BS or NPM.

I just want a simple boilerplate, nothing else.


You're doing something wrong then. I'm using tailwind on an absolutely massive project and I have 4 lines of CSS.

What you need to do is heavily use the `extends` property of your tailwind.config.js so it applies the paddings and margins you seek to ALL properties.


It sounds like you're fighting Tailwind instead of working with it. Are your designers aware of the presets and design with them in mind?

I'm curious what you're adding to your custom config to make it so bloated? I've been using Tailwind on a number of sites, big and small, and have yet to run into any situations like you've described.


It's not like Tailwind is SAP or something. It's just CSS. You shouldn't need to re-work your entire process around it.

The custom stuff in our config was mostly the need to create standard styles for components. Eg. button large, button small, etc. to correspond with our design system.

For example, here's tailwind code required to create a button large: bg-violet-100 text-violet-700 text-base font-semibold px-6 py-2 rounded-lg

How the hell does that help with consistency? You have to copy paste that mess every time you create a new button, and then guess what happens if the button you copied from needed special margin? Try debugging that if something looks wrong. Also try turning that into dark mode.

Now you've got to search through the spaghetti to find what's custom about this button and fix it every time.

You know what's easier? Creating a ".btn-lg" style to fit our design system, and just typing .btn-lg each time. It also has the bonus of making your code actually readable.

Maybe this is solved with the groups functionality in the latest tailwind, but this is just one of the frustrations I eventually developed.


> It's not like Tailwind is SAP or something. It's just CSS. You shouldn't need to re-work your entire process around it.

No, your designers should already be working to scales for size, colour etc. which you can implement in Tailwind. If they don't, now's a good time to start.

> How the hell does that help with consistency? You have to copy paste that mess every time you create a new button

You're extremely not supposed to copy-paste that. You're supposed to extract it somehow, either with your Javascript component framework, or by making a semantic class with the @apply directive.

https://tailwindcss.com/docs/extracting-components

The difference is that Tailwind allows you do some quick work without coming up with abstractions. So you work bottom up instead of top down.

> then guess what happens if the button you copied from needed special margin?

That's the beauty of it! You have a button class, and then if your button needs "a little extra" you add the button class and the margin utility.

At my previous job, when this situation came up, the normal way was to make a BEM class specific to the location, import the button in that (with a SCSS mix-in) and add the margin. So the HTML would have a class name that was specific to this one button, but you didn't know what it added: class="info-page__navigation__button". With Tailwind, you get 'class="btn mx-2"' and you can basically see what it's going to look like.


> with your JavaScript component framework

If I’m using React components, tailwind makes even less sense.

I’ve already separated my button large out as a component, guess what happens in a mature design system? The system gets updated and changed to fit the needs of the product.

So what happens when you need to change button large in tailwind? You need to restyle the button with the spaghetti mess (maybe add something to the config), then re-extract the mess into a tailwind component. Now you’ve got components within components just to emulate the abilities CSS has right out of the box.

Guess what you could have done? Just had a .btn-lg class in an old school style sheet where you updated to the new font weight and padding and you’re done!

There is no need for this layer of complexity and abstraction of CSS. CSS is literally the easiest thing in the entire stack. Why do you want to make it so complicated?

Rube Goldberg machines are extremely elegant in their beauty, but they are not the most efficient way to get something done.


I'm guessing you haven't actually used it. It's a fantastic fit for React or similar frameworks. There's honestly nothing spaghetti messy or Goldbergian about it. It's just generating a stylesheet.

I absolutely do have a .btn class in my Tailwind projects, that's a given. For consistency, it's built from the utility classes that Tailwind provides, but buttons are kind of a pathological case in many ways, they're really not how you should evaluate a framework. When I put two buttons next to each other, I don't make a new class for one of the to get some spacing, I just slap a "ml-4" on one of them, and that matches all my other spacings.

But the real magic is when I'm building up my mid-level components, I don't have to try to come up with names or abstractions for the CSS, I just make things look and work right, and as I notice patterns I can break them out into semantic classes as needed. It's a great way to work and the results have been good for me.

In my mind, the real mess is a bunch of poorly named CSS classes that end up being specific to the place where they're used. Specificity battles, 40 character BEM selectors, mismatched margins sizes and randomized colour palettes. Setting up a Tailwind configuration is a very ergonomic way of turning your basic design system into CSS.


In regards to you needing to change your button when the design system needs to change I think you may be thinking about how to apply your current naming conventions or methodology as something like sass for instance what you could do is create the default button component and anything that you think you may need to change about that button you have props with defaults already set this way if you have one button requirements you just include it in the prop of that button, if you need to change all of them then you update the default prop.

In other wards instead of doing <button class=“btn-lg><button/> you're doing <Button {...specs}/>.


CSS is difficult. First start with content. Then add semantic markup. Only add classes if you really need to. Try to avoid div and span.


You're meant to use it with some other mechanism for code reuse, say React components.


The point of react components is to centralize all instances of something for consistency and easy updates.

This is also what CSS does for you natively. Tailwind is a beautiful, elegant, and ultimately unnecessary layer of complication.

It feels powerful and fast to beginners, and then you go through a design system overhaul with it, and start wishing you had just used bootstrap style class names and avoided the whole mess.


If you are using Tailwind then your designers need to be aware of its presets and be designing with them in mind.

When it comes to code reuse, either extract the button to a component that you reuse, or extract it to a class in tailwind.

   .btn { @apply px-4 py-2 rounded } 
Now you can just add the btn class and you’re done. If you ever want to change that button you can just update it and be done. If you want a button with different padding add btn px-8 and you’re done.

If you’re using components then you just create the button in a single place and reuse it. If you have custom requirements for the button then you override it.

It’s really quite simple and easy to do everything you’re describing. I’d read the docs and watch some videos on it and start working with it instead of against it.

Or don’t use it at all, makes no difference to me!


On the surface Tailwind seems quite great and whenever I stumble upon it I like the idea of good defaults, but since I don't use React or a component-based UI framework I'd mostly work with Tailwind's @apply directive, I assume, and at that point I wonder why I shouldn't simply stick to

    .btn { padding: 4rem 2rem; border-radius: 2rem; }
rather than

    .btn { @apply px-4 py-2 rounded }


It simply feels like an additional, unnecessary layer and, frankly, somewhat wrong.


>How the hell does that help with consistency? You have to >copy paste that mess every time you create a new button, and then guess what happens if the button you copied from needed special margin? Try debugging that if something looks wrong. Also try turning that into dark mode.

Agree with that. Wish the custom theme mechanism becomes mature enough like React components.

Until then the best bet i found was to use our own styles along with tailwind class names


As with all compositional programming, refactor your classes at the point of generation. So you most certainly do have a “large button” concept in your code, as a function/helper/method/partial/template/component.

Otherwise you’re just fighting against the framework.


> "Padding, margins, widths, heights do not make sense as utility classes IMO."

Why not? They usually benefit from having consistency in the design and that's where utility classes work best.



I love everything about this product page, pro tips, choice quote from the Author & its Amazing Idea generator is genius!


This looks promising!


For the minimal CSS framework, I've been a fan of Tachyons on past projects https://tachyons.io/


I did like how you can use Tachyons as a raw stylesheet without complicating your build process.

However, tachyons is even worse than Tailwind in that it offers far too few classes for margins, padding, widths, etc. so you end up having to build everything custom anyways.

And you can't just "try" one of these frameworks once or twice, you have to memorize their particular syntax or you lose all of the benefits of using them. After spending hours learning tachyons syntax and googling about 17,000 times, I had forgotten the tailwind way. And when I went back to tailwind I had to google every time I wanted to add a style again.

Ultimately, CSS frameworks don't save you time unless you pick 1, customize it to your needs, and do front-end stuff full-time so you don't forget the syntax.


This is low key what makes frontend hard for those that claim fullstack proficiency. Just because you hooked up that UI once upon of time doesn’t mean you still remember or have the muscle memory to do so quickly again later. Or if we put you at a new company or team.


We have two design systems at Draftbit that utilize tailwind and it’s great.

We use what they give us, it works.


In which cases do margin and padding not make sense as utility styles? I’ve only needed custom values a handful of times, but I’m not using it on a complex app


Hey, check out https://piccalil.li/cube-css/, but more specifically the stack used for the picalilli website itself (check the footer): https://github.com/hankchizljaw/gorko and https://utopia.fyi


What I do is extract spacing, colors, fonts and other standardiz-able elements in SCSS maps and use them in standard css BEM class definition.

As in

color: c(cool-gray-800); background-color: c(cool-gray-100); font-family: ff(sans-serif); padding: s(m);

Where c, s and ff are SCSS functions returning a value defined in scss maps.

If you find the tailwind definitions useful, they’re easy to borrow.


I'm working on something like this which is close to 1.0. I'd love your feedback: https://cavepaint.github.io/cavepaintcss/


Frankly it sounds like you would have nothing but complaints about any CSS framework.


I am definitely missing something. What I don't get: if tailwind provides all the preprocessor parts, why do people need to put the class definitions as part of the HTML?

I would completely get behind tailwind if it was only the SASS part. Give me a bunch of mixins and consistent variable naming, which I could just `@import` into a sass file where I get the definitions for UI elements, widgets, etc... the whole "Design system" if that is the word kids use these days.

All of that can (and should if you actually paid attention at the CSS Zen Garden) stay outside of the HTML. So why when I go to any introduction to Tailwind it still shows all that <div class="size-foo color-blah rounded-baz"> code, I get major WTFs on my head and then I just go back to my simple SASS-based workflow.

What I'd like to see in the next generation of CSS frameworks would be for it to be able to take a completely classless HTML document (like CSS Zen Garden, modernized to HTML5?) and have it look like 3 or 4 different design systems without touching the HTML. Or for extra points, take a web application like webapp (web version of winamp) and show how you can make completely different skins just be redefining the base types and the color palette.


The answer to your question is the actual confusion regarding "separation of concerns" in HTML and CSS. You can do what you've described with Tailwind: check out @apply. But now you still have the issue of coming up with CSS class names. Because CSS on its own doesn't do anything. There is a high dependency between HTML and CSS and it'a up to you to choose the dependency direction. HTML and CSS are not concerns, they're technologies. Components are a better way for separating concerns. That's why CSS-in-JS is so popular and why we're combining pseudo-HTML and JavaScript in React.


> But now you still have the issue of coming up with CSS class names.

Not entirely true. I'd be totally fine with class names that identify what type of widget it is. <div class="card">, <div class="modal"> <button class="secondary-action">, or <span class="clipboard-copy"> are "made up CSS class names" that identify a type of widget and used without making no assumption about presentation concern. <button class="btn btn-small"> and <div class="w-12 rounded-small"> are not.

And yes, I understand that tailwind allows you to create types and @apply them. What I am saying is that (1) I'd like to see this separation to be enforced and not just possible and (2) plain SASS also lets you do that already. so I don't understand what I would gain from adding tailwind.

> Components are a better way for separating concerns

Except when they aren't. Downthread I gave the example of a library project that I want to define the functionality/behavior but leave the looks/styling to the consumer.

Desktop GUIs have theme engines for ages, yet frontend web developers want to get excited about frameworks that allow for "night mode"? "Night mode" is just a way to say "you can separate presentation and content however you want, as long you only present in two different styles".


With your example lower down, what you're describing is entirely possible both with tailwind[1] (depending how you provide your config), and CSS-in-JS toolkits like emotion. These are called themes and they're normally handled with writing a provider that needs to be included higher up in the chain, your CSS function then includes this parent configuration as an argument.[2][3]

You can only change so much of the styling without changing markup.

https://tailwindcss.com/docs/theme [1]

https://material-ui.com/customization/theming [2]

https://emotion.sh/docs/theming [3]


Yes, I understand it is possible. What I am saying though is that if we design things with separation of concerns from the start, this would never be a problem in the first place.

> You can only change so much of the styling without changing markup.

I take that you are not old enough to remember the CSS Zen Garden?

Even with craptastic CSS2 implementations of IE7 and no browsers that could fully pass the ACID3 test, the Zen Garden showed how anything could be changed without touching markup.

Don't tell me that it's harder in 2020 because it is a whole lot easier.


I think you might be looking at tailwind the wrong way here.

Tailwind does “enforce” separation of concern between styling and content, just in a different way than the separation of html and css.

Consider the utility class m-1 and m-2. What they are supposed to say is that element with m-1 class and element with m-2 class should have different margin, with the m-2 element probably have a slightly bigger one, and every element that uses m-2 class should have the same margin. It doesn’t specify styling at all. The concerns of styling are completely separated into the theming system.

All that the utility class define is the relation between elements. Eg. which elements should have the same margin/color/typography etc... This would also provides consistency in your designs, unlike pure css which allows you to do whatever you want without defining structure and relationships between elements.

I would say tailwind forces you to separate styling concerns out of your content and into your theme. You could probably replicate css zen garden using tailwind theming system.


If you tell me that there is a way to make all the utility classes completely private and available only for composing styles that can then be @apply'd to your CSS code, I'd not only agree with you but I would preach it as the One True Framework and Adam would be my Pope.

But if you are saying that you have different "utility" classes to specify different margins, and if these classes end up in your HTML, you already have styling/presentation definitions that should never be the concern of the document writer.


I no longer think of myself as a "document writer", and there honestly would not be room in my team for someone who only wanted to touch the HTML and not the CSS or vice versa.

I was there for the Zen Garden, and it was great at the time and in its context (Flash and image maps!), but now I'm using the web stack for a 3D editing application, and my last job was complex GUI for managing large number of IoT devices. The idea of separating "the content" from "the presentation" does not apply anymore. It's just not a thing. Good software engineering is super important, more-so than ever I'd say, but keeping some parts of the UI in the .css files and some of it in the .ts files does not equal adequate "separation of concerns" in my context. It's just not that simple anymore, and in fact in the previous job it was an impediment, since UI refactors became much harder because of the state of the .css files. In my new project, which was moved over from Bootstrap shortly after I started, Tailwind has made sure that many of the old problems just don't arise anymore.


> Good software engineering is super important, more-so than ever I'd say,

This smells of complexity to-justify-my-paycheck thinking about software. Css and html go well as seperate documents which makes things like theming and maintenance work but not frustrating. Why do we need the tooling overhead if the gains are marginal? SCSS gave css the powers it needed to be flexible but Tailwind sounds like classic cool-kiddery just like react.


I was here for all the discussions about how React went against the idea of mixing html and js, but once I started using it and grokking how that wasn't really the case, I found React to be so much more pleasant than what had come before. I mean, I still avoid it if I can, but that's not React's fault.

The fact that most front-end frameworks implement some kind of React-ish approach should at the very least make you wonder if dismissing it as 'cool-kiddery' is perhaps a bit too broad a swipe.

With Tailwind, at first I had similar concerns. I used it a bit and it seemed okay, but went back to the good old fashioned way of doing things. Then, in a later project, I decided to give it a proper shot and it measurably increases my productivity, reduces complexity, and reading articles about why it's not 'separation of concerns' (in many cases) convinced me I had no real basis for being against it other than being a curmudgeonly old-skool guy.

It's totally fair to stick with what works for you, but perhaps dismissing both React and Tailwind as 'cool-kiddery' is more a 'stuck in your ways and insecure enough to need to justify it' kind of thing than it is a reasonable perspective. Sometimes new things /are/ better!


The tool overhead of Tailwind is extremely small. I don't use SCSS anymore though, I thought it was too complicated for what it brought, and I didn't like the way it encourages nesting.

React etc. are extremely nice if you're making complex applications for the web. Of course it can be overused, but I'd say that some kind of SPA framework (and state management framework) is a requirement for the work that I do.


The point is not separating people, much less about separating files. It's about separating concerns to allow extensibility of one aspect of the component without having to worry about the other parts of the system.

Yes, with vue it is nice to have <template>, <script> and <style> on the same file, but what if I'd like to have multiple styles? Why can't I say "This component has this structure and this behavior and it allows for style A, B, and C" and have the application bundler choose themselves what style they want to use? What if the application bundler thinks "I want to use style C, but I'd like to customize some rules"? How do you do that?

> moved over from Bootstrap shortly after I started, Tailwind has made sure that many of the old problems just don't arise anymore.

Yes, Tailwind is a step up compared to Bootstrap if you consider how you can define the types and remove the utility classes from your HTML. But my feeling is that people who are so fascinated by the idea of Tailwind custom types are just in the process of reinventing semantic styling, this time with a preprocessor to compensate for the verbosity and some helpful mixins to overcome inconsistencies between browser implementations.

So, to repeat the question: What am missing? What do I have to gain from Tailwind if I am using already SASS as the preprocessor and a good library of "utility classes" that can be @imported/@use'd/@apply'd to the document without touching the HTML?


> It's about separating concerns to allow extensibility of one aspect of the component without having to worry about the other parts of the system.

Right, and I don't see the HTML and the CSS as separate concerns when the HTML describes a GUI, not a document. There being two languages in play is a historical detail that as developers we have to tackle in the best way. I don't believe that it's some sort of holy spirit we have to respect.

For my money, separation of concerns is things like where do I put my mutable state, which part of the application talks to the network, etc.

> but what if I'd like to have multiple styles

I have to say that's not a thing I've ever needed to worry about. I'm worried about things turning into a big pile of goop. The old approach too often devolved into making a separate class for each tag. Starting with repetition and noticing patterns that then get factored out is a better approach for me.

I will say, though, that in Tailwind it absolutely would be workable to give e.g. colours a semantic name - like primary and secondary - and then map those to whatever you want, including CSS custom properties. So you absolutely can implement both build-time and runtime theming at that level if you want, where you just need to change configuration options or a set of properties.

> What do I have to gain from Tailwind if I am using already SASS as the preprocessor and a good library of "utility classes" that can be @imported/@use'd/@apply'd to the document without touching the HTML?

Again, I'm not afraid of touching the HTML, that's not a goal for me. In my work, any change of any consequence is going to involve both HTML, CSS, and JS anyway. I am much more afraid of accumulating cruft in poorly-maintained CSS files.

Tailwind's utility classes are pretty fantastic - for instance, you can define a colour palette and they also become usable in gradients - so they're a good place to start. I also like that it's basically real CSS because that forces developers to learn, which will lead to better layouts. And yes, it will in some cases lead to the same set of classes as a semantic approach, because sometimes that classes are what makes sense. But the thing is, how do you arrive at that set of classes, and what do you do with the edges and boundaries and all the glue you need. Tailwind provides an extremely usable starting point and a good thought pattern for building the type of apps I do.


> Right, and I don't see the HTML and the CSS as separate concerns when the HTML describes a GUI, not a document.

You know that you can create themes in GTK (a Desktop GUI) using CSS nowadays, right? Whether a document or a GUI, behavior (how it works) and presentation (how it looks) are still separate concerns.

> (Multiple styles)'s not a thing I've ever needed to worry about.

Yeah, others have though - both as consumers and as integrators. If you are okay with the idea of re-inventing wheels every time you want to have a different color, plenty of people are not.

> I'm not afraid of touching the HTML

It's not a matter of being afraid to touch HTML. It's a matter of not being able to! Whether in terms of ability (some marketing person that is putting together a wordpress or Shopify store and can only go with different artifacts provided to them) or from the nature of the source code (e.g, imagine you want to make a RSS/Atom feed reader, embed a Tweet on your site with a custom styling or use an OSM tile editor), if you are not able to touch the code but you can select different styles, then it is fundamental that the data is separated from the style definition.

You might not think that this is important for you to do your job, but I think that is extremely short-sighted. What made the web as interesting as an application platform was the idea that the user agent could be extended. It is in our interests as users to keep the web open and able to be tinkered with, and the easier it is to separate the layers that people want to improve, the better.


> You know that you can create themes in GTK (a Desktop GUI) using CSS nowadays, right?

Does GTK offer CSS layouts? Do I describe the elements of the UI using HTML? As far as I know they just use a subset of CSS - aren't the selectors predefined by the framework? I don't recall, exactly. But GTK provides an entirely different set of primitives, I don't think it's the same problem at all if you're just providing fonts and colours. Again, I'm talking about something rather specific, creating complex, desktop-like user interfaces using HTML and SPA frameworks.

> behavior (how it works) and presentation (how it looks) are still separate concerns.

Yeah, but I wouldn't say that that distinction maps to the distinction between CSS and HTML at all, not in my context. HTML, especially document structure, is also presentational. That's really what I mean when I say it's not a "document".

And any way, no matter which approach (and platform, I'd wager) you use, if you want to completely restyle a complex GUI application like what I'm writing in the way you could restyle HTML documents like the Zen garden, you're looking at some serious engineering effort in keeping the so-called behavioural HTML and Javascript in check and documented. It won't just be about how you handle the CSS, it'll be about how you handle everything.

> Yeah, others have though - both as consumers and as integrators. If you are okay with the idea of re-inventing wheels every time you want to have a different color, plenty of people are not.

I actually feel like I have better control of my colours with Tailwind than I ever did. Currently I'm using a limited selection specified in the Tailwind theme. They have names like $adjective-$colour, so it'd be weird to change them, but if that's important to you that things are themable, as I stated, you can put in the effort to set it up with semantic names and make them customizable at build time or at run time. I still think you'd have a better experience than making separate classes for every tag and reimplementing that for each theme.

> It's not a matter of being afraid to touch HTML. It's a matter of not being able to! ...

And all of these things you list are not what I do. The examples that you list have a different set of trade-offs. I'm not embedding other people's code in my GUI, and I don't expect them to take a random chunk of my application and put them into theirs. OpenDoc was a fun idea, but it didn't take off.

> What made the web as interesting as an application platform was the idea that the user agent could be extended.

I don't really know about that in the general case, I think there are more reasons than that, but in the specific case I'm certain it's wrong. The reason my company is doing what it's doing on the web is 100% about distribution. Arguably, the web stack isn't even that good for making the kind of UIs I do - but if we did what we're doing in Java, we wouldn't get any users (or investors).

I totally agree with you about openness, but openness in my space means providing good APIs and integrations with other services, not allowing user stylesheets. A user stylesheet for my app would mean a twenty page list of weirdly interdependent CSS selectors, and the end result for someone who implemented it would be something like a colour theme that only works for app. Explain to me who would want that.


>Except when they aren't. Downthread I gave the example of a library project that I want to define the functionality/behavior but leave the looks/styling to the consumer.

Sounds a lot like an edge case. Most consumer applications do not need theming.


Most desktop applications also don't need them, or just use the standard style defined by the OS toolkit.

My larger point is that when you are developing a web app, it would be much easier if the framework was designed in a way that separated the concerns of presentation and behavior of the components.

Just to use Vue as it is what I am using now and had to get a bit more familiar: you have libraries like Vue Bootstrap and Vuetify (for Material Design) which have a lot of duplicate functionality yet are not compatible with one another.

If the concerns were separated, you could have components that have a common behavior and only differ in the visuals. Less work for everyone involved, easier for developers to get started, less unnecessary fragmentation and the possibility of positive feedback cycle between different design systems.


> And yes, I understand that tailwind allows you to create types and @apply them.

After (a short) twitter discussion with Adam Wathan about this, my impression is that his idea is to basically never use @apply, and instead create micro-components to encapsulate your basic styles. So instead of <div class="modal"> you create a component modal, and then you can put all the utility classes in its html, and still be able to quickly change it if needed.


That is interesting. But what do you/does him mean by "create a mini-component"? Are we talking about a React component, a Vue one, none of that?


They mean a normal component in React, Vue, Angular, or whatever other front-end technology you are already working with. I think they’re calling it a “micro-component” just to emphasize that there is no logic in the component beyond the templating.


Ok. So it is basically that going full-on "CSS dictates HTML" approach, which only makes (some) sense if you have full-control of every aspect of the stack and you just want to have a single repository for your design system.

Honestly, the only possible place where this may make sense to me is if you have tooling that can keep a two-say sync between designer tools and programmers tools. I think AirBnB was doing something like that with Sketch?

Aside from that, honestly I am still failing to see any benefit. If you are tying yourself to a JS codebase, you can still do that whole "utility classes at the component level" with plain SASS and global variables and mixins and you still don't need to put class definitions in your HTML.

Let me see if I can draft a quick Vue example:

   <template>
     <button><slot></slot></button>
   </template>

   <script>
     export default {
       name: "my-button"
    }
   </script>

   <style lang="scss">
   @use "my/sass/variables"
   @use "my/sass/mixins/buttons"

   button {
     @include buttons.rounded($variables.radius-button-small)
     @include buttons.colors($active: $variables.primary, $background: $variables.primary-accent, $disabled: $variables.disabled)
   }
   </style>

No Tailwind required. Easy to customize. One central place to organize your style and - most importantly to me - no css classes shoved in the HTML!

Now, someone might ask for "a large button inside the hero section from the home page." Let's go about that...

  <template>
  <div class="hero">
    <p>Welcome to the beautiful site</p>
    <MyButton>Sign up now!</MyButton>
  </div>
  </template>

  <script>
  import MyButton from './my-button.js'

  export default {
    name: "hero",
    components: {MyButton}
  }
  </script>

  <style scoped lang="scss">
  @use "my/sass/variables"

  div.hero {
    button {
      width: $variables.size-button-large-width;
      height: $variables.size-button-large-height;
    }
  }
  </style>
Really, I am yet to understand what I am missing by taking this approach. The example above is contrived, but I don't see why more complex widgets and even whole pages couldn't be done this way. The mixins are the place where you can have all of the abstraction you want, you can even add some logic depending on the values from the variables.

So, let's take a look at the benefits:

- If next week the frontend team decides to switch from Vue to anything else, the SASS code does not need to be touched at all.

- If next week the design team brings a whole new "Design Language", the JS code does not need to be touched at all (unless of course the design system also brings new functionality)

- The styling could even be verified on a series of static HTML pages. If the designer does not do any code, they can verify if the implementation matches the designs by opening a reference template, no need to run a whole JS app.

Downsides:

- If you want the code to be truly portable, your SASS need to follow a standard convention of @mixin names/parameters as well as variables. Honestly though this IS what I would expect from a "CSS framework", so I am not even sure it's a bad thing.

- You don't get to put any hip CSS-in-JS framework on your resume.


IMHO main issue is that you suffer from the same problem that killed jQuery. By separating html and the logic affecting that html (css in this case, and event handlers for jQuery), you might make it look cleaner, but you also make it much harder to track what is affecting what. You need to scroll up and down to follow what's going on, you might miss that there's say 3 buttons with this class you defined and not just 2, etc. And as the complexity grows, it gets exponentially harder to manage it and it quickly can turn into a mess. Components help keeping the html short, so this approach is certainly working better than with the old monolith pages, but it's still more work to have single .button and then look up its styles, then to have all the utility classes directly on it.

Also on bigger project you're almost guaranteed to have someone on the team who will insist on naming their classes in totally unintuitive way, or you'll end up with .big-blue-button that will at some moment end up red actually because they've been in hurry and forgot to rename the class.

One of the biggest benefits from using the frameworks is the standardization and uniformity, you're guaranteed that everyone on the team now or anytime in the future will know exactly what classes/mixins/variables are available and will have a documentation on how to use them. You need extra people to meet the deadline, you just hire devs who know the framework and you're good to go, no extra onboarding needed to explain where the buttons variables are located, and where to apply which, and how to name their classes, etc.


Respectfully, I disagree about the comparison with jQuery.

On the technical grounds, you are right that the biggest thing against jQuery was that it operated on the global context and that made large codebases messy, and that CSS alone might lead to a similar experience.

But I am not talking about CSS, I am talking about having an organized SASS framework, which can provide the utility classes (mixins) and which then your code would be organized by "base elements/components/pages" along with variable definitions.

The approach I am using and suggesting does require a certain discipline. It will also require that the whole team conforms to the idea that no class should represent presentation directives. But in my view this discipline not only would be beneficial in the long term, the separation of concerns would improve the chances of making reusable components and design systems that are easier to improve on its own, separate from the specifics of each underlying website/webapp that tries to adopt it.


i think what you're missing is how good removing a layer of abstraction /feels/ when putting things together. it didn't quite click for me until i built something with it. it ends up being a question of "where the work is done" i think, and the work being done within a string in your component just melts away layers of friction


>HTML and CSS are not concerns, they're technologies. Components are a better way for separating concerns.

This is the clearest concise explanation of this I've seen, thank you.

That you frequently have to add <div>s in your HTML in order to get CSS to lay stuff out correctly is enough evidence for me. :)


I gather you haven't used much of display:grid?

I'm trying not to make this too much of a dogmatic discussion, but is the cultural norm among developers going to be to just throw their hands in the air and say "styling is hard, let's go shopping for divs"?

On the one hand, I get that most people nowadays see HTML and CSS as object code, and is not that important to be abstraction that people think in. However, current web application frameworks can not solve problems that desktop GUIs frameworks have already solved in the 90s and no one is asking themselves "is this really the way to go forward?"


> I'm trying not to make this too much of a dogmatic discussion, but is the cultural norm among developers going to be to just throw their hands in the air and say "styling is hard, let's go shopping for divs"?

The experiment failed though, we've been trying for over a decade. You can't let one group write the HTML and one group write the CSS (with the pipedream being the designers writing the CSS). The only way to make complex designs is to modify both as you develop. They're too intertwined and CSS alone isn't powerful enough to do everything you want.

Keep your actual data like blog post content, blog post meta data, images etc. separated but it's 1) not practically possible and 2) there's no significant benefits to keeping your CSS and HTML separate besides sticking to dogmatism "best practices" that haven't panned out.


Honestly, I don't buy it. It might be the case if you are trying to target IE9, but "we've been trying it over a decade" is no longer an excuse in 2020 when there are only 2-3 relevant browser engines and all of them are reasonably up to spec.

Also, it's not a matter of strictly separating the groups of people doing one task or another. It's a matter of being able to extend in one dimension while keeping the other untouched.

> They're too intertwined and CSS alone isn't powerful enough to do everything you want.

I'd argue that is precisely backwards. The reason that we don't see any more different designs and more bold experiments is because we are not defining the interaction points between different layers in the development stack.

If most developers keep this mentality that all they need to do is to get a system that solves their immediate problems and solves their own unique solution, then all they are going to do is this mushing together of their structure and their presentation layers, and all we are going to get is a pile architectures are going to converge to different local maxima. If instead we don't take the easy way out and make things with flexibility and extensibility in mind, then the likelihood of it becoming the basis of something ground-breaking grows enormously.


> Honestly, I don't buy it. It might be the case if you are trying to target IE9, but "we've been trying it over a decade" is no longer an excuse in 2020 when there are only 2-3 relevant browser engines and all of them are reasonably up to spec.

> Also, it's not a matter of strictly separating the groups of people doing one task or another. It's a matter of being able to extend in one dimension while keeping the other untouched.

Have you worked on a website with a complex web design? If you know how to do this where you write the HTML with only semantic markup tags then don't touch it again while you style it with CSS, you're breaking new ground because nobody has figured out how to do this.

That's why Tailwind, Tachyons, Bootstrap etc. exist and continue to evolve - nobody has figured out the best way to do things yet. The MVC style you can do in other languages just isn't practical with standard HTML and CSS and it's not through lack of people trying. CSS has rapidly been improving the last few years but we're still a long way away from being able to avoid e.g. adding a wrapper div or shuffling HTML around to solve CSS issues.

> all they are going to do is this mushing together of their structure and their presentation layers

I think the issue here is you think HTML is for structure only and CSS is for presentation only, when the practical reality is HTML is mostly part of the presentation layer as well because CSS alone isn't powerful + practical enough.

Large websites already store their page titles, page content etc. in a structured CMS database. What tangible benefit are you getting by pushing to separate structure and presentation more than this?

For non-web apps, how is structure and presentation split up more than this and how does it differ from web apps?


> If you know how to do this where you write the HTML with only semantic markup tags then don't touch it again while you style it with CSS.

No, I said that I style it with SCSS.

I can give you all the utility classes you want - in the form of mixins. Then all your site styling and components can be defined in terms of these mixins.

I said that I am not against Tailwind in general. What I don't understand about it is the idea of having already all the mixins and utility classes and then letting people stick those in the HTML.

> What tangible benefit are you getting by pushing to separate structure and presentation more than this?

Go take a look at the template sites like ThemeForest and CreativeTim. Some of the templates look actually quite nice and could be an excellent starting point for a project. What they all have in common is that you have 5 JS technologies and maybe 3-4 different styles and they sell each permutation of these as a separate "bundle".

Then you actually download the thing and start working with it. You find out that some older versions will use Bootstrap 3, some will use Bootstrap 4. Some of them have their widget implemented with an outdated jquery plugin, but the rest is with React/Vue. And then you realize why no one makes big projects out of these things, because it requires an all-or-nothing approach when it is not necessary.

In my fantasy land, we get javascript UI component libraries that are standardized and a separate set of SCSS implementation of "design languages". So when I am writing an app and I want to have, say, an autocomplete that looks like Material Design, I can import only one widget and one "theme", instead of hoping that some React/Vue/Angular/Nuxt/Svelte/JS_FRAMEWORK_DU_JOUR has already implemented components following the style of Material/Bootstrap/God-Knows-what-Design-Language-is-fashionable-today.


> All of that can (and should if you actually paid attention at the CSS Zen Garden) stay outside of the HTML.

Yes, I've paid lot of attention to CSS Zen Garden. No, I don't think it should stay out of HTML.

You don't have to like it, it doesn't have to fit the way you like to work. But don't try to paint it as if people who prefer having utility classes inside HTML are just somehow not familiar with idea that they should be kept out. That's been the default view for the past 15-20 years, you know?


HTML and CSS are inseparable. Or at least, CSS can't do anything without the proper references in HTML anyway.

And you're likely using IDs and classes already to target, so instead of typing the name in HTML and the styles in a stylesheet, why not just condense into typing the style as a class name in the HTML?

This carries you pretty far while you can still customize as necessary. I do skip tailwinds when I'm not working in a component framework since I can type less verbose CSS, or if there's a complex situation that needs more control.


> why not just condense into typing the style as a class name in the HTML?

Because the style may change, but the underlying data won't. I know that nowadays everyone default architecture is to have data coming from some json API and that will have to be processed and rendered in the client anyway - but it is not just because something is the common case that it is the only case.

By looking at the discussions, I am starting to realize that most of the people that are okay with mixing HTML and CSS have only to work with one application to be worried about. If that is the case, then yes, it gets obvious why people want to treat everything as object code.

Consider different scenarios, though. Think of how many APIs could've been avoided if we actually looked and said "HTML is data content and structure, and CSS is presentation, so why can't the HTML be the API? The microformats people have been clamoring for this for decades already, yet no one listens. How much fragmentation could be reduced if we had half-dozen frontend developers saying "we are going to build a JS component library that is strictly about behavior so that anyone can style however they want with CSS"? All of those man-hours wasted reinventing wheels just because there is an unnecessary coupling between component structure and styling, penny wise and pound foolish.

It's almost as if companies don't want to have their data easily accessible outside of their own sites and if developers actually want to spend their time reconfiguring databases and creating ever-growing Rube Goldberg machines for their own fun and profit...


> "Because the style may change, but the underlying data won't."

What's the difference? It's the same typing, whether you create styles in CSS or just class names in the HTML. Designing the first time vs changing it later is the action.

The rest of your comment seems to be ranting other issues. CSS can't be split, that's the point. It's been tried often but it just doesnt work in reality and is part of HTML which also covers presentation concerns.

I don't see what JSON APIs have to do with this. It's not the most common case but it does actually mean you have an API to use without the presentation if you really want it, so isn't that exactly what you're asking for?


Let's make this discussion a bit more concrete.

Take a look at https://news.ycombinator.com/item?id=25155424 and tell me where the CSS is inseparable from the HTML? Or where would one have to change the HTML structure if the designer decides to change the styling of the component/page?

I am genuinely curious to get some feedback about it. I'm working on this project where I am dealing now with frontend stuff and I do want (need) to make it as easy as possible for others to integrate with their systems. If there is anything wrong with my approach I'd be very pleased to find out earlier than later.


When pages get complicated, you're going to start having issues in targeting these elements unless you only ever have exactly 1 single design for each element, no matter where it is.

What happens if you want a different styled buttons? What happens if you put <button> inside different tags or different order? What happens if you need to change a single <button> specifically?

The complexity of cascading rules and specificity and HTML structure is what makes the reality so different than this ideal. But if you can really keep everything flat with simple modifier classes, then that's exactly what Tailwinds already does for you.


> you're going to start having issues in targeting these elements unless you only ever have exactly 1 single design for each element, no matter where it is.

My example shows precisely how untrue that is. The buttons got different styles without having to change anything in the html structure.

> What happens if you put <button> inside different tags?

Then you define the corresponding rule. With SASS that is almost too easy. Also, don't forget that the C in CSS means cascading.

> different order?

display:grid, grid-template and even position:absolute if you need.

Do you think it will be too repetitve? Make a SASS mixin that defines these for you. Not only you're still keeping CSS separate from the HTML structure, it will very likely work in the same way that all of those "pull-x" and "push-y" rules are doing anyway.

> single <button> specifically?

I am not against using classes and ids that define purpose and even state (for the odd case where the attributes are not enough/non-existent). What I am against is the definition classes that are mapped to the presentation. You can have a <button class="critical-action-trigger"> all you want, but please do not make <button class="size-huge red">.

Likewise, if the "fire all nukes" button is so special, it deserves to be represented with <button id="fire-all-nukes">.

> then that's exactly what Tailwinds already does for you.

I said above. If tailwind was only providing a bunch of utlity mixins and variables that I could then @import to my SASS, I would understand. What I don't understand and do not want is to have classes that I am supposed to be writing inside the HTML.

The reason that I don't want that is not out of "purity", but rather because this lack of separation of concerns is leading us to a sub-optimal solution and forcing every frontend developer to reinvent component libraries every time they want to do something that is non-standard.

If we had a 100% style-free "standard" component library and the CSS designers focused only on implementing their design languages against that standard, the chances of us getting a more paretto-efficient basis for frontend development would grow immensely.

Nowadays, every frontend developer either needs to do everything on their own or hope that there is already a combination of JS component library + design language that is acceptable. If we had my way, everyone could then start their application with the standard components, pick any design language that claimed to implement the rules for the standard components and customize only the relevant parts. Everyone's 80% of the job would be mostly done.


If it was so easy then it wouldn't even be a problem. You're arguing for the ideals again. This isn't new, many people have been trying for the past 15 years but there's a reason it just doesn't work out. If you want to find a "paretto-efficient basis for frontend development" then good luck, but reality has shown that CSS is not separate from HTML, they are the same concern because presentation includes structure.

Cascading rules and specifying by HTML layout are hard to deal with, especially in larger projects, because that structure may change and rules can overlap in complex ways. It's far easier to just atomically apply some classes directly to your HTML. And yes, you can use Tailwind as mixins within your sass rules without ever touching the HTML if you want.


> Then you define the corresponding rule. With SASS that is almost too easy. Also, don't forget that the C in CSS means cascading.

Over the lifetime of projects 'cascading' always led to headaches. There's a reason the whole BEM thing became a thing.

> Do you think it will be too repetitve? Make a SASS mixin that defines these for you. Not only you're still keeping CSS separate from the HTML structure, it will very likely work in the same way that all of those "pull-x" and "push-y" rules are doing anyway.

I used to do all that. Still do for some projects that rely heavily on SASS. But using mixins and functions and extends and whatnot adds complexity that I honestly feel I can't justify anymore. /Why/ do I want to keep CSS separate from HTML when in practice they tend to end up entangled anyways. It just reeks or cargo-culting 'separation of concerns' where really it's just 'separation of technologies that are separate for historical reasons'.

> I am not against using classes and ids that define purpose and even state (for the odd case where the attributes are not enough/non-existent). What I am against is the definition classes that are mapped to the presentation. You can have a <button class="critical-action-trigger"> all you want, but please do not make <button class="size-huge red">.

But why? Other than 'this is the way it has always been and I refuse to change my mind'?

> I said above. If tailwind was only providing a bunch of utlity mixins and variables that I could then @import to my SASS, I would understand. What I don't understand and do not want is to have classes that I am supposed to be writing inside the HTML.

Because it works. And it's measurably easier to do, in the experience I and many others have. And because I still can't find a good argument not to.

> If we had a 100% style-free "standard" component library and the CSS designers focused only on implementing their design languages against that standard, the chances of us getting a more paretto-efficient basis for frontend development would grow immensely.

I do agree with this, I think. But day to day it's not going to happen. When someone comes up with a popular style-free standard, assuming that's practically possible and good enough to become popular, I'd happily switch to that.

> Nowadays, every frontend developer either needs to do everything on their own or hope that there is already a combination of JS component library + design language that is acceptable. If we had my way, everyone could then start their application with the standard components, pick any design language that claimed to implement the rules for the standard components and customize only the relevant parts. Everyone's 80% of the job would be mostly done.

Yes, but honestly by that logic we could dismiss any improvement and argue for some kind of ideal where HTML and CSS are not used for app development in the first place. But that's just not the reality we live in.


> But why? Other than 'this is the way it has always been and I refuse to change my mind'?

It is interesting how the immediate use-cases dictate our first opinions of the technology.

As I stated in one of the first comments of this thread: I am working on a self-hosted crypto payment gateway and I am providing a "Stripe Checkout" widget for those that want to set up a payment workflow inside their website.

I could do exactly what Stripe does and make one good-looking widget and just give the user the option to change some things like color scheme. But two things go against that: first, I am a terrible designer, so I am sure that anything that I come up with will not be as nice what Stripe does. Second, it is an open source project and I would rather have more people feeling encouraged to contribute their own different themes than trying to enforce "my" styling, which we already established will be bad.

What am going to do, then, if not ensure that I write the components without any predefined styling and perhaps offer an open source repository of "themes" - like CSS Zen Garden?

So, there you have it. My reason to argue for a "pure" HTML structure is not just out of some idealist out-of-touch mentality.

> When someone comes up with a popular style-free standard, assuming that's practically possible and good enough to become popular, I'd happily switch to that.

Honest question: would you pay for funding this? I think this haven't come to be is because it's much easier to sell a "turn-key" system than something that is flexible enough to get other developers to say "I could've done that as well."


> So, there you have it. My reason to argue for a "pure" HTML structure is not just out of some idealist out-of-touch mentality.

No, but it's based on a use-case that is very specific and considering that it's a relative uncommon one, I don't see the point of trotting it out. Okay, so in this particular situation maybe something like Tailwind isn't ideal. Nobody is arguing that it is.

> Honest question: would you pay for funding this? I think this haven't come to be is because it's much easier to sell a "turn-key" system than something that is flexible enough to get other developers to say "I could've done that as well."

Sure. I mean, I'm close to paying for Tailwind UI, so paying for good stuff is definitely something I'm willing to do.

But I think what you propose doesn't exist not for lack of payment, but because it's just not that easy to do. In lieu of perfection, stuff like Tailwind can be a pretty good improvement over other things. No need to whine about it or compare it to some hypothetical ideal that you deem good enough for your edge-case needs.


The only issue I am taking with your comment is to think that I am "whining", like I am just waiting for everyone else to respond to my plea. I've done this idea of taking SASS mixins from both materialize.css and Bootstrap already for two different projects and partially for the communick website.

I think it's actually easy to do it. It can be laborious, but not hard. And even the labor is something that can/should be done only once. So the only justification that I can find to not have this as a more widely adopted practice is that using utility classes is "easier" to get started. Coupled with the fact that most people don't care about making their components "portable" between different designs, and we end up with this local maximum.


The problem in this discussion is that most of us are happy with Tailwind based on our experience using it, and our experience with previous approaches. And not just because it's "easier to get started".

And from what I can tell, most of us do care about portability and componentization.

If your experience is different, then that's interesting, but not much of an argument in itself. Either 1) we're just much worse at this than you are, 2) your use cases and projects are more unusual/uncommon, or 3) what you think is 'easy to do' perhaps is not, and perhaps you'd benefit from a more Tailwind-like approach too.

Obviously if what works for you, that's fine. I don't use Tailwind in all my projects, and in some cases wouldn't even do so if I could. And it's not like what came before is entirely unworkable.

But it feels a bit dismissive to argue that our experiences are just wrong, or that we're just taking the lazy way out.


I was in the same boat. It felt super wrong. It felt like the long, slow nightmare of maintaining an early Boostrap site all over again. But I got peer-pressured into trying it on a medium-sized project and yep: I'm in love. I'm in camp Utility Classes now.

The only serious issue I had was when implementing designs provided by an outside designer:

1. The design says this width needs to be 28 px

2. That'd be "w-7", which TW doesn't provide. Guess I'll add it to my tailwind config file.

3. Repeat ad nauseam until I broke down and added all "w-n" widths to my tailwind config from 1 to 500.

4. Repeat for min-width, spacing, border-radius, etc.

The result is that A) I get really good at converting pixels to rems to tailwind-scale, then back again in my head and B) My tailwind config is huge - the saving grace being the purge tool that gets rid of unused styles.


Every designer I've met loves consistency and design systems, but I've found that most design tools are too limited to cover the cases you are discuss. Figma can make a library of colors/fonts, but it doesn't have anything to enforce spacing constraints. It's very possible your designer would have been happy with w-6 or w-8, but their design tool didn't give them that feedback loop, so they pushed ahead with 28px.

I've been curious what a "Tailwind Linter" plugin for Figma would look like....

And when you watch Adam's screencasts, you'll see him take a design which has some "custom" pixel values and then use his judgement to snap it to a built in size.


Every graphic designer I've worked with wants it to be pixel perfect. I've seen them numerous times pull out rulers and literally measure the spacing on their monitor! It takes a special breed to be a graphic designer. In my experience, suggesting that it can be a little off gets me a withering look and the suggestion that maybe we should have another developer look at it. It's never an issue with their OCD.


Seems like the graphic designer is the problem then...

The modern web and pixel perfect design is a combo that doesn't mix and any good designer would know that.


For some elements of the UI, sure. For others, especially branding related, no, pixel perfect is important.

Additionally, this is a good example of the tooling overstepping bounds. Developers giving feedback that their tooling can't match designs made to fit existing brand standards is naive and doesn't reflect business reality.

As a counterpoint though, I definitely see merit in Tailwind for new web-first applications where the development team can align with designers from the outset.


Ask them to provide pixel-perfect reference designs for all possible window sizes.


You lead a charmed life, my friend.

Many designers I have known think of consistency in terms of branding (at most). There is almost always some weird edge case that means a new font size, or unique spacing. Get enough of those, and the design system falls apart.

Some are better than others at this, obviously, but the mix has not really been in consistency's favor (though I will admit it has been improving the past few years).


Note: I didn't say "they love it so much that they follow it religiously and never break from it". :)

While I don't disagree with your points, there is still ground to be made here.

1) If designers had a "tailwind linter" in their design tool from the start, I believe that they would be encouraged to use it from the start and would start tweaking their designs from the get go to look just as good with it.

The same principle applies to code linters. There are exceptions where developers can disable a linter for specific pieces of code, but having it there encourages the code to be "constrained" in a consistent way.

2) Just because a design has a "13px" padding doesn't imply the designer thought "13 pixels is the best value here and 12 pixels is simply unacceptable". A design linter would help with the "expressiveness" of the design and when things truly are "exceptional" cases.

Note 2: I'm obviously recommending a technical solution to the problem very early in the design process, but the way I solve it now is by discussing it with the designer over a zoom call. I'll show them the design and say "does this look good? I deviated a bit, is that ok?" It almost always is, which is a win for everyone.


(not the person you're replying to) This is so true, and thanks for introducing me to Adam Wathan's Youtube channel, I had no idea this existed. I work closely with designers who use tools like Sketch, Framer, Figma, etc and I'm always finding little edge cases where their "pixel perfect" designs have mismatched paddings, margins, often half-pixel letter spacing that they've decided is more aesthetic in their design tool. It can be hard to push back sometimes.


I think this gets to the core of the problem -- we need a design tool that can directly export fully styled React components (or whatever).

Basically, we're asking workaday designers to design using a tool that doesn't respect the implementation constraints, and doesn't allow them to preview at arbitrary window sizes.


you can set custom grids in Figma (like a 4px grid for instance), and you use workaround like spacer elements, and you can setup margins/padding with auto-layout for your components, but yeah there aren't reusable classes in Figma for spacing. Would be nice if there was


I know you can't do much about it but i think forcing people to think about how many "values" they have in system is really helpful.

Good designers will also want as few values as possible. They are creating visual system. I doub't they will want to have 20 different font sizes and padding left values. If there is fontsize 26 and 29 its most probably a mistake because nobody can differentiate the size so it has no function.


that sounds like a not-great designer, tbh. Which happens often, what I usually do is not take everything in the design at face value: 28px is actually 32px, which is 8rem, which is `w-something`.

It really needs to be 28px this time for some sorta-legit reason? Fine, add a semantic class (or id) for it that's not part of your tailwind framework, kind of dropping down to "usual" CSS


An actual inline style would suffice in this case. Before v2.0, if you want anything other than `top: 0`, it was recommended you do it in the style attribute: `style="top: 20px;"`


This won't work for everyone, but it might be possible to push your designers towards using HTML. Tailwind classes are simple enough to manipulate that you don't need to know CSS.

After a while, you get the amazing benefit of simply being able to copy and paste HTML from one place to another - since the class names are common, you can copy HTML directly from a design mockup into your application, with only minimal extra work in templating. This is much more efficient than trying to figure out pixel-sizes in a PSD, then trying to figure out which combination of CSS classes will succeed in reproducing the visual appearance (most of the time, in most browsers...)


Love this idea. I do all my design in HTML+Tailwind. I wonder if all designers would use HTML+Tailwind over design software if they knew it.


Tailwind is superb at specifying design (sub) systems upfront.

Take the time to communicate with the designer to define color shades/palettes, margins, typography and so on. This can also lead to discovering relations and components and intent.


I think the biggest pull back / time sink with Tailwind isn't the CSS, it's the (lack of) JavaScript.

With Bootstrap you have a bunch of common things handled for you out of the box (dropdowns, modals, tooltips and like 100 other things you can easily find on Google since the community is massive). You can just drop these widgets into your template and get going. Often with just 1 or 2 lines code if you're using Yarn + Webpack.

With Tailwind you're on your own for all of that unless you buy Tailwind UI and even then it's only JavaScript solutions with the libraries the authors have chosen to use and it's no where near as feature complete vs the JS widgets you get with Bootstrap, even if you only count what's officially bundled with Bootstrap.

Both of those things are kind of problematic for someone who isn't super strong on the front-end and doesn't want to invest a lot of time designing these things from scratch (a full time job in itself). Especially if you want to use something like StimulusJS instead of Alpine or Vue, since Tailwind UI doesn't seem to include any examples for StimulusJS. There's a whole bunch of folks out there (like me) who aren't building SPAs. We're just using good old server rendered templates with sprinkles of JavaScript.

With that said I still prefer using Tailwind, but it's not really near the level of productivity you get when buying a very well supported $30 Bootstrap theme (ES6 JS, Webpack, etc.) and get going on your project without having to worry about implementing every last line of JS behavior.

I'm sure Tailwind will get there with better JS support. I've seen some of Adam's tweets on how he plans to address this problem but I don't think there's a time line on when all of that will be ready to go, or if it'll all be locked into Tailwind UI only (about $250).


For a react app all what that javascript from bootstrap does is get in the way


> For a react app all what that javascript from bootstrap does is get in the way

But don't you have the choice to not use Bootstrap's JS then, and instead use either premade React components that are vanilla JS or use React Bootstrap components if you wanted to?

I'll admit I haven't written any React code but if I Google for React Bootstrap components I find a ton of resources, even 1 to 1 ports like https://react-bootstrap.github.io/components/alerts/. I also see tons upon tons of vanilla JS React components, all ready to go where you can drop in CSS class names and you're done.

Someone not using React with Tailwind is left with basically having to implement everything on their own, or try to stitch together a bunch of libs that others have written with their own individual opinions and lack of standards. It's a much different world. It's a world where you can spend 10 hours trying to get a responsive drop down working instead of 10 seconds with Bootstrap.


I'll identify as in the "not yet convinced" category on Tailwind (though, I have evolved on other paradigms, which I will now discuss). JSX felt wrong (at first) due to co-mingling HTML and JS, however, I realized that's the wrong application of concerns because 1. JSX isn't HTML, it's a sugared syntax for the React.createElement API and 2. that separation wasn't meaningfully improving my architecture and in retrospect was clearly holding us back. Could anyone evaluate if these are analogous 'separation of concerns' (SoC) fallacies?

I will admit, I think I never fully appreciated the intent of SoC.


> JSX felt wrong (at first) due to co-mingling HTML and JS, however, I realized that's the wrong application of concerns because

The line React core team would say is that that what you're thinking of isnt "seperation of concerns" but rather "seperation of technologies".

React/JSX is good because both the HTML and JS together is the view. It's the same concern.

React seperates concerns much better because it so heavily promotes the functional programming approach and that the UI is a function of state.


Agreed. We got used to thinking of any Javascript as "business logic" rather than "presentation" because it's an imperative language, but React/JSX are tailored to using JS in a way that acts more like presentation. If you write it imperatively, it won't be idiomatic React, and sooner or later something will break.

So it may help to think of JSX as using a functional subset of Javascript. It's not, and that veil gets pierced pretty often, but the better you contain it, the more you can effectively use both Javascript and HTML together as part of a single concern.

Using Redux with sagas even further separates out the most side-effecty parts of it, though sagas are really heavyweight and I'm still not certain if I think they're worth it.


Sagas are a great power tool, but most Redux apps don't need them. That's why we opted to include thunks out of the box as part of our official Redux Toolkit package:

https://blog.isquaredsoftware.com/2020/02/blogged-answers-wh...

(You can still customize the middleware when using RTK to set up your store, same as always, so if you want to use sagas you still can.)

That said, there's a lot of things thunks _can't_ do, and for those use cases it makes sense to use sagas or observables.


You could tie CSS/JS event handlers to HTML elements, but if someone edited the HTML file and changed the hierarchy, things broke.

You could tie CSS/JS event handlers to class and id attributes in the HTML file, but you'd have to add those attributes into the HTML file to target the right elements.

Web SoC always felt more SoF (Separation of Files) to me. There is no advantage in putting the HTML/CSS/JS into separate files if making routine changes requires visiting multiple files. React puts it all in one file, which makes me think that the concern is the Component and not the individual browser parsing libraries.


I will give an example that I am facing right now.

I am working on a open source payment gateway for crypto and one of the things that I am providing is a javascript library for those that want to provide a Stripe Checkout-like experience on their sites.

I started doing this in vue.js, which has the idea of the components where you define the html, code and style together in one single file.

My problem is, I want the user to be able to have the styling of the checkout widget similar to their own website. So I want to have my HTML as simple as possible and let them provide the CSS. I could even try to help and provide some different ready-made CSS (to be used directly) or SASS files (if they want to customize) but I've given up on trying to do that inside of vue component definitions.


There's another approach that is more rooted into react paradigm - styled-components. I still don't understand what people see in tailwind as most of the arguments I see in this thread could also be applied to it, but you also get type-checking (typescript), theming, ecosystem of plugins and a lot of other cool things.


I agree that styled-components takes care of a bunch of issues that make some of us reach for Tailwind.

However, aside from requiring a very specific tech stack, it doesn't solve the problem of every component potentially having slightly differing styles. There's ways to handle this, but one thing I like about Tailwind is that the defaults are stronger across components, while still leaving space to deal with all the one-offs.


I believe in some environments (when you have designs already) building off normalize+react-aria(for logic) and thought-out architecture could be as productive as tailwind, especially if you already have some helper functions on-hand. For me, storing mixins for common behaviours inside theme allows to construct lightweight variations where I need them, and you can dynamically modify it in react.


I really like the author's explanation at https://adamwathan.me/css-utility-classes-and-separation-of-... - key points for me are:

The question is not "semantic" or not. The question is whether your HTML depends on your CSS, or the other way round - and that depends on what you're doing.

Halfway down, it feels like we've somehow managed to recreate the OOP inheritance vs composition debate in our stylesheets (with @extend as an example of inheritance).

To me it depends on what you're actually writing - if you're making a reusable component for other people, say a custom DateTimePicker, then it's much more important to be able to restyle the thing Zen Garden-style, than if you're running the front page of your own organisation and want things to look exactly like your house style.


What I'm struggling with is consistency across pages, especially if you are not using a component framework.

I'll often end up with 50 similar, but different looking buttons.

On the other side when using a component framework, re-implementing all components when there are solutions already available (i.e. very similar in terms of look and feel Ant [1] or even Material-Ui [2]) sounds counter-productive.

Didn't you stumble upon such issue? How did you handle this?

[1] https://ant.design/ [2] https://material-ui.com/


If you're not using components (react/vue etc.) then you can use @apply - I think the secret with that is to blend inline tailwind and the applied style so you might say..

.button { @apply rounded-md bg-gray-600 hover:bg-gray-300 text-white; } and then inline you might use class="button px-2 py-4" or similar to create specific styles. Of course these could be abstracted again to .big-button .small-button etc.

Tailwind has changed not only how I write CSS but how I think about writing front-end code completely - it's really great once it clicks.


I like tailwind a lot but that style of using @apply smells exactly like creating ad-hoc css classes to me


How is it ad hoc? You're creating a class .button, but you're using the Tailwind-specified design system. This is how the framework is meant to be used!

Atomic/utility-first CSS doesn't mean that you shouldn't make classes. It just means that you should make them where they make sense. Don't make a new class just to add a margin to something,or whatever. If the margin is literally all this element needs, use the utility class directly. If it's the only place you'll use this combination of classes and naming the combination doesn't add anything, you might as well just keep it inline.

But if you find yourself repeating a bunch of utility classes, make a class with a semantic name once you start seeing the pattern. In some cases, like buttons, you might see that pattern before you've even started. That's fine. You should definitely have a button class (or three).

What you (probably) shouldn't have a is .info-page__navigation__aside__second_button that just includes the button class and adds a margin, or whatever... like we did at my old job. Urgh. I refer to this as "might as well be inline CSS" - making extremely specific classes that are only used once. If your CSS classes aren't reusable, all you gain from not having it inline is the joy of maintaining two text files, and manually look up the cross references. Tailwind solves this perfect, IME.


To me, that is what it means: You shouldn‘t make classes.

Only if you are using a component framework or something that works like it though. Otherwise you should make semantic-style classes, yeah.

It‘s ad-hoc because you can not predict what a class contains (tailwind classes) or how it is spread through your codebase (BEM classes)


Not everything requires making a component. A CSS class can be fine, and I'd always use the least powerful way first. This is how the framework is meant to be used - that's the entire reason for having @apply.

https://tailwindcss.com/docs/extracting-components

I don't understand what you mean by ad hoc. It's a very structured approach. When utility classes don't work, you make a semantic class. If that doesn't work, you make a component. You can even use BEM naming if you want, you'll just be making a lot fewer classes.


you can make common styles for things like buttons, if you watch adams tutorials videos, they cover this reasonably early on


> adams tutorials videos

They're all gone. Vanished completely from the website. And I was half-way through!!! Now they link to somebody's youtube channel for random Tailwind stuff rather than the nice walkthrough/tutorial that were the originals.


Is this what you're looking for?

https://v1.tailwindcss.com/course/setting-up-tailwind-and-po...

There's a version selector in the upper right corner.


Oh, thanks! I didn't realise they still had the old site up somewhere.


Where were you watching them? Assuming you mean these, hosted on egghead:

https://egghead.io/instructors/adam-wathan



Oh, thank you. I didn't realise they were on YT as well. The new website points to somebody else's channel (Tailwind Labs) instead of this one.


It works for simple single-element components.

When you have things nested it gets out of control really quickly.


how does it get out of control? I've been using it for quite sometime now (with Vue). I really haven't experienced things getting out of control. Curious what problems you have had?


So what you’re saying is that Tailwind is css-in-js with pure css? I can get behind that, design systems and component libraries have completely revolutionized how I think about these things.


Yes that is 100% what it is. Using theme-ui or tailwind is just a switch of technology and syntax. The development style and thinking is the same.


Suppose you don't want to use a JS framework in your application, and you instead want to serve HTML and CSS via server-side HTML templating. I do understand the premise (mentioned many times in the comments here) that semantic CSS classes have somewhat limited value when you're doing all your HTML via templating.

Are there CSS frameworks that help with responsiveness, and work well with templating, but are designed to work exclusively with SASS/SCSS and not leave utility classes visible in the compiled CSS? Preferably something that doesn't start with "let's make h1 and p and ul all completely unstyled", and instead has reasonable defaults that let HTML work like HTML?


It's wrong because it's useless: you can use inline styles instead (and if you gzip the html it's probably going to be smaller as long as you factor in the framework, since essentially you are using numeric LZ backreferences instead of useless long class names).

The whole point of CSS classes is that they don't map to fixed styles, so they offer a useful abstraction, allowing you to change the CSS class definition once and effect all elements it applies to.


I'm not using Tailwind, but that comparison is wrong. Something like mt-2 still doesn't map to a fixed style, and it also has another specificity than inline styles which makes it easier to override.

If you need to globally change the margin that mt-2 adds, you only need to change that class instead of all HTML inline styles.


Sorry for my ignorance, I am a backend developer and I am trying to figure out what is the best for my frontend code (when I work alone on something). So far I was using Tachyons (https://tachyons.io/) and elm-ui (https://elm-ui.netlify.app/). Is there a chance that Tailwind would be better for small / medium sized projects than these? Based on your comment it looks like. The only problem with Tailwind just by looking at the default settings was its size. I was reading somewhere that you can greatly reduce that. Your second point sounds pretty good (almost like a discriminated union for CSS)


Once I properly used Tailwind for a mid-sized project, I was pretty much sold on it. Size was my main issue. With PurgeCSS the payload can be really small though. it only includes the Tailwind classes that you're actually using.


Thanks! I am going to check out PurgeCSS.


> 3) If you're struggling to abstract reusable higher-level classes/components, the problem might actually be with inconsistent and non-modular design, not CSS tooling. If every page or section is a "unique work of art" then you may have poor UX/design.

I can't agree with this more. It is almost punishing in how it enforces consistency. You really have to try to move outside the consistent default it has set and if you find yourself having to do that, it should be setting off alarm bells.

I do think it has to be used with a component system though. It provides the context that people miss when you don't have nominal class names anymore. It even encourages something close to styled components I find you have very small components that do one thing.


Several people have pointed out the redundancy, even hypocrisy, with `@apply` and compositional classes. I like to think of `@apply` and componentization as competing solutions. Just like "composition over inheritance" I believe in "componentization over @apply / composite classes".

Ideally, you don't have composite `.btn` classes. You simply have a `<btn>` component which encapsulates appropriate Tailwind CSS classes in the component (no external CSS, `@apply` required).

With this framing, `@apply` is the less preferred of 2 approaches. It's good, even necessary, in some situations, but generally you should seek ways to componentize vs. abstracting compositional classes.


Agreed. Although I'd say that in practice I often find the need to use mostly a fixed set of Tailwind classes + some adjustments. It can help to use @apply, but I think even the documentation advises against reaching for it too quickly. a <button> would be a typical use case for me.

The way I see it, @apply is like a mixin, compared to CSS atrocious global inheritance. I tend to start with components (and 'micro-components') with all the Tailwind classes, but if I start seeing an obvious pattern I will consider using @apply. In practice, that's worked out very well. It really seems to help with not abstracting too early or too late.


Not only is it productive and maintainable, it's super performant! I work on systems with very limited power, so it's been a godsend in fixing performance for machines that can't handle all this "CSS in JS".


So what's the answer to semantics and user styles? Just, screw it, they aren't important any more?

I mean, I get it, it isn't something most people care about, but I still value them.


Just use Tailwind utility classes in the html while you’re figuring out your design. Once the design solidifies you can write clean, semantic classes for your html and move the tailwind utility classes to your css file using @apply. It’s really the best of both worlds!


I always felt uneasy about the "separation of concerns" with HTML/CSS/JS.

I felt it was at the wrong level - a technical one. HTML and CSS are different technologies, but the domains we should be separating are logic and presentation. These don't always map, e.g. there is such as presentation logic.


agreed on the counterintuitiveness. I echo a lot of your points on my Why Tailwind essay: https://www.swyx.io/why-tailwind/


Same here. I'll add that I think the hundred bucks or so that we spent on Tailwind UI was worth it many times over.


First they ignore you, then they laugh at you, then they fight you, then you win.


Framework author here! Don't miss the new landing page, it is probably the part I was most excited to share :)

https://tailwindcss.com/

Crazy amount of effort went into building all of these interactive examples, so proud of how it turned out.

The trailer in the blog post is absolutely 100% a joke in case it's not obvious. The music was scored for us by a friend, and that's a real life professional opera singer at the end chanting "utility first" in Latin. It's completely absurd and absolutely outrageous, just laugh at it :)


I have never heard about Tailwind before, but the interactive elements and animated mini examples on the landing page are stellar at conveying what problems the framework solves. I've been putting off the UI for small project of mine and this looks like a great chance to try it out.


I don’t want to steal the focus from the achievement, but the landing page fails to open on Safari on iPad Air 2013.


Yes, still seeing that too. The tailwindcss homepage fully loads for a brief moment then shows a white screen with "An unexpected error has occurred."

Using Firefox on an Android phone.


Same behavior in firefox 68 android, but not in the new firefox android (using 83 beta), where it works without problems


Yeah works now, thanks.


I had to replace my 2013 iPad Air because barely anything would work on it anymore. It’d run Netflix and basic websites, but that was about it.


I am big tailwind user and i can confirm. I have same tablet first Air it just crashes due to "unexpected error".


And want to add scrolling on Safari 14 isn't very smooth at all. Although that is probably Safari's fault.


Every example I see seems to work with Safari on a 2020 iPad Air, /shrug. Ya on an old version of iOS?


Also had this issue.


I haven‘t even tried the interactive parts but I want to say that just the messaging and presentation flow is spot on.

I‘m 50/50 between tailwind and theme-ui style tools (which are really more similar than not). Just how well you can articulate your vision is honestly convincing me to just fully embrace tailwind. It‘s something every developer from every framework or guard of web development can get on board with.

I‘m happy you are putting the recommendation to use components or partials front and center over @apply. In my experience @apply has the power to negate the wins from tailwind. Maybe v3 can drop it?

One small thing: maybe you already discussed it but I would just drop the word gag reflex from the landing page. It‘s just... unpleasant.


That might be one of the best landing pages I've seen.

I'm sold.


I was coming from mobile app development when I tried Tailwind (with Vue) and I knew right away that it was architecturally sound. It's the only CSS framework I've ever used since, and I think it's very future-proof.

That said, I really don't like how it's being described as "utility-first". It's very ambiguous language to me even as an experienced programmer, and I've never really seen that phrase used elsewhere. Besides, all that the authors really seem to mean by "utility-first" is that it is "composition-based" as opposed to the more common inheritance-based approach to working with CSS.


It’s just a catchy phrase to help evoke the right emotion and make you remember the framework, which I think it does a good job at. It made sense to me at least in the context of reading about the framework, and besides no single hyphenated term is going to accurately describe a technical system.


This landing page is the slickest demonstration I've seen of anything in programming


Hey Adam! I know the video's meant to be over the top but I'd be curious who/what you worked with to make the visuals and animation if you're willing to share :)



OK, the trailer sold me. Seriously. I was skeptical about Tailwind, but the trailer makes it feel like you're my kind of person, and I want to try your product.

Also credit to a post above, which acknowledges the "it feels wrong but it makes sense in the end" sense. I'd dismissed Tailwind in the past over the feeling that it was the Wrong Thing. This convinces me to give it a try the next time I'm starting on something.


for tailwind 3.0 i would love for you to bring your rock/metal passion into the video!


That landing page is absolutely insane. It really makes me want to try Tailwind.


I love the trailer! The part about dark mode was blazing.


It's very obvious (in many different places: landing, documentation, streams) that TailwindCSS is made with love. Thank you for that!

P.S. Trailer is cool!


That is just swank. Also, thanks for Tailwind.


Hi Adam,

The demo given just below looks amazing. I initially thought it was a video, now seeing that it is actually coded. Brilliant


tailwindcss is like the fresh air that finally comes after trying bootstrap, flatui, kubecss for years. Thank you.


"Brutalist" - love it. Was "Jack McDade is the absolute worst" too long?


Safari: sites load and then... "An unexpected error has occurred."


Love the trailer, and great job on the entire release.


I love the new landing page, so awesome!


very much enjoyed the amount of sass in that blog post announcement ;)


That is a fun trailer. I laughed


Beautiful, beautiful work


both landing page and a trailer were fantastic


That is an absolutely beautiful home page. Very Apple. Well done!


The things I love the most about TailwindCSS:

1. After purged the CSS file is really, really small.

2. Hopping into all of my projects and not having to remember new class names.

3. Not having to come up with new class names.

4. Not worrying about making a change in a class and having unintended consequences.

5. Not skipping back and forth between HTML or CSS files.

That said, if you don't dig it, there are plenty of other great frameworks, naming conventions and approaches that people use. Or start from scratch and roll your own.

For frameworks I flirted with InuitCSS for a bit. It's pretty nice and after digging through the code I realized it's not as complex as it first appears.

I also like Andy Bell's approach with Cube CSS.


> 5. Not skipping back and forth between HTML or CSS files.

What? I thought the point of this was for use with composable JS components.

You're manually writing and updating attributes like this?!

  class="text-4xl sm:text-6xl lg:text-7xl leading-none font-extrabold tracking-tight text-gray-900 mt-10 mb-8 sm:mt-14 sm:mb-10"
How could you possibly manage this without components? Ctrl-F "lg:text-7xl" and replace?


Lots of good responses already on other ways to abstract, but I'll even go one further and say "sure, why not?"

When are you changing every single instance of "lg:text-7xl"? More often you're probably making a change in one single place in the app, in which case this is incredibly easy, you just make your change where you want. You're not slowed down by digging through layers of abstraction cruft and indirection until you find the right place to make the change.

If you're doing an entire site design refresh, then doing some find and replace isn't really that crazy. For something you do relatively infrequently like this (maybe every couple of months or even every couple of years?) it's not a big deal if it takes a little bit longer. And likely you'll need to look through and test your changes on every page one by one anyway, to make sure you're not breaking anything you didn't mean to. You'll need to do that whether you changed the definition of a css class, or you made a bunch of inline changes, at which point making the actual code edits inline probably isn't even the bottleneck.

But again, that's perhaps a bit extreme of a way to look at it. You will inevitably have some layer of abstraction anyway, something like components or templates or partials, in which to wrap your styles.


> When are you changing every single instance of "lg:text-7xl"

I'm not, I'm changing some 7xl-sized text in multiple places. But I don't want to change every element that is .lg:text-7xl already.

> If you're doing an entire site design refresh

I'm not

> You will inevitably have some layer of abstraction anyway, something like components

I already do, they're in JS, and much more powerful and extensible than HTML attributes.


You could also update the Tailwind config file to define what "text-7xl" is. Default is "4.5rem"


> But I don't want to change every element that is .lg:text-7xl already.


You don’t need to be using a JS framework to have components. Pretty much any server-side templating language allows extracting “components” in the form of reusable HTML fragments. And even if you’re serving static HTML, there’s plenty of ways to compile a template into a static file.


Right, components. Not a search-and-replace for every instance of ".color-pink" in your codebase, suggested by the parent.


Sometimes I extract to component classes, but in Laravel or Statamc the html element and the classes have already been extracted to a component so there's only one place to make the change anyway. When doing WordPress sites I extract to component classes more often.


Yes, if it's not componentized into a smaller chunk, find and replace works fine. The beauty of Tailwind is though, if you change that, you know exactly what the consequence is since every utility is so highly targeted.

You absolutely do skip between lots of HTML/JSX/VUE files, but that's true of any project. The point of tailwind is to keep you in the view layer of your project and not jumping between more than a browser and one tab in a code editor when building your UI.


> find and replace works fine

It would replace every `.font-extrabold` element on the page.

What if I only want to update my extra bold headlines, not the extra bold subheadings? Global search-and-replace breaks my subheadings.

>> 5. Not skipping back and forth between HTML or CSS files [with Tailwind]

> You absolutely do skip between lots of HTML [with Tailwind]

??


Yep. There's so many global replace situations where the logic completely breaks.


In my experience global replace is much easier across multiple component files rather than multiple CSS files. If I need to do change a font color I do a search and know to change it based on the file/component it's used in. If I had to change the color in css files I'd have to review the class and also track down where that class is in use.


You make components as usual, but you style with those utility classes. Those utility classes are configurable in one theme file where you can set what "text-4xl" is or how much space "mt-10" is.


I’ve been keeping an eye on Tailwind. Over the last few years we’ve switched from old school single css file to css in js, and while that helps with the class spread issues, by lots of other measures it’s inferior. This was solidified for me last week when we rebranded our app and I needed to hack in both new and old code. Editing is js controlled css in the browser is just too painful.

Anyway, couple of weeks back I needed to make a website for a mate and decided I’d give tailwind a spin. My god does it make css fun again. I’m not sure how you look after sprawling styles in a bigger app (though I’m sure I’ll figure something out) but having the right combination of safe css, everything right there and responsive styling locally is a dream. I’m totally sold.


I don't do front end dev, and haven't for a very long time, but can someone help me understand how this doesn't lead to inflexible hard to maintain soup? Just to take colours, for a moment. Ordinarily I might define semantic classes, let's say "primary-nav" or "prominent-action" and apply them to relevant things (and use relative selectors for things inside them, etc.). So if I want to change the colour of all prominent-actions across my web app, I just do it in one place. This seems to be demo-ing adding a particular colour class to everything I want to be that colour. So... If I change my mind, what now? I have to find all those places and change the applied class? Search and replace?

This seems like the literal opposite of the clean separation I always understood to be the point of styling being separate to markup...


Actually it's more like toolkit to make your own set of utility classes. With one config you can really change it to be whatever you need.

I always throw away colors on every project and change it to semantic naming. I add / remove fontsizes, spacing whatever project needs.

I've been also confused how can people use it without touching the config but apparently many do. I guess when developers don't have particular design or brand they just pick from whats available.


> Actually it's more like toolkit to make your own set of utility classes.

You mean like CSS? Why recreate raw CSS as classes and use that in your CSS? I'm sorry but all I'm seeing is a huge disconnect.


It systematically abstracts CSS to an atomic subset.

You either take the default configuration with a few tweaks, for example if you are a programmer first.

Or you define a more complete, unique system upfront, for example if you implement a bespoke interface from a UI designer.

If you see emerging patterns that ask for composition, then you can easily compose utilities and give your components semantic class names.

It is a blessing for productivity, performance and maintainability, because it decouples CSS concretions by introducing a light, composable abstraction layer between raw CSS and component/semantic CSS.

Think of it as a lightweight, well defined query builder on top of SQL that you use for safe parameter binding and composability. (The analogy leaks a bit but you get the drift)


Yes, like CSS, but it’s effectively a much smaller subset of CSS. Instead of the entire CSS specification being on the table though, it’s a drastically smaller set of “utility” classes (or properties, to follow the “but it’s css” logic)


It’s CSS with a design system. If you need to bump a value like margin or font size by one click you know you’re doing that within the context of a harmonious scale, not just writing free-form css, reinventing a design system (if you even have one) from scratch on every site.


Ideally, you can use theming.

https://tailwindcss.com/docs/theme

Its slightly more work, but well worth it.

Regarding the 'class soup' thing, I found that using 'primary-nav', etc to also devolve into soups, albeit, soups of a different taste.


> can someone help me understand how this doesn't lead to inflexible hard to maintain soup?

It most likely does, but it's not old and popular enough for people to have accumulated enough technical debt within systems built with it.


My thoughts exactly.


Tailwind is completely flexible, if you would rather have your colors be `brand-light', `brand-dark`, etc you can. Just update your config however you want.

It just comes with a config out of the box that is highly usable for any app and any need without customizing. Purge then allows you to strip out all the extra unused CSS in production.


Ok, so I could mark everything as "brand-dark" and then change the definition of that in the CSS? Mmm. Ok. How about layout and sizing? A lot of that looks a lot more defined - I'll pick a random example from their own homepage then: "border-b border-gray-200 py-6 flex items-center justify-between mb-16 sm:mb-20 -mx-4 px-4 sm:mx-0 sm:px-0" - if I wanted to change my approach to centring, justification, and sizing, it still seems like a lot of search and replace...

(I think I understand that the approach is that I'd then change what those definitions mean centrally - but that won't help me if I decide that two properties which are currently different should be the same, or vice versa).


Layout tends to be a property of a particular component, and semantic classes don't work well there either.

In a complicated codebase with multiple devs, the number of times you could confidently make a "one-place-CSS-change" to a semantic layout class is very small. It's likely that in one place or another, some dev made an assumption about your `sub-container` class or whatever, which causes your change to break their layout.

Most large codebases thus end up with a TON of very specific class names (often used in one place), so the dev can be confident in their layout; this is the biggest contributor to unmaintainability that I've seen in large applications.

If everyone is forced to use e.g. d-flex justify-content-center ..... it hugely improves readability as any developer can quickly look at any layout and see what is going on without building a mental index of semantic class names that the original dev chose.


but my Cards are design components, they don't have semantic classes. How is ctrl+f "border-b border-gray-200 py-6 flex items-center justify-between mb-16 sm:mb-20 -mx-4 px-4 sm:mx-0 sm:px-0" better than changing .myCard__title{}?


I guess it depends on the project, but I can't recall one time I've had to do a CTRL F like you've mentioned.

Of course if you have a very simple page with just some cards, a couple page layouts, that is one thing. Probably can get by with just a myCard class that works everywhere on the site.

But in most projects, as the number of custom components grows, nobody wants to go back and touch (break?) old CSS, so they end up just writing a bunch of fresh stuff for this new feature and throwing it on the pile.

This problem happens often, while the refactor-in-one-place case happens very little.


I was going to say the opposite. Search-and-replace would never work on a high-volume site with a lot of components. Replace ".font-bold" and you just affected anything that was bold across the entire site.

I could see a use for this in JSX though.



Instead of repeating "d-flex justify-content-center..." everywhere is it possible to define that once and inherit those properties in Tailwind?



Definitely, you can still add custom classes where it is the best solution, such as a reusable layout.

EDIT: Instead of custom CSS classes, Tailwind recommends extracting components like the other commenter pointed out. https://tailwindcss.com/docs/extracting-components



> Create a template partial or JavaScript component

The parent comment was specifically about not using components.

But you use your Bootstrap/Tailwind utility classes in JSX. Now your styling is tightly-coupled to your component again. Isn't that just CSS-in-JS with more steps and less power?


Basically, these concerns are split in half now, between components and design systems.

In my opinion tailwind works out best if you use components or use template partials in a component style. In that case, there won‘t be that many places where you declare what your primary nav looks like. You just go into the PrimaryNav component and change the class.

In the other case you mention, you may want to use a semantic color name, which you can do in tailwind.config.js no problem, so your color class could be bg-action-300 or bg-red-action. Now this is not the same as some action-primary css class which could contain color, layout, an IE hack whatever. It‘s only predictable design system primitives like color, spacing, typography style, shadows etc. You can think of these like types in a programming language because they are enforced and predictable, not ad hoc thought up by developers per project.

Both of these things have emerged more strongly in frontend in recent years, so it makes sense that different things make sense than 10 years ago (semantic classes)


The inflexible soup can come just as easily in the opposite direction though. Eventually you have prominent-action-7 and you need documentation to understand what all these supposedly semantic names actually mean in reality and figure out which one you want. Or you want to change the look of your prominent actions, so you change the class definition and then later you realize someone made a totally different kind of thing look like a prominent action and just reused the class but now it should no longer be the same. Making a change in one place breaks other things in totally unrelated places in the app. So in order to avoid that, you need to look closely at every use of a thing anyway when making a change to make sure you're not breaking something. And if you're doing that, then you're not even getting any benefit from your abstraction anymore, you almost might as well change every instance of the thing one by one if you have to carefully comb through them all anyway.

> So if I want to change the colour of all prominent-actions across my web app

As I was just saying, it's naive to think this would ever be a simple one-line change of a constant. It will inevitably be a moderate sized undertaking no matter what you do, because of all the cruft and coupling that may have built up under the old assumptions. But it's also not something you're doing every day, so it should be far from the first thing on your mind when thinking about which patterns are most helpful to use.

But, even putting all that aside, using utility classes like Tailwind doesn't even prevent you from abstracting as much as you'd like. You just do it at a different level. You're not likely writing static html on every page anyway, you're probably using code to generate your html whether that's React components, server-side rendered views with partials and templates, templates in a static site generator, etc. So you can still do the abstraction you want at the level of your components or your view code instead of via css classes. In that world you can think of tailwind as just a higher-level version of the underlying css properties. And you're still free to repeat yourself or DRY-ify your code as much as you want (though as I allude to above, I tend to think DRY in programming is often very overrated).


Theming can be done for specific types of elements but also your own keys like "primary", "secondary", etc. You should be able to change the color in one place.


I'm on the same boat. No one here really tells how to avoid the ease of getting tens of classes added across many tags. Tailwind requires a lot of self-discipline and that is very easy to omit in some projects. I can't imagine maintaining a project with tailwind on board.


As someone who is actively maintaining several projects using Tailwind now, it really doesn’t in practice. In fact if anything it requires _less_ discipline, because a styling change can’t really break a layout elsewhere.

You avoid repeated classes by extracting components (either template partials, or actual components if you’re using a front-end framework). The components themselves define how they look, and then you assemble them, perhaps with a few additional classes for things like spacing. If you need to change a component you don’t need to go and change classes everywhere you’ve used it, you just change the component itself.

If you feel like reading further, Tailwind’s author explained his rationale very clearly in a blog post a few years ago [1]

[1]: https://adamwathan.me/css-utility-classes-and-separation-of-...


"Incompatibility with IE11, so you can tell the man upstairs 'sorry boss it's out of my hands, blame Tailwind'..."

I know it's said tongue-in-cheek, but popular frameworks taking this stance is valuable when convincing clients, leaders, authority, etc. to not require IE support. I've consulted on dozens of front-end projects, and showing the stance of "industry leaders" is the most convincing argument.


That's the tail wagging the dog though…

I've got clients whose customers using IE11 represent 1-2% of revenue i.e. $1M+ / year


How much could they increase the revenue from the 98-99% by if they dropped IE11 and moved faster, spent less time on supporting old browsers, or embraced new features? It's possible (even likely) that simplifying the code by supporting fewer targets that need additional work would increase the overall profit.


Most likely zero

They're an online retailer and those customers would just go to someone else who's site would work in IE11

People aren't stuck on IE11 out of choice, it's corporate policies and other factors at play


yes but one of my central arguments [1] is that it is time to explicitly charge customers for IE11 support rather than implicitly have your 99% of customers subsidise support for the 1%

1: https://www.swyx.io/ie11-eol/


Yes, but you're using that argument in the context of a software business rather than a consumer facing retail business


these customers are obviously the poorest percentile


> Internet Explorer represents less than 1% of my work traffic according to Google Analytics. People will sometime spin this away by arguing that 1% of a large number is also a large number. If you have 100 million hits, 1% is 1 million hits! But the flipside is that 99 million hits are not Internet Explorer and are not helped by optimizations aimed at Internet Explorer.

https://blog.carlmjohnson.net/post/2020/time-to-kill-ie11/

1% is 1%. If you can’t find a better way to improve revenue by 1%, you’re in too narrow of a market fit.


How many of them are unable to use a new browser? Long back our enterprise app didn't work on IE6, our stance was, "yeah it does not, install Chrome". I don't think we ever lost a deal because of it.


At this point even JIRA and Microsoft 365 have dropped support for IE11. The majority of big corporates have either moved to Chrome or are hurriedly doing so.

However, there are presumably old computers in far-off corners of the world that still use IE11. I wonder what will happen there...


They can continue to use IE11 for that one, weird corporate intranet app that nobody likes using anyway, and they can also load a modern browser for everything else the user has to do. Browsers don't exclude each other.


as well as linkedin, skillshare, dailymotion, etc. i keep a running thread of major IE11 drops here https://twitter.com/swyx/status/1260627626739130369?s=20


Microsoft, in general, doesn't even really "support" IE as a general purpose browser. They view it as a compatibility platform for old IE-only apps.

Edge is Microsoft's only general purpose browser ATM.


This depends completely on the industry.

Maybe a dev tools startup etc. would accept the Industry Leader argument, but Retail for example would never pass up the revenue opportunity by dropping IE11 support.

I've always appreciated when libraries who drop IE11 support provide polyfills etc., or at least some notes on it, since the library author knows better than anyone which corners are not IE11 compatible.

This eases adoption in these other industries, instead of taking this hard stance which may sound good, but ends up limiting the # of devs who can use the library.


Good news is v1.9 supports IE11 and is pretty damn good already. A lot of the updates here are just default config options for tailwind, that you can add yourself to mimic 2.0


I would have thought that the most convincing argument would be that the company that made the software has deprecated the software and no longer supports it. However, it's not always the user's decision, and they are forced to use IE due to a corporate IT decision to lock down the users from allowing software installs (understandably).

I've used a product for doing webcasts that 90% of the users were on IE11. The training was for nurses using hospital provided computers that are locked down by their IT staff (for good reasons). These poor users are forced to use the default browser that came with the OS. Every single issue that the users had was from someone using IE. Some hospitals finally relented and deployed Chrome for the users doing the webcast.


What often gets missed in the tailwind debate is how it forces you to use a design system. When you’re writing CSS by hand it can quickly get out of control when you need to bump something up or down, left or right by a notch. If you add padding it should be related to font size, line-height, etc on some sort of cohesive, harmonious scale. By using a Tailwind class of py-2 rather than writing a CSS class you can be confident that the change will fit with the design system as a whole. This is much better for most people than creating your own design system from scratch every time you need to make a web page. Once your design starts to solidify, just extract out common components like “button” out of the html using @apply.


For those complaining about dense HTML using Tailwind, the headline feature of 2.0 should be @apply for everything: https://tailwindcss.com/docs/functions-and-directives#apply

It lets you move all of those excessive class attributes into your CSS, where it realistically belongs. And that makes your CSS look a little more like CSS. But you get guard rails on it by applying a known set of properties to each rule. It's really the best of all worlds.


> It lets you move all of those excessive class attributes into your CSS, where it realistically belongs

No. Adam said multiple times that he basically added the feature to make onboarding people smoother.

The right way to use Tailwind is to extract components, for example in Vue.

That way you have the markup, behavior, and styling in self-contained in a single file, that can be used anywhere, without leaking any internal implementation details.


Can you help me understand the architecture a bit better? I have some reservations.

If you extract components then you require JS (low lighthouse score, lots of JS processing on slow devices, likely SEO problems) or SSR to render the page and then serve it (high TTFB)

Ideally you would have some kind of build step that can pre-process all the vue components and spit out pre-rendered HTML for all pages but preserve the interactive parts of the component scripts.


> If you extract components then you require JS

Only for interactive components. You can use PHP or a static site generator and create components with no runtime JS at all.


Yeah I suppose if you use a server-side framework you can use a templating engine to create partials for your components and have a single source of truth that way. I was curious to know if there was a way to do it with just Vue + some build step and pre-rendering


Not sure about Vue, but in React the simplest thing you could do is to use ReactDOMServer.renderToStaticMarkup(). You can develop your whole "app" in React and then create a JS-less HTML output. There's also Charge [1], a React static site generator with no client-side JavaScript.

[1] https://github.com/brandonweiss/charge


> The right way to use Tailwind is to extract components, for example in Vue.

That's not the full story. Using @apply is the only option if you're not using a component based JS framework like Vue or React.

@aply works everywhere. The current documentation highlights this difference; showing both component extraction and using @apply as a failback when you want to go old school.


Sure, you may have to use @apply if you're for example adding Tailwind to an existing project with .css files.

But the right/ideal way to use Tailwind is to use components. That way you get the most dev ex that Tailwind can provide.


I think the three levels all have merit. If you don't end up repeating yourself too much, just add the utility classes directly. If you find yourself repeating a bunch of classes together, maybe you can make a semantic class with @apply. If you're repeating a bunch of HTML (and Javascript) along with the CSS, make a component.


    @apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
so @mixin in Sass? @apply in CSS? (being replaced with Shadow Parts)


> It lets you move all of those excessive class attributes into your CSS

If only CSS had thought to include such a feature.


Yeah, Tailwind uses postcss to let you use its utility classes with the normal way of doing abstractions in CSS - but it also promotes using Javascript component frameworks where that makes sense.

The utility classes are in themselves great. It's a complete set but it still promotes thinking in design systems.

CSS classes are good, but should be used in moderation. Since you're likely using a component framework anyway, you can often just use the utility classes directly in your components with no loss of clarity and without repeating yourself. But when you do end up repeating yourself in the CSS, you can reach for postcss's @apply and have access to Tailwind's design system. The three levels work extremely well together.


Yes but you shouldn't do that really. You should use a view templating system instead to recycle the patterns you spot, e.g. button.tpl would contain the abstraction of classes.

The moment you collapse the classes in to a single class you're back to square one and the reason functional CSS arose be first place.

Adam Wathan promotes this pattern himself in this video.

https://youtu.be/J_7_mnFSLDg


using @apply adds all of those properties and values into a new css class right? you're adding extra lines to your bundle


At that point, what is tailwind offering?


Again, guard rails on those property sets. You are locked into a set of values and they are unlikely to conflict in some odd way.

You can also apply configuration changes globally that might affect multiple properties. If you're changing from px to rem for sizing, you can do that without having to go through your entire code base to update that. Or if you need to tweak a color, it's applied everywhere, including computed values (color variants).


How is that different than Sass with some of the same classes `items-center`, `flex-auto`, `space-x-3` etc?


Or the utility classes in Bootstrap?


I've been writing CSS since the beginning of the web2.0 days and so it was really hard for me to adjust to the Tailwind approach. It's by no means perfect, but after working almost exclusively with it (and Tailwind UI) I am a big believer. I find myself wanting all the utilities almost immediately as soon as I am back on any other project/codebase.


Yep. Can confirm. It took a while, but I'm sold. Also, the VS Code tooling is excellent.


Tailwind smells like using a style attribute but with properties that are fewer characters. It's fully embracing what everyone said to avoid. What am I missing?


One huge difference is that you can use media queries with TailwindCSS and you can't with the style attribute.

I think the best defense of Tailwind's approach is from Adam Wathan in this post.

https://adamwathan.me/css-utility-classes-and-separation-of-...


I think one key difference is the way people are developing re-usable components now. Since you only define it once, the benefit of re-usable class names isn't as important as co-locating and scoping your CSS for ease of use. You want as little cascading as possible in that circumstance so again, traditional benefits of classes aren't as compelling.

I use a flavour of BEM naming with an approach I call Contexts and Components to achieve concise, low inheritance CSS and I can see how Tailwind can get you similar benefits and solve for some stuff traditional CSS has a hard time solving within frontend frameworks.

I am still fighting picking it up, but that is the use case I see for it, component driven workflows.


I'm a non-designer developer who nonetheless does some frontend work, so with that grain of salt, here's my take:

What everyone said to avoid was actually just wrong. Semantic CSS failed. Tailwind (or utility classes in general) is the best way to implement a reasonably-maintainable and properly-specified version of putting things in the style attribute.


You're likely missing 2 things: 1) you probably haven't delved into Tailwind on a non-trivial project and 2) the nuanced difference is between infinite possibilities (style attribute) vs. discrete, "hard-coded" options (Tailwind classes). Think of strings vs. enum values when describing "types" in an application.


Apologies if this seems snarky but it would be far more useful if you could explain your point rather than a generic condescending "[you] haven't delved into Tailwind on a non-trivial project".


That's a very fair comment, but I do sort of agree with the person you're replying to.

Others here have provided reasons why Tailwind is great, and many comments just center around how it's at least not a bad idea.

But for myself, I read a lot of these arguments before and wasn't convinced until I used it in a fairly big project. To some extent it's hard to explain the benefits because once you get past the more 'ideological' issues (separation of concerns, etc.), it's really much more about how it affects the flow of day to day work. I don't think any arguments would've really convinced me, but because of the excitement around here I gave it a shot, and was convinced by seeing how my project grew without many of the usual CSS issues I'd run into (as well as the convenience of just not having to switch to a stylesheet file most of the time).

But I do understand how frustrating a comment like that can be.


I don't think they were being condescending – there's a lot of material out there on why Tailwind is good, it's easy to find via Google, but nothing beats trying it out.

If you don't want to do that then you could watch some of Adam Wathan's screencasts on YouTube where he uses Tailwind to recreate pages or build new ones.

https://www.youtube.com/c/AdamWathan/videos?view=0&sort=p&fl...


The benefits are "you don't suffer from <some set of problems I've never suffered from, even on large projects>". The cost is cluttered markup and what appears to be impossible reuse.

This smells a lot like every other tech bandwagon. It's the best thing since sliced bread until wide adoption exposes all the flaws and we go back to what proceeded it.


I'm giving myself additional time before I get into it for this exact reason.

Something seems fundamentally off about this library, but I can't pinpoint what.


I dunno. The vibe I get from it is very similar to React. The excitement, the arguments for and against, the focus on some kind of 'separation of concerns' purity that isn't ultimately that convincing.

I waited a while before bothering with React, but based on my positive experience with that particular 'paradigm shift' I gave Tailwind a shot. So far it's been really, really pleasant on a moderately-sized project, so that's hopeful.

I don't see the point in dismissing it, based on all that. We didn't go back from React to jQuery and Backbone, we moved forward from it.

That said, it's fair enough and probably smart to wait and see at this point if you don't have the luxury of experimenting. I totally get that.


It does. Using inline style attributes is basically a good idea when using a component framework, except for missing features and questionable performance. Tailwind solves that.

There is an influential presentation from, i think, someone on the react team that started the whole CSS-in-JS thing. It just advocated for using inline styles. I can‘t seem to find it.

React and Vue have special handling of the inline style attribute to make it more pleasant to use, so it‘s not been fully discouraged for a while.


That was Christopher "vjeux" Chedeau's "CSS in JS" talk:

https://blog.vjeux.com/2014/javascript/react-css-in-js-natio...


Well it is like that, except instead of picking any attribute possible, you're picking from a pre-selected list which have been saved as variables, i.e. utility classes. And it also provides workarounds for the things that inexplicably don't work in inline CSS, like media queries.


What's the problem with style attributes? I would use them instead of regular CSS if I could add pseudo-attributes and make them responsive. Since I can't I use Tailwind where that's possible.


Style attributes have very high specificity so they basically preclude using normal CSS files (they would mandate every line include !important)


This is misleading, !important is not required to use inline styles.

They still cascade normally like CSS classes... see this example:

    <div style="color: red">
      <p>red text</p>
      <p>red text</p>
      <p style="color: blue">blue text</p>
    </div>
Ironically, it's actually complex CSS classes and long selectors that produce high specificity, which then requires even more specificity to override and eventually the dreaded !important


If an element has a style attribute that sets the color, it will override every single CSS/Style-element style that also sets the color, unless the CSS/Style-element style also includes an !important.


The parent is not talking about inheritance. They are talking about specificity.


> What's the problem with style attributes? I would use them instead of regular CSS if I could add pseudo-attributes and make them responsive.

Imagine styling a table row. That is one style attribute. Now imagine styling a 100 tables rows. That is style attribute duplicated a 100 times. Think of the amount of unnecessary bandwidth consumed to load that HTML file with 100 duplicate style attributes. Not only does it slow down page load times, it also slows down page render times.

Now if you add selectors to style attributes then it solves the above issue altogether. But, then you are just re-inventing the wheel. Instead of CSS in a separate file you now have the same functionality but all inlined in style attributes.


That's a good point, but tailwind is primarily suited for component based architectures.

So in this situation you would have a <my-row /> component, which would contain the tailwind classes. This reduces load time as duplication is eliminated, but I'm not sure it would reduce the render time.


The render time point is misleading. It can be slower but even on low end devices, CSS is so insanely fast, you would need an HTML source in the tens of MB's range to cause noticeable performance problems. Also, CSS classes do make that even less of a problem. Inline styles are fast enough, and classes are faster by default, so Tailwind wins there.

Page load times are interesting, but again, unless you're loading an insane amount of data from the server, it will never be a real issue.

Some sort of component architecture solves the problem you bring up w/ duplication. You should never be writing the same thing 100x over. JS frameworks all render 100's of the same component with the same attributes and performance is fine for 99% of real use cases.

The downsides for Tailwind all revolve around personal preference and how your team organizes a project. There is no performance hit (unless you ship the entire un-purged CSS file to production, even then, it's minimal).


> you would need an HTML source in the tens of MB's range to cause noticeable performance problems.

What? Do you ever leave the city? It seems like that’s an unsupported use case any many developers minds.


Okay now I'm growing curious, where in hell do you regularly find HTML sources that weigh tens of MBs?


My point is that it's a problem loong before you reach tens of MB, once you leave the dense cell towers and fast hard links found in a city.


The stockholm-syndrome of the few users positively recommending something that changes their development workflow slightly when they were bored of doing things the old ways.


Ah yes, few users. Which is why this post was on top of HN frontpage.

And yes, definitely it's just that it changed the development workflow slightly, not at all that it brings new possibilities and a much better developer experience.


apart from the many points the other repliers raise, you cant write media queries in style attrs. making precise changes to the exact dom elements for responsive design becomes a great deal less a house of cards with tailwind.


Their marketing is good, they do a primo job at conveying the message in a nice looking way, but the end result is still HTML littered with hundreds classes, that gets hard to maintain and impossible to refactor.


I'm a big fan of Tailwind because I've realized that HTML isn't really maintained and refactored anyways: it's either composed or rewritten. Rarely do refactors happen in the same way as most programming languages.


Depends on the kind of work, for me, in the kind of long-running web software I make HTML is actually maintained or refactored.


For this use case, the "tailwind solution" is to use components, either Angular, React, or whatever, but to pull those "hundreds of classes" into reusable chunks that could be refactored.


I found the promotional video for v2.0 somewhat silly. Epic music taken almost from some Nolan trailer playing in the background for things like "New color palette", "New shades of Gray".

Edit: here's a stark contrast of another promotional video for some tool doing a better job (IMO): https://www.youtube.com/channel/UCaNsjhUdh3BxFL6tzyuhc9g


Framework author here, yep the whole point of the trailer is to be absolutely ridiculous.

The music was custom scored for us by the best man at my wedding, and we had a professional opera singer record all of the chants at the end which are literally "utility first" in Latin.

It's completely outrageous and absurd :) It's the Old Spice commercial of launch videos.


That's literally the point: it's silly.


I used to a skeptic, to the point where I thought it was completely ridiculous. Then I realized that I was over-using inline styles anyway since I was always afraid of messing with old CSS. I was adding layers of overwrites just not to accidentally change something unrelated.

Now I can't imagine myself ever writing regular CSS again. I just love how I can look at the HTML and instantly "visualize" how the component will look just by seeing the classes. No more mysterious cascades where it's hard to pinpoint where the styling is coming from. It makes iteration so fast and responsive design has never been easier.


I use TailwindCSS for some personal projects, works great, no major complaints. But as a dev in the government sector, I'm disappointed in the way they just whimsically dump Internet Explorer 11 in their release notes [1], as if it's a minor thing / cool to hate on.

In my bubble, there's no alternative right now. Switching to a more modern browser requires an enormous amount of agility throughout the pipeline that does not exist. To adopt a shiny new browser, agencies would need to push browser updates to all their client machines every ~4-6 weeks [2]. Solution providers need to perform continuous testing on their web apps (browser vendors do not guarantee minor updates are backwards compatible), creating patches, which need to be submitted to the government for regression testing... and oops that took too long and the next EOL is here.

With Microsoft's surprise obsolescence of Internet Explorer 11 across all its cloud offerings 1Q 2021, we're headed straight into a brick wall. Very interested to see what shakes out here.

I suspect initially we'll see the government just deploy and use older unsupported copies of Chrome/Edge browser, under the guise of "well it's better than IE11 right?". Longer term, ...?

[1] https://blog.tailwindcss.com/tailwindcss-v2#incompatibility-...

[2] Vendors do not support these versions after EOL for any reason. Firefox has an ESR branch, bless them, but some agencies have now increased scrutiny of Mozilla software for recent political/security reasons.


At least now the costs are properly placed on the party responsible for paying them.

Too often users have expected library authors to support obsolete, insecure browsers along with the other maintenance and innovation work they are doing.

Now you're in a situation where you can start applying pressure to force change, since your tooling no longer supports your current environment. That would never have happened if Tailwind just kept paying your costs.


Of course you can still use your current system but with windows 10, most of ie11 users switched to never browsers and current use of ie11 is under %1.5 right now. https://www.w3counter.com/globalstats.php?year=2020&month=10


Whenever this comes up I wonder whether there is an opportunity to create a govt specific browser (based on Chromium initially say) which abstracts responsibility to a specific vendor with clearance ala Lockheed or similar. Web is only going to become more of an a) complex environment and b) normal daily workspace for users so it makes sense in the longer term, and considering the size of market we're talking about, licensing would make it worth it.


> But as a dev in the government sector, I'm disappointed in the way they just whimsically dump Internet Explorer 11

As a dev in the government sector, working for a large public agency, that's pretty much our attitude to IE 11. I mean, sure, staff in our agency need to keep it around for some legacy apps that haven't yet been migrated or replaced, but its being phased out and we're not supporting it beyond making sure that we detect it and put up a banner explaining that its not supported for some of our current (internal and external) apps.


How do they keep the modern browsers up to date? Are these just Internet-connected machines, they take updates, and everyone just hopes for the best?


Flip it: you’re using a browser that is dead and just “hoping for the best” on internet connected machines. If you’re not planning to stay up to date, you’re just hoping for the best.


Something to note: If the update frequency of chrome is too much for you, you can use Firefox ESR [0]. This lets you upgrade major versions less often whilst still getting regular security patches, and it's often used in Linux distros that don't want to ship the latest Firefox.

[0] https://www.mozilla.org/en-US/firefox/enterprise/


Even so, that doesn’t mean everyone else should shoulder the burden of larger css bundles and slower updates. Version 1.9 is still great.


I've gone through the following phases:

1. Write old school circa 2008 CSS.

2. Oh shit, it's a real pain in the ass to do layout and make a responsive grid. Let me use a framework. Sweet!

3. Hmm.. its kinda painful to write css selectors all day long. They're reusable but I am having to get out of comfy JS IDE setup to go change some CSS properties in a different file.

4. Tailwind arrives. OMG. This is awesome! Never have to leave the context. Just stack properties as you like and compose your components!

5. HTML looks completely unreadable. It's a goddamn mess.

6. I want to go back to 2005. No frameworks. Just write non-responsive CSS, one for each screen (yeah, you read that right. I don't want to compromise the layout for responsiveness. I'd rather handcraft one for each device size give or take a few pixels). Custom crafted like a piece of fine art. CSS grid/layout is a lot better with css grid and flexbox. Things have improves since the 960-grid days. No frameworks at all and its fucking liberating.

Edit: I currently use reset/reboot css to clean up default rendering + sass (only use variables + mixins). I am happy like a daisy.


I miss CSS compilers like SCSS/LESS on your vita ;-)

Basically the best way to do CSS I ever worked with was using Bootstrap the LESS way. You could use a sean HTML code with semantic (=speaking) class names and basically do the mapping to bootstrap classes within LESS. This was subsequently compiled to short CSS code. The best of all worlds.

I guess the CSS framework SemanticUI has a similar idea in mind. However, most people use it in the same way as Tailwind. This is web technology as it was done 10+ years ago, when people mixed markup and styling. It's a pity that young folks don't know...


1. this is a pain.

2. i'll write an abstraction

3. the abstraction is a pain


You can use postcss and @apply tag to compose single classes that you can use in your html code like .btn-blue

.btn-blue {

@apply py-2 px-5 flex items-center bg-blue-500 text-white rounded

}

So I don't really see that as a problem. You are supposed to refactor your styles later to be more reusable. What tailwind provides is fast iteration and design. I love that.


The exact problem is the 99% of people who DON’T do this and their markup ends up a Frankenstein’s monstrosity. I don’t know if it’s the new crop of front-end “developers” who don’t know the very basics or just hipsters being hipsters and YOLO all the things. Tailwind (IMHO) promotes bad practices and needs to explicitly state that you SHOULD use @apply or a puppy somewhere will die.


Oooorrrr some of us just don't care what you might think are good practices. I find tossing classes is more maintainable than trying to refactor down.


I'm a FE dev with 10 years experience.

I've only started using Tailwind specifically in the last year or so, but I've been using functional CSS for about 6 years.

I don't believe using @apply is a maintainable approach. A better approach is to use view templates. In fact Adam Wathan recommends this way too in this video https://youtu.be/J_7_mnFSLDg


I think you can blame compilation time for that. If you only use tailwind utility classes, there is no need for recompilation on every change but with @apply directive and external CSS file, the thing gets compiled every time you make a change.

I wonder if they can bypass compilation in development mode somehow.


I second this! I have gone full circle myself. From Dreamweaver (have to start somewhere), hand coding, Bootstrap classes and modifying them, then naturally started using utility classes. Finally made the switch to Tailwind (felt like cheating on a lover, because I loved Bootstrap so much). I then went full on utility classes and low and behold, discovered @apply with nested @screen media queries and went right back to writing clean HTML with named CSS classes that use utility classes in a SCSS file. Its so cool to me, I want to tell everyone about it.


PS: Plus postcss purge. CSS ecosystem is complete!


> Plus postcss purge

What does this mean?


I believe they're referring to https://github.com/FullHuman/purgecss.


Please, tell me more :)


Here is an example off the top of my head, while on iphone:

.card { @apply flex flex-row shadow rounded-md p-4; @screen md { @apply flex-col p-6; } yada... yada... }

then in tailwind config, point the purge path to your html file(s) to purge.

End result is css file with no more and no less than what you need, and in the web inspector you see clean HTML markup and clean CSS declarations.

edit: typo


that's ridiculous, why not just write padding: 2px 5px; display: flex; align-items: center; color: #fff; You are basically just creating a set of attributes that just mimic standard css properties, I find this approach of tailwind absolutely counter productive, and I am surprised that it gets so much popularity.


I think there are two reasons:

- you can copy the classes from html directly into @apply (you need to tinker a bit more to get responsive/hover/etc classes to work, though)

- you work with predefined values, so if you switch color in tailwind.config.js, it's gonna get correct value in the @apply class too.

That's the way I see it


2. which values are you going to ever change in align-center, display-flex and text-color-white, it's not like you will change the display flex to mean display block or align center to mean align start, it will always be the same. Same with color white and 95% of other classes that tailwind uses.


For the second one, couldn’t you get the same effect by just using css variables?


Sure you can and you should, right?

But this way you have to write couple of classes more, couple of variables more. And with Tailwind you just define/change value in the config and you have all the classes generated, so the changes are minimal.


I used to think the same way until i tried it, now i'm completely hooked. it actually makes sense not to extract everything in a "class" simply to separate the presentation out, since that class probably isn't reusable.

plus, it's mostly made to be used with vue/react components which should be small standalone units.

I'm personally looking forward to building websites since using tailwind after a long time


Quick FYI, py-2 is REM based, not pixel. So you know your design will fill properly.


Everybody makes @apply out to be the eventual solution to HTML soup, and a project I'm on uses it heavily—BUT the problem is you're now completely locked into a single framework. You can't ditch Tailwind and still use @apply bg-blue-500. If you used regular CSS properties, design tokens via CSS variables, etc. it would be completely portable. I've switched entire sites from one CSS framework to another and it's challenging but doable with standard approaches. With Tailwind, good luck with that…


Um. The Tailwind compiler produces a plain CSS stylesheet with all the classes you need and none of the ones you don't. You can just dig that out of your build (or wget it from production) and stick it where you normally stick your styles(..!).


That's a single output file compiled down from multiple source files likely using a preprocessor…lol. That's not a solution!


Didn't the @apply tag get rejected from the spec? https://www.chromestatus.com/feature/5753701012602880


I could use sass to do the same.


Yes. You can use tailwind with sass as well though it's not recommended.

Think of tailwind as a framework for all your styling needs while sass is more a functional language to generate CSS for you.


Partially. You'll lose the system Tailwind gives you, which makes it easier to be consistent.


I handcraft that system myself.

It's like buy Ikea furniture and assembling it vs. having your own woodworking shop to handcraft furniture with precise requirements. These frameworks have made me lazy. I think CSS design is pretty much exactly the same as any craftsmanship job - there is so much pleasure from building it from the ground up. No, I still get the knots in the wood out by using reset.css.

Also, I try to not use class selectors as much as possible. HTML looks sterile and spartan with only a handful of span tags or id tags for very specialized targetted changes.

I can see why people use frameworks - its fast and quick. But you lose personality in the outcome.


You mean that @apply tag? https://caniuse.com/css-apply-rule

That is supported by 0% of browsers? Or am I missing something?


you missed reading 'postcss'


This is basically exactly what I get out of writing web components. I get the best of every possible dimension I care about. I can write short neat little snippets of code that encapsulates my HTML, CSS and JavaScript in a single place. I can do it just using really simple CSS because it is all scope, I can actually build reusable components, I’m using the native web platform (though I do recommend lit-element as well) and I can do all using modern tooling and JS and all of the benefits that brings.


Similar curve. I found my optimal trade-off with tachyons.css.


I did the same thing for a recent side project. Only I still use sass.


What benefit does having completely readable HTML offer?


The same benefit as any language you program in. Readability (not saying tailwind is hard, but it can be messy) is one of the most important things I look for.


If you use prettier or similar readability isn't an issue. I'd argue readability is improved since you can tell right away how an element is going to be displayed vs having to open up the css and look there.


What benefit does laying out your circuits cleanly offer? It's pride in your work, a tacit invitation for people who aren't you to look at it. From a functional perspective, does it matter? No, it doesn't really. But it might help you sleep better at night.


Why? Because it makes the document readable... for machines.

You may think about browsers, but if your HTML is a mess, devices that translate content into Braille or read it as audio, won't be able to make sense of it.

That might not sound like a problem, but this might very well cause legal issues in some business cases (e.g. people with an impairment can't access a website of a public administration? That might be a civil rights violation in some countries).

Another reason is because it makes it easier to extract data and information from HTML documents: search engines and search spiders. If your HTML is a mess, you're going to take a SEO hit.

That's just two concrete concerns that come to my mind right now.

HTML and CSS today are mostly used for presentational & interactive purposes: push UI components in there right place, with the desired shapes, colours, fonts, animations and so on, in order to build complex interactive applications.

But HTML wasn't originally conceived for that purpose. The word "markup" says all you need to know. The entire purpose of a HTML tag was simply to describe the structure of a text document: this bit here is the header, that bit is a paragraph, the next bit contains an image, and here are a few meta tags with extra information about the document you're reading.

However, as markets drove demand for more and more interactivity - applications in browsers rather then just static documents - browser technologies including HTML evolved beyond the original scope of "marking up text documents". That original design foundation is still there: marking the content structure of a document through HTML tags, though.

The problem is that developers want to cater to demands to build these nice fancy UI experiences that need to be rendered perfectly on various devices. And so, the original intent of HTML goes right out of the window. What's left is an unreadable mess of spaghetti HTML, mangled DOM's with non-sensical auto-generated CSS classes to which one needs compilers and transpilers and entire toolchains as you write your CSS in an entirely abstracted fashion.

When you're building a complex interactive application for the browser. That's just the current state of affairs one will have to accept. Presently, you're still, in essence, using tools that originally never were designed for that purpose.

However, if you're just going to build a simple blog or a site with static content, it pays dividends to think about the structure of your content, consider the semantics of your HTML and the CSS classes you're going to use. Using pure CSS, you could then easily write lean, performant and understandable stylesheets that don't need to be processed by complex toolchains. And you certainly wouldn't need complex frameworks to build a website.

Of course, YMMV, and so there's definitely a market for Tailwind and their ilk. I do think that developers should learn about "golden hammer" syndrome early in their career: while frameworks make your life as a developer easier, they aren't the best choice in all use cases.

From the perspective of a "body shopping" business, it makes sense to standardize the process as much as possible and fall back to a few well known tools and practices with repeatable - and therefore measurable - outcomes. In the same vain, the big trade off here is providing any form sanity/clarity when someone hits the "browse source" button in there browser.


amen. Not comprompsing layout for responsiveness... things have improved since the 960-grid days. (you've been around!) Amen.


Amen, brother!


The problem I have with pure CSS is it relies on the fact that you and your team are experts at CSS, which is almost never the case. Pure CSS with an unexperienced developer can lead to spaghetti pretty quick. There are always limitations with any approach, including frameworks, but on a team with more than 1 developer and long term maintenance in mind I'd prefer to go with a framework more times than not.


I'm tired of this argument: train your devs for the job you have for them, or if they're not trainable, then find them another position not doing stuff they are incapable of.

We're engineers, let's act like it and know our goddamn stuff, not dumb it down to the LCD.


This feels like the story of a lot of web tooling: accessibility over all else, especially performance/future maintenance. The fail-fast/move fast and break things culture of some startups bleeds into the aesthetics of tools. Knowledge of tools begins to be confused with skills. Ironically, it burdens new devs heaviest, as they're not able to sort through which concepts/abstractions that tools bring with them are worthwhile, and which are not.

It drove me away from the platform entirely.

(This isn't about Tailwind, I've never used it, so I can't comment on it.)


Blame companies and job titles like 'Full Stack Dev'


Looked into tailwind 2-3 times and simply couldn't see the appeal. Working on analytical-dashboards in react, I mostly end up writing css straight in js using material-ui's makestyles. There's only so many components to style before I start reusing them and the css needed to make something 'not-look-too-crappy' is actually quite low.

Now after learning all the css basics, I'd have to learn yet another 'system' again? I think I'll pass.

On the other hand if I'd be constantly restyling webpages with hundreds of different components etc., I might consider it again...


What you're missing is that there's overhead in writing CSS-in-JS. You have to switch context from HTML to JS, you have to keep track of the "link" between your CSS-in-JS and your React component, you have to deal with cascading styles, and hopefully you're able to keep all styles across all components consistent.

Tailwind cuts through all of that and says:

- Just declare the styles you want directly in the HTML

- If you're repeating styles, use @apply

- Limit the number of styles available to your project to enforce a de facto design system


Material UI still fulfills all those points, unless I'm missing something:

- Just declare the styles you want adjacent to the component

- If you're repeating styles, make a component

- material-ui has a design system / theme that you're encouraged to use

Like Tailwind has `class="mb-6"`, mui has `<Box mb={6} />`.


I've seen some incredible things built with Tailwinds, but it still hasn't clicked for me. It seems like you're learning a completely different language for styling and layout. I also have some gripes with optimization in that the suggested solution to eliminating unused CSS is to use a tool that finds classes in HTML files, which is a pretty rudimentary way to accomplish that. (However, I'm sure in more advanced codebases, particularly JavaScript ones, there's probably a better utility to use.)


What kind of projects do people use Tailwind for? and what's the general role of the person using it? I haven't found a use for it myself as a predominantly front-end dev but I've met a few devs who like it a lot but found that they were generally less comfortable writing plain css without a framework. No shade towards Tailwind intended, just not a paradigm I've gotten on board with yet and trying to understand.


I use tailwind with frontend components. I don't think you're actually supposed to keep the atrocious classes as-is all the way to the end. Or for rapid browser prototyping if I want to get a layout up quickly.

For example, my component uses something like this:

.btn-indigo { @apply py-2 px-4 bg-indigo-500 text-white font-semibold rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-opacity-75; }

In the end, I get a <button class="_1aZeRTY"> or similar and that's it, no mess. All of it gets compiled down, and any Tailwind classes I don't use don't make it into the final .js file


We use it for a large enterprise webapp. We have a component library that uses react and applies the correct classes to the component there. I came from mostly using styled-components (CSS-in-JS) and tailwind has worked pretty well for us. The benefit of tailwind over css-in-js is primarily one of performance.

The downside is all styling gets shoved into the `className` prop which isn't great. If I had full automonomy to choose the css "framework" I would probably opt for something like `rebass` https://rebassjs.org/


I built a simple macro/postcss plugin to give tailwind more structure, but preserve runtime performance. https://github.com/fleck/class-types.macro#why-use-this-libr...


I've been using Linaria recently as a zero-runtime css-in-js library. You get a lot of benefits of css-in-js except it compiles it out of the js and into regular css class names and native css perf. Enjoying it so far as I was always cautious of the unneeded overhead of normal css-in-js solutions.


I don't find plain CSS harder to write. It's a bit more verbose and unintuitive to think about sometimes with long-ass property names, too many ways to do the same thing, a bit too low level etc.

Tailwind simplifies them and make those things more readable as well as visible. Combine that with postcss, you get ton of functionality via plugins.

You can use tailwind in any project. The end result is pretty minimal after purging unlike bootstrap or traditional CSS frameworks. Think of tailwind as high level styling framework that simplifies many common scenarios you tackle with writing few lines of CSS.


Any type of project. Before Tailwind existed, I used a similar system but Tailwind is obviously more complete than what I'd roll in a week. I really don't think of it as a framework since you're still specifying which CSS properties you want to apply, just indirectly via classes.


I used it for my site here: https://www.listenaddict.com/

I've also used it for other various sites in the past.

Makes it trivial to add / change / design things quickly, which for me as a non-designer, is great. Also, works well to make things look good on mobile/tablet/desktop sizes, light and dark mode.


For whatever reason, the homepage flashes dark mode, switches to light, but the icon stays a sun. I have to click that twice to get to dark mode and then it works as expected.


Thanks, added an issue to my board to check it out!


If you were instead given a specifc design by a designer, would you be able to use Tailwind only or would there be custom CSS mixed in there to finess it to match the designs?


I would 100% be able to use Tailwind only. And in fact, that would be my preference.

In the past, a lot of projects I've seen started with Bootstrap + maybe some theme. Then they slowly add custom stuff that ended up being horribly bloated and impossible to refactor well. With Tailwind, so long as you're using @apply properly, or a decent component system (I prefer Svelte), then it's very easy to keep things in a nicely updated, non-custom design.


Very interesting. As a Svelte user I find Tailwind counter-intuitive, as the CSS is already scoped to the component. I also found the added build step slows down the otherwise snappy dev server. I had purchased Tailwind UI but got a refund after I ended up needing to write custom CSS on top of the Tailwind classes.

I would be interested in your setup (I generally use sapper).

As an aside, can Svelte reactivity add Tailwind classes? For instance class={`color-blue-${someNum}`} or does all that need to be available at build time (I'm assuming the latter).


That's really cool to hear, that's something I've been a bit confused about since I have to actually dive in to Tailwind. I was unsure how much control you could have from pre-defined classes, but it sounds like it's enough.


You answered your own question, "devs less comfortable writing plain css without a framework"


Nah, I'm very confident with CSS and I prefer functional classes. It's just a far more efficient use of my time to not have to write CSS when there's no need.


I think tailwind is the first thing I’ve ever realized I’m a hipster about. I’ve been using it since early on and bought tailwind UI the instant it came out. I love it.

But now that’s it’s super popular I can’t help but wish it was still a quite little secret. Every other product hunt or show hn seems to be using tailwind with all the default configurations so they all have the tailwind look, just as every new startup used to have the bootstrap look.

And there are so many tailwind UI knockoffs and tailwind tutorials out there it is insane.

I’m super happy for Adam and all the success he and the team are having. Tailwind is a truly great library and now ecosystem.


Forgive me if this comes across condescending or patronising. Genuinely not my intent...

So many people reach for a solution without really understanding their own problem.

I'm talking specifically about maintainable code. And maintainable CSS code at that.

For scaling CSS imagine a continuum with complete isolation one end (BEM, ECSS et al) and complete abstraction at the other (started with 'Atomic CSS', which then spawned countless others including Tailwind).

My experience is that either end of that continuum leads to an approach that can scale well and be maintainable. Mixing of approaches is where people come unstuck because they don't understand why that is problematic.

Understanding that fundamental (more here: https://css-tricks.com/scaling-css-two-sides-of-a-spectrum/) goes a long way to dealing with the problem.

My preference is isolation (which I detailed at https://ecss.io and in the book 'Enduring CSS' about 5 years back — not mentioned to pimp myself, I don't give a hoot if you buy/read)). I like code that is easy to reason about and delete (I like deleting code far more than writing it!) and that suits my mental model.

I also believe our job as a front-end developer is to accommodate designs, not turn around and say, "sorry, we don't have a class for 8px margin, it will have to be 5px or 10px". I'm not suggesting this or that framework can't accommodate this need, just highlighting why I feel the way I do and choose the solution I do.

Think about how __you__ want to build and maintain code. Don't just jump on something because everyone else does. Analyse your problem. Where are your actual pain points. Find the solution to your own issues. Otherwise you'll just swap one set of problems for another.

A framework may very well meet your needs. And by all means listen to others extolling its virtues but that will not save you from a lack of due diligence!

[ends attempting to dispense fatherly advice]


> Incompatibility with IE11, so you can tell the man upstairs "sorry boss it's out of my hands, blame Tailwind"

For those who don't know, IE11 is the last major release of IE. Between a major frontend framework feeling confident dropping IE, and Apple dropping Intel it kind of feels like the end of an era.


Yes, released on October 17, 2013.


I have a Windows 7 machine around that used to run IE 11, but one day it silently updated that to "Edgium", which is great.


So the biggest advantage of tailwind in my opinion is that it enforces some structure in CSS. I work on small, highly custom designed/branded websites (like marketing product sites) often times with bunch of freelancers of differing skill levels that i might have never worked with before. We also often pass the site to someone else to maintain and upgrade after its finished. For my usecase Tailwind has been simply revelation.

If you look at CSS methodologies like BEM, ITCSS, CubeCSS they require developers to learn them and be very disciplined to follow them. These methodologies are probably very effective in orgs where employees work long term. In my case it's always just matter of time before they start to break down. It just takes too much time to onboard devs.

Maybe it's not so much about Tailwind being better or the "right way" but about it making very clear how you should structure CSS (put it in html and tailwind.cofing). Other frameworks like bootstrap also enforced something but Tailwind is not UI kit. It infinitely more customizable it can have any look.

Tailwind creates less technical debt? Maybe that's how to describe it? For others it will be the exact opossite.


Can't wait to upgrade to v2.0. I've used Tailwind CSS/UI very extensively over the last year or more. The time I've saved in my day to day client dev work is incredible. Some of my notable recent projects using the framework include:

https://www.hawking.org.uk (Adam Wathan often uses it as an example of how different sites built in Tailwind can look - https://twitter.com/adamwathan/status/1298932488769875968)

https://www.paced.email (While a bit more Tailwind-esque, the framework has allowed me to concentrate on functionality while knowing the product will look great in the end).

Happy the TailwindLabs team is getting the exposure they deserve. Congratulations folks. Thank you for the awesome tools!


While it may seems like a great idea, I just finished a project for a client on Tailwind.

First of all it's not free, to use UI components it would cost many hundreds of dollars.

But maybe cost is not an issue for all, on the other hand productivity might be.

I found myself terribly less productive, having many classes like:

  <div class="mt-8 mx-4 flex flex-col items-center font-medium text-base ..."
it's very hard to add or remove a rule compared to CSS where each rule is on it's own line.

Also some pretty significant issue for me was hot-reloading taking a lot of time, whereas in CSS you can just refresh linked stylesheet, with tailwind you need to reload complete page, and if your page is hosted on a Django/Symfony/RoR application in development mode, you better have to be patient at each CSS modification !


Can you elaborate on what you mean by "it's not free"? Based on Github, Tailwindcss is open-source and MIT licensed.


There is a project by the creators/maintainers of Tailwind called TailwindUI[1] that is paid. The pricing appears to start at $149 USD which may not be accessible for everyone.

[1] https://tailwindui.com/


I don't get why Tailwind is so hot. Do any of you actually maintain large custom design systems?

Where the same system is used across multiple code bases, with varying components, where you need to be able to accurately replace the look of a component, that might be coded in multiple dev environments (Angular, PHP, React...)?

If so, you would be running away from this approach fast. BEM/ITCSS all the way. How would you globally replace something that is marked up like this (example appears somewhere else in this thread)? How would you assert what this code means across projects?

    class="text-4xl sm:text-6xl lg:text-7xl leading-none font-extrabold tracking-tight text-gray-900 mt-10 mb-8 sm:mt-14 sm:mb-10"
With BEM/ITCSS, you would have a custom namespace like `auk`:

    class="auk-btn auk-btn--primary"
And you can reason about it, maybe in project 2 it is

    class="auk2-btn auk2-btn--primary"
So now you can refactor the old buttons out to replace the new buttons. Good luck with the mess above.

If people say: you can use `@apply`. Yeah. If you write your whole stylesheet in `@apply` logic, why are you using Tailwind at all?

Design tokens and the re-use of design variables is not a Tailwind thing by the way. Some people seem to be acting like it is. We've had variables in Sass for over since 2009. People have been doing clever things with variable maps (arrays) in Sass since forever. There's no way Tailwind can take credit for this.

I've written extensively about why Tailwind is problematic:

(1) https://johanronsse.be/2019/11/11/thoughts-on-tailwind-css/

(2) https://johanronsse.be/2020/07/08/why-youll-probably-regret-...

(3) https://johanronsse.be/2020/08/20/hey-your-api-surface-is-ca...

Don't fall for it! The marketing is sweet but the choice will hurt you in the end.


You globally replace it by putting it in a component. And even if you use ‘@apply’ everywhere, you still get the benefit of design system consistency and faster styling.


You can easily just add a BEM tag for that specific component which has no function but allows you to easily find and replace. This is what I do with Tachyons and Tailwind. I like the ease of building with it, especially for a small startup - https://app.assembl.net and https://assembl.net are both Tailwind.

With the @apply directive, Tailwind components, and dead BEM classes for find and replace, tailwind is a joy - and so maintainable!


I took over a fairly large project which used tailwind v1. Have a low-hate relationship with it.

I like how fast you can do stuff, but when when a designer creates something a bit custom it all falls part really quick.

I understand it solve the issue with reusability and style-guides, but for modern apps that would also mean everything should already be react componentized, so you shoudl not really care about css at that point idealy.

I rather use a mix styled-components (easily extendable if you need something custom) and css-variables for dark mode and defining global variables like colors,paddings etc. Plus I route-split so page only has it's related styles.


Engineers of the world, push back on this stuff! Chances are your designer will want to work with you to make designs fit the tooling used to implement them. It doesn’t hurt to at least try it, ask questions. It does hurt to silently hold grudges and release what you know is suboptimal.


I'd say that tailwinds only works if the designer is on board or if you are not working on pixel perfect specs.


Geeze, this homepage is truly world-class. Props to the Tailwind team!


What homepage? This website makes one of those noob mistakes that many off-domain blogs do, in that their logo doesn't link to tailwindui.com.

I wonder why they used a blog off-domain in the first place. blog.foo.com is so 2005. foo.com/blog makes more sense.


Come on, surely you know I'm talking about https://tailwindcss.com.


Now that you've confirmed it, yes. They have two websites and two home pages: foo.com and blog.foo.com


Re: bloated HTML. Has anyone built a vscode extension that can toggle the style classes on/off?

Would also be cool to hover on a HTML block and see it highlighted in a browser hot-reload view.


I used to like web development some 15 years ago. Ever since frameworks became a thing, I stopped doing any web development. I simply couldn't get myself to setting up a bunch of tools just to process some byzantine file formats to a usable CSS. It was a really great feeling when I discovered Tailwind. Not only building custom, trimmed stylesheets required a single command, everything about using it just clicked. Kudos to people behind it!


Lord, if you tapped out even 5 years ago you still skipped the worst of it. It's relentless, I feel like clean software is hard to find in web development. Web apps are so often written with 5+ different technologies and frameworks all jammed together, and everyone picks a different combination.


1. Tailwind is awesome.

2. I hate the new website, sorry. The old one was clean, focused and clearly portrayed what TW does. The new one is IMHO big, loud, and a lot less focused.

3. I have had endless issues compiling with npm[1], and am using yarn just because of tailwind. Anyone else with this issue?

4. 30 minutes to upgrade is a lot when you manage thirty sites. Though if it is not worth it, no one is forcing me to upgrade.

5. There are some really awesome tools out there that complement tailwind, like tail-animista.vercel.app and tailwind.ink, and some collections like bestoftailwind.com.

6. tailwindui is really nice, and gives the best of both worlds compared to something like uikit.

Partly I feel that the creation of tailwindui took the wind out of the sails of sites like tailwindcomponents.com (of which there are quite a few) which is a shame, since a community can do more than even a dedicated team.

But partly I wish they would filter, organize and promote all the neat tools that there are on tailwindui.

[1]: https://github.com/tailwindlabs/tailwindcss/discussions/1891


> 2. I hate the new website, sorry.

I've spent way too much time trying to find the screencasts that were there yesterday and seemed to have disappeared completely. Now they link to somebody's Youtube Channel. How the hell am I supposed to complete my WorkCation app now?


I'm quite interested in frontend technology and enjoy to take a look at announcements like these. But at the same time my knowledge about JavaScript is extremely limited. So just out of curiosity:

Why is the theme fontSize defined as

    xs: ['0.75rem', { lineHeight: '1rem' }]
rather than something like

    xs: { size: '0.75rem', lineHeight: '1rem' }

?


Tailwind released 2.0, but it is a result of constant work releasing new versions gradually and listening to the users. This is a very active project and it is good to keep an eye on new things https://newreleases.io/npm/tailwindcss. Actually, 2.0.1 is out already. :)


For those using libraries / frameworks like React / Angular / Vue / Blazor / Etc. just try Tailwind. It's awesome and fits very well with component based UI systems.

You will have a slight learning curve, but I recommend you try to learn the classes, style your components without looking at the docs for a week or so, and believe me, your productivity will shoot up, and most importantly, you will start thinking in terms of design, look & feel, rather than how do I encapsulate this in css class.


> Extra wide 2XL breakpoint, for designing at 1536px and above

Is it still common for folks to use pixels in their CSS? I moved to em and the rest around 1999 (I think). What is the reason to stick to pixels?


I think that's referring to screen width. As in, breakpoint for when screen witdth is >= 1536px and as screens use pixels, that is the only unit talking about screens is reasonable in. em/rem/whatever don't make sense in media queries.


I see, thanks y'all.


Most people use rem these days, but there are common browser bugs with using rems or ems in media query rules, so in the rules specifically it is common to still specify pixels, even if the rest of your stylesheet uses rems or ems.


Pixels have always had their uses, but I moved from em to pixels even for sizes that would ideally scale with text in order to be able to get things to align to whole vertical pixels (and horizontal ones, when not centered).


px is still easier and more convenient to reason with, plus it's more readable. I use px in my code but I also use a postcss plugin to convert them to rem during build time


Also the magnificent rem (root em) unit.


Tailwind and utility-first in general is a major win in my book if for one thing only; I don’t have to think about naming my elements at the html level at the start.

Huge speed increase that gives me immediate results. You can absolutely spot and define those names, but you don’t have to think of them up front, allowing you to move forward more abstractly. Readability and maintainability seem like an inefficient nightmare but so far I have felt no pain or burden.

Hats off to the Tailwind team. This is the way.


For anyone who's interested, I put together a repos to bootstrap a react with typescript and tailwind project.

It's intentionally fairly barebones, but I've found it useful to get a wide variety of projects started quickly: https://github.com/figelwump/react-typescript-tailwind-boots...

I've come to love Tailwind, after a few failed attempts at using it. Recommend trying it!


These look like great improvements! I've been using Tailwind one a medium-large solo project and I can confidently say the whole project is MUCH better designed than it would have been without Tailwind, while still looking very custom.

Tailwind is not the one true way to do CSS, but it saves me from myself. I think of Tailwind vs Regular CSS how I think about TypeScript vs Regular JS. I could do everything and more in JS, but I'd make so many more mistakes along the way.


I've been using tailwind for a chess game (https://github.com/JMS55/chessmatch) and so far it's been really good, and the first time CSS has clicked for me. My only complaint is that the html templates can get kind of messy, but that can probably be solved with @apply or splitting the template into pieces.


Can anyone comment on the current state of React Bootstrap versus Tailwind?

There was a relatively recent React Round Up episode where people seemed unconvinced on tailwind: https://podcast.app/rru-react-tools-codebase-management-and-...


We’ll have an entirely new generatiom of front-end developers who don’t know anything about CSS beyond some arbitrary class names soon.


This isn't how you HTML, people! https://threadreaderapp.com/thread/1329156451416244224.html

I don’t have too many programming hills to die on, but taking full advantage of the glory that is HTML5 is one of them. Tailwind is…the opposite of that!


(I have little experience with Tailwind, but I can still make the following argument)

I think you're making a mistake in assuming that the example shows how you should actually use Tailwind in a project.

The creator himself has said that Tailwind should be combined with whatever component-system your framework provides. That's how you can get your semantic tags.

...and it's also how you should write Websites anyways - this has little to do with Tailwind. Tailwind can be seen as just a more powerful way of writing inline styles.

If you rely on CSS for reusable components, you may be in for a bad time as soon as you need to make even a tiny change in your design.


The ol' theory vs. practice…that all sounds fine in theory, but all it means in the end is you've taken a giant wad of dig/span tag soup with 30 utility classes and broken it up into reusable bits of tag soup with utility classes. Or you move everything over to @apply…but now you have a bunch of stylesheets which are completely incompatible with every other CSS framework/build system. It's not a panacea.


Nothing's stopping you from using custom-elements inside your components. (In fact, some frameworks like Aurelia are even built around that). If you don't like frameworks, use Web Components.


I switched from tahyons to tailwinds like 3 years ago and been using it every since on all my React projects. I have tried all the CSS-in-JS stuff etc nothing compares to the dev speed with Tailwinds. Checkout https://42papers.com it's all tailwinds and has a darkmode too.


I occasionally write HTML/CSS, and have always just grabbed Bootstrap, Pure, something. I've briefly looked at TailwindCSS a couple of times and always end up at: where are the some of the common, basic components? It seems like those are paid for items. Am I on the hook to be e.g. a button designer if I don't buy the bundle?


It is still very hard to get it to work with React Native mobile apps. I wish there was an official compatibility package.


Incredible work by Adam and team. I'm using Tailwind from beginning and I have so used to it that I'm not even thinking to go back to whatever Bootstrap, Bulma, etc. It's such a joy to work with TW. Once you try to tinker around with Tailwind there is no back, trust me.


Tailwind 2.0 palette color might be the sexiest on the interwebs, now featuring 50 shades of gray.


Love seeing a promo video on a stylesheet library.. expect to see more marketing on open source


Probably the best invention i added to my tool belt for a long time.

Never was i able to move so quickly to style components in a way that works and you only have to learn one set of keywords. Reminds me a little bit of vim learn once apply everywhere :).

Props to the creators of tailwind !


Half-OT: Are there good UI toolkits out there based on Tailwind?

I read it is really flexible, but I don't want to start from zero. Most of the time I want to throw some pre-made UI components together and then sprinkel them with customizations when required.


Tailwind themselves offer a paid one called TailwindUI[0].

It's still in early access, and I commonly run up against components that are missing and I have to devise a style for myself, but it provides a pretty good starting point for building out a clean looking web app.

[0] https://tailwindui.com/


Pretty nice, thanks!


It's still pretty immature and buggy, so unless you have no problem fixing blocking issues yourself I'll suggest waiting until it becomes more mature.


I don't need it today, but would be nice to have something like that in the future :)


Tailwind UI, by the same authors. But it's a paid product.


CSS/Stylus framework inspired by Tailwind, trying to respect the content semantics https://github.com/holtwick/windy-css


I really think writing component-scoped and BEM named CSS with Tailwind is the sweet spot here.

For example:

  .menu {
    @apply w-full h-12 bg-gray-100 flex flex-row items-center;

    &__icon{
      @apply h-8 w-8 object-fit;
    }
  }


This is an awesome news. Thanks to the team at Tailwind.

I migrated a big-ish project to TailwindCSS about a year and a half. I like it for the fact that I can train juniors to be productive and part of the big project quickly while the experienced developers can graduate to using it as a utility for their styles.

For those worrying about not being able to work on the type scales, etc. I would suggest trying to use Tailwind as your utility and write your own SCSS.

Try this out for your Styles.

1. Includes Tailwind CSS.

2. Create separate components for repeatedly used set of Tailwind classes. See examples at https://github.com/valinorearth/valinor.earth/tree/master/sr...

This is our Startup's website built in the open. A bit overkill but was our attempt to do a multi-lingual Static Site with 11ty + Tailwind + AWS s3 + Cloudfront + Github Actions/CI and other interesting toolsets.

For instance,

  .button {
   @apply inline-block py-2 px-4;
   @apply no-underline bg-water-600 text-white;
   @apply border border-water-600 rounded;
   @apply transition duration-100 ease-in-out transform;
   @apply leading-tight;
  }

For any number of team-size, I suggest maintaining design-tokens in the Tailwind Config. Of course, do post-process your styles with the likes of PostCSS — postcss-import, autoprefixer, etc.

For those asking for simpler CSS/Styles, I believe Tailwind might not be the right one for you. I don’t really write codes these days (quite a few years actually) but I tend to do a lot of marketing landing pages, brochures-types for prospective customers, and throw-away prototypes.

These days, I like the plethora of classless CSS available for me to choose from. I might have even created one for our internal use based off the NordTheme color palette (will try extending it with TailWind). Here are some of them for you to start off - https://github.com/dbohdan/classless-css

I have come back full circle and now just write in plain CSS for the marketing pages. I was once a purist and started with tools such as Hotdog Professional, Ultradev as an IDE.

Tools such as Tailwind has their places and we are standardizing it for all of our websites, customer dashboard, admin, etc. Check out the Tailwind’s own TailwindUI at https://tailwindui.com


Does anyone know how this affects TailwindUI? The paid parts of Tailwind?


For someone who really wants to learn CSS from scratch, is it a bad idea that I start learning CSS by using tailwind?

I am mostly a backend dev and trying to learn UI dev since I need it for some side projects.


My developer co-workers and I have talked about teaching our designers how to code with Tailwind. The designers have no experience with writing code, but I still think its a good idea to start with Tailwind because you'll use many of the best practices and avoid a lot of the historic madness in the CSS world.


Depending on how much time and effort you want to invest, learning how something works will always be more useful than learning how to use it.


Any great alternative to material-ui? It's going to be open core and will make us pay for "advanced enterprise features" like a date range picker.


Wow, the homepage for Tailwind has me excited to try this. I haven't seriously considered using a full on UI framework since early Bootstrap versions :)


Tailwind is great, my main issue when I used it was that I felt restricted by the limited set of sizes. I wish it was possible to use e.g. "m-7px".


Tailwind out of the box is a bunch of really good defaults, but it won't suit all designs, but the essence of tailwind is how it builds it's classes and you can quite easily make your own combinations. See https://tailwindcss.com/docs/customizing-spacing


I tend to just extend the config with whatever sizes I feel that I need.



I think they added a bunch in 2.0, so you may want to double check that.


TailwindCSS is great but I wish it didn't require custom postcss build pipeline. You can use the prebuilt css file, but it lacks some features.


I don't know if it will suit your workflow but Laravel Mix is pretty easy to use. I use it to process my CSS and JS on Laravel and non-Laravel sites.


Anyone using the paid Tailwind? Is it worth the price?


This project is really amazing, so much love


Tailwind is the best "css framework" ive ever used in my entire history of web design / programming.


Using `yarn upgrade tailwindcss` only brought me up to 1.9.6. I had to specify the version to get it to upgrade.


I would assume it's by design. A simple upgrade would potentially break at the very least the colors that you're using (they updated the built-in color palette).


That's understandable, but they didn't clarify that at all in the upgrade instructions, which say to just use "npm install tailwindcss" to upgrade.

edit: And it also broke PostCSS somehow. What a mess!

edit 2: I just noticed the "@latest"


I like the new addition of css grids, transforms and gradients. Now my projects will have literally ZERO css!!


I mean, that’s a damn impressive video. In the moment I totally want to throw out all other CSS and dive in.


I don’t understand a lot of the hate here claiming messy HTML. Partials and @apply and it’s all sparkling.


Is the upgrade enough big to go major?


Always have been a huge fan of Tailwind CSS just for the amount of passion that is clearly behind it. The whole utility-only approach is not for me - I prefer a middle ground with utilities and pre-built component classes. Although I am also building a CSS framework, I can only wish them the best of luck. This update looks freaking amazing!

Edit: Removed link to avoid self-promotion.


Has anyone created a react library that is well maintained with the tailwind framework?


I know the Tailwind guys are working on a project called Headless UI[1]. It's a component library without the styling. There is also Tailwind UI[2], which is more like Bootstrap. Both are official Tailwind projects.

1. https://blog.tailwindcss.com/headless-ui-unstyled-accessible...

2. https://tailwindui.com/components


twin is a babel macro that supports integrating tw util classes with css-in-js libs like emotion


thanks.


I never envisioned a web dev tool would have trailer music like that lol.


Lol... Incompatibility with IE11 touted as a feature is really good.


LOVE tailwind! couldn't have build www.outseed.io without it :)


+1 for the epic battle music in the video trailer.

Solid implementation


Does anyone have any thoughts on Tailwind UI?


I love it. It’s saved me a lot of decision making on my current project.


that video is quite aggressive.


It's so cringe i was thinking thats joke at first.

I guess that happens when you invest and hire some outside help and sometimes it ends up a bit... unsophisticated?

I am big Tailwind user btw.


Framework author here, yep it is a joke. We literally had the music scored for us by a friend with the goal of making it as outrageous as possible. There's a real opera singer chanting "utility first" in Latin at the end. It's a parody of itself :)


I thought its because of your love of heavy metal!


IE 11 is no longer supported :(


IE 11 is no longer supported :)


Windows updates are replacing that with Edge on Chromium, even on "unsupported" systems like Windows 7, so here's that.


Everything in AtOmXpLuS


This is neat. I actually wrote my css similar to this 10 years ago, but was laughed at by "the smart devs". I'm glad to see I was right all along.

Don't let imposter syndrome get you kids, it's a hell of waste of time.


Not sure why I am getting downvoted :/. Just wanted to complement the product and encourage others not to be down on themselves.

I'm going to go commit suicide now. Sorry for bothering any of you.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: