Hacker News new | past | comments | ask | show | jobs | submit login
Tailwind UI (tailwindui.com)
974 points by alt3red on Feb 26, 2020 | hide | past | favorite | 358 comments

Tailwind is fantastic. Everyone goes through the initial shock of complaining about the "ugly markup", the violation of separation of concerns, etc. But I've worked in enough large codebases to tell you that the ones that use Tailwind have a more consistent UI, with much less handwritten CSS. Bootstrap sites inevitably devolve into a soup of custom CSS and Bootstrap framework. You end up with lots of verbose class declarations like "btn btn-link btn-primary btn-xs danger", but you still need lots of little `margin-left: 3px` rules to push and pull things into place. Most other CSS libraries suffer the same fate.

On the other side of things, sites without a framework generally opt for a convention like "BEM" (block-element-modifier). BEM seems to be the worst of both worlds, both abandoning the "cascading" part of "Cascading Style Sheets" and still requiring verbose class names!

I've been working on a Tailwind project for the last six months with a team of around 8 people. We did a bunch of initial work getting the Tailwind config just right and some base styling in place, but since then we've barely written a line of CSS. Yes, the templates are verbose, but they are also incredibly readable and easy to reason about what classes are doing what. On-ramping new people has been easy as well, since they don't have to learn some custom system, instead they can just read the docs on the Tailwind site.

I agree with you about Tailwind, but had to call you out on this:

> BEM seems to be the worst of both worlds, both abandoning the "cascading" part of "Cascading Style Sheets" and still requiring verbose class names!

BEM doesn't abandon the cascade (or really care about it). What BEM is actually pushing back on is rule specificity. For example:

  #navbar a { color: blue }
  /* Can't do this, it doesn't change my navbar-submenu colors */
  .navbar-submenu { color: inherit }
  /* Have to do this as a workaround */
  #navbar .navbar-submenu { color: inherit }
And now I'm in an arms race with myself over rule specificity.

I think BEM is often misunderstood, it's not immediately obvious to beginners why it's helpful. Specificity is one problem it helps solve as you mentioned but the biggest thing for me is it forces you to think about what an element is and who it belongs to.

If someone writes '.nav a' they're saying "select all links inside of nav", but what they really wanted to say was "select all nav menu links, and nothing else", a class like '.nav__link' will never select other links that happen to be in the nav (CTA buttons, logo links, etc) and will survive markup restructuring, something like ".nav > ul > li > a' will not survive minor markup changes as it doesn't express what someone wanted to select in the first place. I think this way of thinking brings a lot of benefits that most CSS frameworks don't give.

> Everyone goes through the initial shock of complaining about the "ugly markup", the violation of separation of concerns, etc.

Hmm, that's not really my main concern. My main initial feeling is that it feels like just as much work as writing plain CSS?

For comparison, I've been using Bulma for a lot of my projects so far, and given that many websites/web apps really don't have any special unique layout, it's covered my use cases very well so far, to the extent that I really don't recognise the anecdote of needing lots of little `margin-left: 3px` rules. (Though a magic number like that would be a red flag anyway...)

The primary benefit that Bulma gives me there is that it's just much less work! I really don't need to throw together some shadows, rounded corners, borders, etc. to make something look like a card, but I can just use Bulma's `card` class, and set some global settings w.r.t. colours and dimensions.

Is there a reason I might be interested in Tailwind still?

>Is there a reason I might be interested in Tailwind still?

Bulma or Bootstrap are ok if you stick to the defaults, but it get's tricky if you work with different fonts, icons and graphics in general, where you often have to make small adjustments to align things.

Everything sits in their own little bounding box and might look off next to another element. Tailwind and other utility based systems with generous enough sizing scales make it easier to make those small adjustments.

Sure you could re-center icons from your icon libraries manually within a design tool and adapt their bounding boxes to fonts this way, but it's a time consuming task.

Personally I think css utils are better suited for layout related stuff, acting more like layout primitives (hbox, vbox) etc since those tend to be pretty ad-hoc.

As far as concrete UI components go, I'm not sure this technique is any better, especially since you often need pretty ad-hoc styling with pseudos etc.

I think if CSS had built-in mixin support you could have the best of both worlds pretty easily, still crossing my fingers we get that some day, would be nice to drop all these build systems.

Did the Tailwind projects use the @apply directive, or just plain Tailwind classes all the way? Asking because I wonder how Tailwind deals with project wide style changes. With traditional CSS you just update the class in one location, with functional CSS you have to hunt down every location where the class was used.

You create components and reuse them.

Agreed, after switching to tailwind, writing CSS became very rare for me.

Hey, is any of you Tailwind UI websites public? Would love to see it!

It just came out. Nobody is using it in prod yet.

Tailwind has been great and I've been looking forward to this for months. I fought Tailwind as a concept pretty hard at first, but after hearing Adam and a few others raving about it I gave it a shot. It takes some getting used to at first but I can't imagine developing without it anymore.

To me, the biggest benefit of Tailwind and utility classes in general is that it removes the cognitive overheard of having to think of class names while designing a new page.

For example, if I'm working on a card and I want some text below the main text to have a smaller, gray font size. What do I name that class? "card-sub-text", "card-sub-title"? No - don't even worry about it - "text-sm text-gray-700" and move on.

Later on, if I end up repeating that combination in a number of places, I have more context of what that class name really should be, and I can extract the utility classes to a specific class name.

Really powerful stuff that has helped to increase my velocity quite a bit.

How is that any different from setting CSS in the style attribute of your tag? What happens when you need to update all the "text-sm text-gray-700" to something else?

Seems like a step backwards at worst and identical to Bootstrap/Foundation at best. Everyone provides class primitives like that

What you're describing offends separation-of-concerns

Tailwind user here. :)

One of the biggest benefits in my opinion is, to communicate the different utility classes to your UI/UX person. By restricting him/her to discrete values for margin, padding, colors, etc. they will not go overboard with there designs and also make the handoff way easier. If you use zeplin for example you can for example define color names in the sketch file and zeplin will show them in their UI. You just click on a text and see "ahh she used text-gray-500".

Much less friction in the workflow.

As for the concerns about messy markup mentioned in some other reply. True that can happen sometimes, but if you use React or Vue, you can encapsulate a lot in components. The markup in the components high up in the tree will look basically the same. And the leaf components should be quite small anyways.

Another really nice benefit to the old way is that you don't have to worry about breaking stuff. When you change bg-gray-200 to bg-gray-300 you can be sure that it only affects the element you have in front of you.

But in the end I think people have to try it out to be able to judge Tailwind.

Concerns are not separated in the first place. Your CSS is heavily tied to the structure of your HTML and you even need to artificially think up structures to be able to write and apply the CSS. I recommend reading Adams blog post on the topic.

Regarding style attribute. You can’t do responsive-ness, hover- or focus-states in style attributes.

It’s hard to compare to bootstrap and the like because they give you components, while Tailwind is just a different way of writing CSS. You can of course extract components, btw, and define stuff like text-primary (that you can change in a central variable).

> What happens when you need to update all the "text-sm text-gray-700" to something else

You update it in the one place (template/render function/component/helper/view/partial) that you wrote it.

> What you're describing offends separation-of-concerns

The entire HTML/HTTP/CSS/Javascript web schmozzle offends separation of concerns and is shot through with layering violations and dependence on the specific rather than on abstractions.

Tailwind responds to that particular shitshow by refactoring style at the point of HTML generation, which (particularly in a template-driven world) makes a crapload more sense than trying to build higher-order style abstractions in a language that was explicitly intended to not be Turing complete.

If the HTML ERB had chosen DSSSL instead of CSS, we wouldn't need this.

When it comes to developer productivity and happiness, composition beats inheritance, even in declarative paradigms.

Typically the "text-sm text-gray-700" would be a one-off styling while I'm developing a page or a component, not necessarily something that will be repeated a hundred times.

If it turns out that later down the line I realize that "every card should have that size and color for the card title", then I'll pull it out to a separate class or part of a partial or something like that.

The idea being at that point then I have more context around when and how that particular section of a component should be displayed, so I have more context about what I should name the class (i.e. "card-subtitle").

I feel like the documentation explains it fairly well if you're interested in reading more about it:


My question is why you cant just name the card and then use selectors to style the title or any other internal styling?

This removes the need to name at all. It can just be .card > h2 or whatever and there you would do your font-weight and color.

Because I don't want that cognitive overhead of even thinking about what the selector should be. Then what if I have another sub-sub text? Do I make that an h3? An h4? I don't want to have to think about that. I just make it "text-xs" and move on.

I don't even need to move over to my css file at all - I stay within my template and stay within my flow.

It seems crazy and counter-intuitive at first, but I find that it makes me a lot more productive.

Something to consider: semantic HTML helps with accessibility.

Yes, but class names doesn't affect the semantics of their tags.

Have to agree. Having to think about the selector makes you think about the structure and make things more semantic.

I have been paralyzed by trying to do things the semantic way before too though. And now no one cares according the markup I venture to look at now and then.

I understand but then why not .card > *:nth-child(1) and then so on down the child list? You could get away with those two selectors to match anything with at least an initial name. No decisions except for the first name.

Some editors like Brackets allows you to edit other files online and handles css specially so you can edit it just by hovering over class names, etc.

This sounds very brittle. What if you want to come back in the future and add another section to the component?

It's different because it's not actually setting a specific style, it's still a semantic description. You would never need to update all the "text-sm text-gray-700" in your project to something else, that just wouldn't make any sense. You might change what "text-sm" and "text-gray-700" (I'd probably go with a more meaningful name for colors, "text-gray-primary" or whatever, but hey) actually do, but you wouldn't want to actually modify all of those to be new classes at once.

In fact, I think this scheme is a whole lot closer to what most developers actually want, which is to have composable classes that actually represent something semantic. "text-sm" is your small text. That should be consistent around your application. If you change what some of that looks like, you probably ought to be changing all of it. If you want a few elements to use a different text size, then go change the classes on those.

I really encourage you to try this out. I was somewhat skeptical, but it truly feels like a huge step forward. Going back to something like Bootstrap/Foundation or- God forbid- BEM feels incredibly painful to me now.

I also don't think separation-of-concerns is a reasonable goal. I read this article [1] after using tailwind for a while, and I agree with almost the entirety of it.

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

Classic question is what happens if you decide to change all gray text with the blue one? Do you end up having the class named text-gray that is setting text to blue, or you search & replace class names...

IMHO search & replace would be the way to go here. Otherwise no one will understand it later on.

But you could also define a color called text-primary, if you are concerned that something like this would happen.

I was turned off to Tailwind at first, but after watching the screencasts[1] the workflow started to make sense. I personally find writing good CSS/Sass from scratch very tedious. For something as "simple" as styling, there are many decisions to make regarding naming conventions, modularization/file structure, specificity, design systems, etc. I almost always opt for pre-built frameworks like Bootstrap or Bulma, but as my projects grew in size, I find myself battling with the framework to customize the components.

I don't think Tailwind is perfect, but find the benefits of consistent naming, easy modifications, and the "instant" design system, more than outweighs the negatives of utility classes. The framework also feels very light since there's no need to preprocess potentially hundreds of Sass files and I can just modify the view template or component directly. PurgeCSS also works amazingly well with Tailwind.

Adam, Jonathan, and Steve are also generous contributors to the opensource community!

[1] https://tailwindcss.com/screencasts/

Reality is more important than technical purity. CSS styles and HTML structure are not separate concerns but tightly integrated in most projects.

Using Tailwind (or other atomic css frameworks) makes it easy to reason about styling while staying completely inside HTML during editing. Within a few days, you quickly memorize all the names and can build complex visuals while also benefiting from the well-designed default sizes and options.

I completely agree with you.

My approach is to use class names, and in a custom stylesheet use tailwind's @apply function, so

.page-section { @apply bg-white rounded shadow overflow-hidden max-w-lg; }

Disclaimer: I haven't used Tailwind. Maybe I'm missing something.

> For example, if I'm working on a card and I want some text below the main text to have a smaller, gray font size. What do I name that class? "card-sub-text", "card-sub-title"? No - don't even worry about it - "text-sm text-gray-700" and move on.

What's the difference with "color: gray; font-weight: 700"? In this case I really don't have to care about the property order, whereas in your case I would guess you still have the cognitive overhead requiring you to know that "gray" comes before "700" (unless it's expected to be preprocessed away? what if I use text-700-gray?).

"text-sm" is just font-size and text-gray is a color code, so the order of the classes doesn't matter either.

The biggest benefit of this over inline styles is that if I decide to change the color of "gray-700", since those colors come from a configuration, I only need to change it in my configuration.

It takes some getting used to of the rules, but after a day or two I don't even need to think about what the class names are.

(Also not a Tailwind user) I guess the common response to this is that well chosen semantic names usually help later down the line after these kinds of changes happen, especially with devs coming in and out.

I've actually come across C code that had "#define ONE_THOUSAND_TWENTY_FOUR 4096" because that was the audio buffer size and later had to be increased to 4096 but the macro name was never changed. AUDIO_BUFFER_SIZE would probably have been a better name in the first place.

Most code is not that bad though, haha. But that is still my first reaction. What if instead of slightly changing the gray color, you now want them to be blue and underlined? Or take HN for example, the username, vote buttons, and timestamp are all #828282, but have different class names. Is keeping this in sync ever a problem in Tailwind? This is only my first time looking at Tailwind, but it seems it's not really meant for "complex" apps where you'd run into these problems often?

If I wanted to change all links from gray to blue/underlined, the best practice there would probably be to use a different utility class (text-blue-500 and underline) and update my templates/partials/whatever.

I think for your specific example, I would use the `@apply` directive to apply certain utilities to all links.

I've used Tailwind on large, complex apps with around 50 screens (so far), and using extracted components or partials hasn't been a problem at all with keeping things in sync.

``` a { @apply text-gray-700; }

// now becomes a { @apply text-blue-500 underline; } ```

The documentation goes over this pretty well, I think.


What if I had two types of links, both of which were currently "text-blue-500 and underline" but I wanted to make one italics at some time in the future?

> The biggest benefit of this over inline styles is that if I decide to change the color of "gray-700", since those colors come from a configuration, I only need to change it in my configuration.

But gray-700 says it's a 70 % gray. Changing it to something else is akin to changing "color: #666" to "color: #444" through redefinition (JS?).

No, "gray-700" doesn't mean it's 70% gray. The term "700" is just referring to a color on a scale. I don't even need to name it "700", I can name it "dark" or whatever I want (which is what previous versions of Tailwind used).

i.e. "text-gray-dark", or "text-gray-700", would have a class with a single css property:

color: #4A5568;

By default Tailwind comes with a default color palette with hand picked colors. They were hand picked by a designer, not determined through an algorithm.


The numbering name system makes it really easy to make incremental changes too. I can’t manually edit a hex to my liking, but I can easily change text-blue-500 to text-blue-600 if I want it a bit darker.

#000000 is black

#FFFFFF is white

They are 3 sets of 2 hex numbers.

#FF0000 is red

#00FF00 is green

#0000FF is blue

(you hear of RGB, Red Green Blue, in that order)

Now if you want a darker color (closer to black) you lower FF to a lower value. A darker blue would for example be #0000AA

if you want a lighter color you increase the other 2 color values. A lighter blue would be #2222FF

If you don't like hex there is rgb(0,0,255) which does exactly the same.

There is also rgba(0,0,255,0-1) with an alpha channel.

You can also put any part of that in a css variable and use it where you like.

body{--foo: 0,0,255,0.5; bar:0,0,100 }

p {background: rgba(var(--foo)) }

div {background: rgba(var(--bar), 0.8) }

Sure, but the colors from Tailwind aren't determined through an algorithm like this. They are handpicked from a designer, which I feel like most design systems do as well.

RGB isn't even a good system to lighten or darken colors. CSS supports HSL which is certainly more intuitive. Then again, it's easier to use a good pre-processor with color functions to darken($color, 10%) and so on (quickly, can you tell me what is 10% lighter than 2222FF off the top of your head?). Still, in the end it makes most sense to use tones from a good color palette then to mess around with hex values.

> I decide to change the color of "gray-700", since those colors come from a configuration, I only need to change it in my configuration.

This sounds like a boldRedText pattern to me [1]. I get the idea of adding utility classes that inherit the base classes, but altering the definition of the "gray" class to be some other color feels wrong.

[1] http://thecodelesscode.com/case/95

gray-700 isn't really 70% gray though, it's a darker gray than gray-600 and a lighter gray than gray-800. It also contains a bit more blue in it, which is actually quite common to do with gray.

In reality I'm pretty sure that you wouldn't alter it directly either and that if you do, you would try to keep the 10 versions of it somewhat linear, or at least consistent with the use that you do of it. Theses colors are there for prototyping quickly yet still offering good looking result. Sure "color: gray" works, but look at the colors choices [1], it's much better than the default gray and offer more choice than lightgray, gray and darkgray without having to do math over #808080.

[1] https://tailwindcss.com/docs/customizing-colors/#default-col...

I have been using tailwind on a new project and I only see 3 real benefits over using inline css styles:

1) Sizes are standardized in a predetermined set of discrete size classes. So you start to think about sizes, padding, margins, etc in terms of steps instead of values. You can change the steps in one place and they apply globally. It's a little easier to standardize a rough style guide compared to starting from scratch.

2) Colors are standardized in a similar way. You just need to configure your app's core colors and then you can just think in terms of steps instead of color values.

3) You have a smaller set of "best practice" means to achieve most outcomes compared to all that's available with css. You don't need to know the best way to do what you want, you can just browse the documentation to find what you want.

Outside of that, you still have to use @apply to collapse utility classes into more semantic classes if you want style changes to cascade (tailwind recommends using components or view partials to achieve this instead of via css classes, though this would work equally well with inline styles)

The styles are very verbose, just like with inline styles. They are only slightly shorter than inline styles since they are basically abbreviated forms of inline styles.

You can still do everything tailwind does for you by using your own style guide and building out css classes, but tailwind gives you a head start.

It feels like it makes you more productive in the beginning because you get a toolset with a lot of decisions already made for you, but I suspect it will make things a bit slower as the app gets more complicated.

I big benefit is that Tailwind supports media queries, while inline styles can't help you at all there.

oh yeah, I forgot about media queries. Which is impossible inline, but also adds to the verbosity

Someone else mentioned this and as I'm not a Tailwind user either, it made me understood a bit more the principle.

text-gray-700 is not a font-weight, it's a color predetermined by the framework. They aren't generated, they are hand picked by a designer. Each addition of 100 is a bit darker.


So essentially, what's the difference between style="color: gray;" and class="text-gray-500" is mostly that you get a more beautiful gray (they add a bit of blue in it).

I guess "text-sm" is also similar, with an hand picked size which appear nice on every device and can be considered "small text".

In that case, isn't that basically style="color: var(--gray-500);" with extra steps? I love to see people experiment for the sake of experimentation, but I'd be hesitant to adopt Tailwind as an engineer unless I understood why they weren't just CSS variables.

They are variables in that they're specified in your Tailwind configuration file, which is what generates the utility classes that are generated. If you really wanted to you, you can extract it out as a variable if you wanted to use that color elsewhere, such as part of a box-shadow or background color or something like that.

  .custom-bg-color {
    background-color: theme('colors.gray.500');

CSS variables are still relatively new though, unsupported until about March 2018 in all browsers, yet the first commit over TailwindCSS is from Jul 20, 2017, nearly a year before browsers even supported the feature. Even today it seems like 11% of users doesn't have support for variables. Could make sense to add support for variables now, but for the sake of backward compatibility, it does make sense to keep it with classnames too.

I love though that as an engineer you would be hesitant to use Tailwind, but you are not aware of how new variables are.

I think Tailwind seems to make sense for any prototypes works and probably even an MVP for a company that still doesn't have a shared CSS that represent the style of the company.

My point isn't that Tailwind should've used CSS variables in 2017, it's that technology from 2017 isn't very compelling in 2020.

> I love though that as an engineer you would be hesitant to use Tailwind, but you are not aware of how new variables are.

Why would you think I'm unaware? Please see: https://caniuse.com/#feat=css-variables

I'm not writing software for IE 11 (released in 2013), Opera Mini, QQ, or Baidu, so CSS variables are widely supported for my target demographic.

For plain old `text-gray-500`, they're pretty similar. One advantage that Tailwind has is screen sizes - you might write `flex items-center justify-between mobile:flex-col` for a row that turns into a column on smaller screens where the UI becomes awkward, for example.

I think the key difference is that you can't use conditionals in style attributes. For example responsive variants, hover, focus, etc.

`text-sm lg:text-lg` is something you simply can't do in style attributes.

`text-gray-700` or `color: var(--mycolor-gray);` is indeed not _that_ much different. (I'm using CSS variables here to achieve the same as Tailwind variables.)

Tailwind also gives you responsive prefixes so if you need different padding on mobile vs desktop it's easy to just use a lg:p-4, for example. You can't do this inline styles.

the 700 is a shade of gray not a font weight

I first took a look at Tailwind CSS a year ago and liked it. However, when I started using its flexbox classes I noticed it was missing one for align-content: space-between (or space-evenly, I can't recall precisely). Thankfully it looks as though those utility classes have since been added [0], however, at the time it made me hesitant to adopt Tailwind because it made me wonder how many other basic property-value pairs were not yet implemented as classes. Maybe that's a stupid reason to have given up on it, but it's just how I felt at that point in time. Do you feel Tailwind has mostly improved with since you started using it?

[0] https://tailwindcss.com/docs/align-content

I've been following this closely. Given the preview with some components listed it seems exceptionally well made: https://tailwindui.com/components

There are also live demos of the app and marketing pages:

1. https://tailwindui.com/page-examples/landing-page-01

2. https://tailwindui.com/page-examples/detail-view-01#

Plus a screencast on how to use it to build these pages: https://vimeo.com/393580241/82c6d7c5f6

Looks good and polished, but that landing page requires 165 KB of CSS, gzipped. That's, to put it lightly, ridiculous.

Yes, but that's just because I think for simplicity they created one large CSS file that is used for all their components and example pages. That's not very realistic. You're not supposed to do it like this for your own project. Instead if you use Tailwind CSS and PurgeCSS I'm pretty sure you would end up with ~10 or 15 kB of CSS gzipped, maybe less.

> You're not supposed to do it like this for your own project.

If even the creator of Tailwind doesn't use Tailwind properly, does anyone?

They are using it properly. It's just that they're using a single css file across all the examples and component pages.

I don't think that's it. Open https://tailwindui.com/css/app.css and Control-F for "placeholder-" -- are there really examples and component pages on this website that set the input placeholder text color to every single different color in the color palette, at every responsive breakpoint?

I'm tired of excuses for inferior tooling. If you truly know CSS, Tailwind is a waste of time.

I've been reading awful takes like this since I started writing software.

"PHP is an awful language, superior developers write in Perl."

"Rails is bloated and slow, making it unfit for any real work."

"True developers don't rely on frameworks, writing all your own code is the only way to be performant."

If you wanna handicap yourself, be my guest.

I've written three or so projects in TailwindCSS, and it lets me create responsive designs quickly. It gives me a very sane set of defaults to build off of. And most importantly, it helps me get a product to production faster than writing raw CSS.

that may be so, but I think it's a valid point to bring up the tradeoffs you're making, including using a non-standard dsl that other designers/developers/hires will likely be unfamiliar with.

personally having written css since I was a teenager, my gut reaction is "eww", but if the team or stakeholders deem it to add value to a project and not affect productivity, sure why not?

The grandparent comment wasn't "bringing up tradeoffs". They literally just said real devs don't use frameworks.

I think it’s not for people who know CSS. It’s specifically for SPAs where site-wide changes are related to component changes and so having to change the html is not that different from changing the css.

I can not force myself to use something like this but I’ve been writing CSS for a long time.

I use BEM and predefined sets of colors and space values to ensure consistency and that’s efficient enough for me.

Quite the opposite. It's a nice set of CSS variables. It still relies on much more CSS knowledge than a framework like Bootstrap.

CSS frameworks are great because there is a flavor that should fit just about anyone.

It seems to require so much CSS knowledge that you might as well just use regular class names and write the CSS components yourself as it requires you to understand how flexbox etc works anyway to use it's utility classes properly.

You're right. Don't use Tailwind if you don't know CSS well.

The use case is for creating Template Components with something like React, Vue, Hugo, Razor or another component template framework. Tailwind offers a large list of customizable variables to use to help keep your CSS consistent. You're still pretty much writing CSS though, just with shortcuts. I consider it Emmet CSS + Variables. I also highly suggest using a plugin for your editor that offers hinting on all the crazy names no matter what CSS framework you use.

If you want a higher abstraction, Bootstrap or Foundation provide that. There is now also this Tailwind UI that you can purchase that would also provide that to some degree.

I thought the anti-css crowd who use React etc generally preferred some form of Styled Components where the style is written in JS? It's a mixed up world of factions :)

Whether building a regular website or a web-app I generally just use component names (like .card) the same way. I'm more of a fan of defined components with limited variations though than people being able to change anything with a lot of utility classes. Sort of like having a succinct API with a constrained depth. I see css as an api to the original designs and Tailwind introduces too much freedom for my comfort! I will endeavour to give it an honest trial though and maybe I will meet you somewhere in the middle.

Styled Components still uses CSS, it just removes the ambiguity and additional abstractions around class names.

This is where I ended up with this framework. It requires so much css knowledge that it is for the advanced but not expert who would be bothered by a number of things.

If you truly know assembler, C/Python/Ruby/Go is a waste of time.

See how dumb that sounds?

Following that analogy, Tailwind is C files that only contain inline assembler blocks.

Yes, you can check off on your list that you no longer have any .S files. But did you actually gain anything?

I can see it now:

> Most C libraries do too much.

> They come with all sorts of predesigned components like functions and structs that might help you move quickly at first, but cause more pain than they cure when it comes time to make your program stand out with custom behavior.

> Tailwind C is different.

> Instead of opinionated predesigned components, Tailwind provides low-level utility macros that let you build completely custom functionality:

    void main() {
        MOV(RAX, 4);
        MOV(RDI, 1);
        MOV(RSI, "Hello world!\n");
        MOV(RDX, 13);
And then every Hacker News discussion of Tailwind C would inevitably include a link to their "Why using Tailwind C is definitely not just as bad as writing inline assembler" documentation page.

Ooh, and then the creator of Tailwind C would start selling the Tailwind C Library, with like an implementation of memcpy that you just cut-and-paste into your program every time you need to copy memory.

I get the sentiment but Python is to assembly as Tailwind is to assembly. It's too far removed.

The leap between vanilla css and tailwind is not large at all.

It’s not a perfect analogy, I will concede. C to assembly is closer. That said...

Assembly: raw html and css C: A framework like Tailwind Python: Components, like TaildwindUI or any of the React components I’ve seen

I think that’s not a bad analogy.

Disagree. Dumb is doing the same thing over and over again and creating new tooling to do the same thing over and over but with added dependencies and frameworks. The fundamentals of web development have barely changed but the flavor of the month way of doing the same thing is constant.

HTML and css are way too low level to be productive in, in my opinion. Especially when dealing with wide ranges of screen sizes, browsers, and platforms. The only way I’m interested in touching the stuff is if there are tools to alleviate the pain.

Caveat: not a UI developer, I’ve mostly done backend work And DevOps for quite some time.

HTML and CSS are too low level? Does such a tool like dreamweaver with response rendering exist?

It's an interesting concept.

I base my comment on the effort required to make a simple web page that a) looks the same across different browsers and devices, b) is responsive, c) supports relatively basic concepts like dropdown menus, columnar layouts, etc...

It’s way too much effort for me to want to mess with, and then you have to repeat the same things for every site you make.

This kind of attitude, while totally relatable IMO as we grow frustrated with massive piles of crapware, is also how we wind up with NIH problems as organizations scale beyond just a few people. There is a very consistent theme by their creators across companies large and small - brilliant, productive, controlling, and eventually fired.

I'm kind of with you on this. We're rebuilding a large internal admin tool with all in house css and components, it's tiny and fast. We didnt want to bring in bootstrap or some other huge framework. Those were fine when I was a jr developer - not anymore

> We're rebuilding a large internal admin tool with all in house css and components,

Why would you have shared in-house css and components? Just write vanilla css right?

Tailwind is that shared in-house css and components for people/team that don't have shared in-house css and components. If you can afford to build one, sure use that!

This is made for prototyping too, this is to get to the MVP quicker. Again, if you have a shared in-house css and components library that does the same, sure use that instead, it makes much more sense!

> Those were fine when I was a jr developer - not anymore

That's a scary sentence. Why do you believe it matter whether you are junior or not to use that library? A library is made to avoid doing twice the works. If you already did that work, you don't need that library, that's for sure, but it's totally unrelated to your level as a developer.

The internet is in a perpetual state of beginner dev tutorials and junior developer tools. I am still waiting for the awesome stuff to come out but it all the same stuff.

I'm sure that in an actual project, you can use tree shaking or a custom build to avoid including components you don't need.

Is there a production-ready CSS purger that's not written in JavaScript? Last time I looked I couldn't find any.

I'm not particularly against JavaScript, but I'm not willing to install and use npm and several hundred dependencies.

All documentation for purgecss always includes postcss and a gazillion other packages I have never heard of.

Maybe something in Go, as a single executable?


still in js, but very fast, ~10KB (min), 0 dependencies, and does not require npm [1]:

however, it expects properly formed html and css; the parsers are quite unforgiving.

(i'm the author)

[1] https://github.com/leeoniya/dropcss/tree/master/dist

Thanks! Properly formed input is not a problem in my case.

I don't know a non-JS CSS purger, but you don't need postcss to use PurgeCSS.


"but I'm not willing to install and use npm and several hundred dependencies"

Good luck being a employable lol

Fortunately, there are many IT jobs that don't include any web work.

For comparison, what is bootstrap v4's weight?

Do these stylistic simple preview images have a name? I have been searching for these for a long time to use in my application without designing them all by my own. A free-to use pack of these would be really great.

"Product Illustration" is what Steve (the designer) calls them. See: https://www.youtube.com/watch?v=1HDR-AV4ODU for a livestream of how he makes them

All of these new frameworks look great, but there just isn't a good way to switch from, e.g., Bootstrap to a new one. I've never come across a framework that had any kind of conversion tool or even a guide on how to efficiently switch.

Jason McCreary from Laravel Shift made a tool called Tailwind Converter which will convert Bootstrap code to TailwindCSS. It's pretty wild. https://laravelshift.com/convert-bootstrap-to-tailwind-css

It converts the css but keeps the markup.

Right now I don't think CSS frameworks are intended to be a drop-in replacement; each one will also introduce a subtle change in style that you have to work with. In theory you can rebuild your application reusing functional components and only replacing visual ones, but it's still going to be a lot of work.

But I think a lot of people wouldn't just replace the CSS framework, they'll rethink the whole UI and everything that goes with it with a big operation like that.

How did you access the page examples? I can't find a link to them on their components page.

They were linked to in a message via their mailing list.

<p class="piew1 piew2 piew3 Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo expedita voluptas culpa sapiente alias molestiae. Numquam corrupti in laborum sed rerum et corporis. Nemo expedita voluptas culpa sapiente alias molestiae" id="Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo expedita voluptas culpa sapiente alias molestiae. Numquam corrupti in laborum sed rerum et corporis. Nemo expedita voluptas culpa sapiente alias molestiae">


When I first learned about Tailwind I though "wow this is amazing!", but it quickly became obvious I was more or less learning another "language", which I really didn't need when re-entering the crazy world of frontend.

I might reconsider it again once I am more comfortable with what frontend has become, but that is still quite a bit away.

I had a different experience – Tailwind made CSS a lot more approachable for me.

A big part of Tailwind's value is that it provides a curated, well-documented subset of the most important CSS attributes. The utility classes are consistently and concisely named (unlike many native CSS properties, which grew organically).

You're totally right that it is yet another abstraction, and that can be tiring. Personally I found it to be well-designed and transparent enough to make it worthwhile.

The documentation alone is great — it helped me learn things about CSS I had been kind of using but had never fully grasped.

100% agree. I learned more about CSS in the Tailwind docs than in all the years I copy and pasted before starting with Tailwind.

Tailwind's draw seems to be in its name -- it helps you work faster. So for people whose bottleneck is writing lots and lots of HTML/CSS, it's probably great.

I'm guessing most of the naysayers here work in the web applications world with component-based architectures, where the HTML/CSS is a small portion of the total time they spend coding, so they can't understand why someone would sacrifice readability, maintainability, and organization for speed on something that isn't a bottleneck for them. The thing is, it absolutely might be a bottleneck for agencies and other companies that need to build lots of custom sites.

> Tailwind's draw seems to be in its name -- it helps you work faster.

And the argument is that this comes at the expense of maintainability.

We ended up painfully removing it from a large frontend project because the custom classes sprinkled everywhere got out of hand and the design started to look more and more inconsistent in a lot of places. Switched to CSS modules (and React components using them) and never looked back.

This is exactly what I'm concerned about at my current location. In a world where it's tough to get anyone to refactor, what's it going to look like after 6 months of use and nobody is creating abstractions into semantic classes?

It seems like if your project is not suited to a "website bashing" or prototyping approach long term, and you need semantic classes to allow for easy theming type use cases, it could be more trouble than it's worth?

It's just CSS classes. You do style="p-4" to make a horizontal padding. It's the simplest thing to learn -- by a long shot compared to most UI libraries everyone has been cooking up lately.

I was experiencing the same thing. I thought it looked really well crafted, but bumped into the same finding as you. Components built on top of it would be great though!

It's really nice, but is there something this pretty for bootstrap?

I literally manage something like 10 different products/websites. And the only way to stay sane and have some pace with features is to use bootstrap for all of them (we currently use bootstrap for maybe 5 of them, and the rest were inherited sites that we're migrating).

I love the look of this but don't have the time or the will to migrate all our sites to learn yet another CSS meta-language with its own sets of concepts and classes.

> It's really nice, but is there something this pretty for bootstrap?

I've always liked the Bootstrap 4 CodeBase theme ($28): https://demo.pixelcave.com/codebase/be_pages_dashboard.php

It's not the same exact look of course, but it has dozens of pages, widgets and components that look clean. It's all well formed code too with ES6 JS, Webpack, etc..

Take a look at the extended license, which you'll be needing in many cases. $999 vs $28, for a single site license. No thank you.

> Take a look at the extended license, which you'll be needing in many cases. $999 vs $28, for a single site license. No thank you.

I don't think the license is worded very well. If you read it as "end user" being a visitor of your site then pretty much every theme on themeforest would cost $999 but that's not the case.

I think what the license means is if you're bundling the theme in with a product you plan to sell and distribute then you need an extended license, unless it happens to be for freelance work in which case a regular ($28) license is fine (the "note to freelancers" clause handles that). If you have a free or paid SAAS app or something like then you can use a regular license too because you're not distributing the theme as a paid product.

I've talked to the author of the theme directly and mentioned using it for a course platform I'm building (end users of the site would be paying for individual courses). He didn't mention needing an extended license for that. He even went as far as giving me permission to release the course platform as open source with his theme included[0].

[0]: What I wrote isn't official for saying you can do the same. I recommend contacting the author directly if you have intent to do that.

Wow, that one is pretty nice... Do you have any experience plugging this into, say, a react app? Fairly simple?

I haven't tried it with a React app but I have used the theme for one of my projects that's using SCSS, Webpack and ES6 JS. The docs are really good and everything is segmented nicely. It shouldn't be bad to get it set up with React.

Tabler is Based on Bootstrap, right?


It says so on its Github page[0]

abler is free and open-source HTML Dashboard UI Kit built on Bootstrap

[0] https://github.com/tabler/tabler

There are many bootstrap themes that offer re-usable components. They are cheap and some are expertly maintained. Look into Color Admin by Sean Ngu.

This is excellent, thank you for the link. Any others you think highly of?

For React Bootstrap there's http://divjoy.com

looks decent, have you used it? any opinions?

I should have mentioned that I created it.. so I'm a bit biased. You can see some opinions in our Show HN awhile back though: https://news.ycombinator.com/item?id=20688044

I remember seeing this earlier, looking forward to the passportjs authentication integration.

Looking forward to getting that in! Which DB do you generally use?

The problem with this IMO is that some enterprising person will just use regular tailwind (or another utility-css framework like tachyons) and re-implement all of these components and give it out for free, circumventing the license and killing the value of this.

Normally with themes it would be time prohibitive to do so, but the nature of utility-css is that it's relatively straightforward to implement each component, even without looking at the CSS that's obviously easy to inspect.

I think what they should do is build a tool that let's you build your entire site using these components and charge for that. Otherwise, I guarantee within a year of today, 2/26/20 there will be a free version of this on GitHub created by the community.


On a side note, if some bored person out there wants to make a huge splash in the CSS community, figuring out a way to target a specific DOM element, create the equivalent of an AST and specify a "dictionary", which would be a utility-css framework (tailwind, tachyons, basecss, etc) and finally reimplement the targeted DOM element in the chosen framework would be amazing.

Assuming you buy into utility-css, that would remove all existing friction in adopting it. Then that would mean you could grab an existing theme [1] and convert it to tailwind components as desired.

1 - https://themes.getbootstrap.com/preview/?theme_id=4231

I use Semantic-UI, which had a problem of finding sustainable funding. There is a community fork (Fomantic-UI), which does not align with my (business) needs: stability, bug fixes, long-term sustainability, rather than adding features left and right and becoming Yet Another All-Encompassing JavaScript-heavy Framework.

Tailwind-UI looks very interesting and I would have no problem paying for it, rather than getting a "free" version, if only for the long-term sustainability. Community projects often go through endless rewrites, and suffer from feature creep and lack of direction.

In a business setting (I run a self-funded SaaS business) I am much more interested in a framework that fixes bugs and is stable.

The only thing that worries me is that the pricing is one-time rather than subscription. How can the authors expect long-term sustainability with a one-time payment? Maintaining a CSS library is a continuous effort, not a one-time thing.

Semantic-UI is a perfect example of the atrophy that I fear with combined CSS and JS frameworks. I'm pretty bullish on utility-CSS (I prefer tachyons since it's much simpler than tailwind). I don't think frameworks should necessarily combine the JS and the CSS. Ideally you would have a competitive market of people selling themes, using utility-css components so you're not limited by framework, and then you can just use your own javascript that you're going to have to use anyway (alpine, react, ember, angular, vue, etc)

I think if utility-css frameworks get popular someone will abstract the components from the frameworks and things like tailwind ui will become unnecessary (rather it will just be utility-css-ui and will work with any css-framework that implements the "interface").

Semantic UI is the perfect example of why you shouldn't go with something that's generic. Unfortunately the project just became too bloated for one person to handle. Your concern about sustainability is a good one and that's exactly why many of the frameworks' authors sell themes. However, themes usually require a lot of work and are difficult to implement using the actual css framework. tailwind ui is different because if you had the theme it's really easy to recreate it because it's utility first.

What's "utility-CSS"? Not having luck googling for it, not familiar with this stuff.

Essentially, utility CSS is a philosophy that promotes having tons of general-purpose classes to apply style rules of extremely limited scope - usually(?) just one rule per class.

It is described in the Tailwind docs here - https://tailwindcss.com/docs/utility-first/

It might happen, but I don’t think it would kill the value. There are tons of free and pretty great UI kits, CSS themes, etc already. Adam Wathan has done a really good job building up a community around Tailwind, and that brand and goodwill is part of the value here, I think.

> There are tons of free and pretty great UI kits, CSS themes, etc already.

There are tons that look visually appealing, but very few I've found that take a component-based approach (where they document each component individually - or think about how they interplay with each other). I've found the CSS is usually muddled, they often have legacy build pipelines that has to be rewritten to fit with Webpack, and a distinct lack of flexibility.

If Adam solves that side, Tailwind UI will be worth the money.

If it causes other theme providers to up their game, even better.

You just can take any bootstrap theme. The component design is the basis of bootstrap.

See https://tailwind.build for something that already exists and knowing the community that surrounds this, he will more than make a good return off it so no worries there for the work that has gone into it. ie. https://adamwathan.me/the-book-launch-that-let-me-quit-my-jo...

I think you're underestimating

a) how hard it is to make a library like this that's any good

b) people will want to support them anyway

$249 (or $599 for a team license) one time is really very little if it does what it promises.

> On a side note, if some bored person out there wants to make a huge splash in the CSS community, figuring out a way to target a specific DOM element, create the equivalent of an AST and specify a "dictionary", which would be a utility-css framework (tailwind, tachyons, basecss, etc) and finally reimplement the targeted DOM element in the chosen framework would be amazing.

This is quite doable for us at Protoship (we've built both a design-to-Tailwind CSS+HTML converter as well as a webpage-to-Sketch Chrome extension). It is a very appealing idea - to be able to recast any webpage into a Utility CSS framework, but I'm curious to hear about situations where it would've been useful in commercial work.

Even if they sell 15,000 licenses in a year, that’s over a million dollars each. Not everything needs to be recurring revenue, they can make a truckload of money In a very short time span.

TailwindCSS is licenced under MIT so I dont' see how creating and selling components created with it could be seen as "circumventing the license".

Tachyons is licenced under MIT too.

The TailwindUI components have their own license.

It's the specific combination of HTML and CSS. That's what you're paying for and that's what is licensed.

I would expect their market is the group of professionals for whom doing that is simply not worth the time.

When your job is delivering high quality UX and there are always more apps to build in the pipeline, having someone give you a library of useful components works.

I have licenses for probably 4-5 of these, and they've all saved many hours of time, and resulted in avoiding the cost of a dedicated designer.

There's inherent value in supporting something with money though, it's likely to actually stick around and improve, rather than some hacky OSS project that will die in a few months.

But isn't Tachyons already on github?

> The problem with this IMO is that some enterprising person will just use regular tailwind (or another utility-css framework like tachyons) and re-implement all of these components and give it out for free, circumventing the license and killing the value of this.

No because I believe that for every enterprising person wanting to circumvent paying for software, there are that many people who want to support the entrepreneurial spirit Adam and company show, and pay for good work. That's what capitalism is suppose to be about at least, anyways.

I wouldn’t bet on that. Most people want things for free and would stole digitized assets if they can go away. In a way what you wrote is true, but I’ll reverse it: for anyone willing to pay, there are many...

Following up on this, it seems like they did quite well.

Capitalism is about making profit. There will be people who feel nice and want to buy this, but it's really not a reliable business model.

Common fallacy. Historically there has been a system of morals that has governed capitalism. Capitalism is about making a profit but also increasing the general welfare. The true capitalist dream is to make tons of money and bring forth great societal good. It's only now where the US has becoming increasingly amoral that we see the "late stage" capitalism we see today.

On the surface, the markup is pretty damn awful. But if you reach certain level of proficiency, this will definitely speed up development.

<div class="lg:flex lg:items-center lg:justify-between"> <div class="flex-1 min-w-0"> <h2 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:leading-9 sm:truncate"> Back End Developer </h2> <div class="mt-1 flex flex-col sm:mt-0 sm:flex-row sm:flex-wrap"> <div class="mt-2 flex items-center text-sm leading-5 text-gray-500 sm:mr-6">

Personally I would prefer Bootstrap over this approach.

It's as if one person was arguing for hard-line separation of style and content, and another person was arguing that in-line is the way to go, and then Tailwind came along and said, "Why not both?"

So now it's the worst of both worlds: an abstraction layer and dirty code.

I think it's a little more subtle than you're saying.

When you use inline styles for everything, you're making the initial development a little faster by making future maintenance and changes a lot harder. (Like, if you decide headings should be italic instead of bold, that's a one-liner fix if you're using CSS properly, but if you're using inline styles you have to individually fix every heading on every page.) So most people have internalized "don't use inline styles for everything" as a general rule.

But if you don't actually care about that sort of future maintenance (or you're charging hourly for it), then using inline styles for everything looks really attractive to you! But you can't literally use inline styles for everything because even non-experts know that using inline styles for everything is bad for future maintenance. So instead you pull in Tailwind so you can say you're using a CSS framework.

I think people that use utility CSS like this will never maintain anything they create. They'll just throw everything away and start over with another framework.

I think that the idea of using well designed CSS rules and classes basically just turned out to not be very useful in the real world (one discussion of the issues: https://speakerdeck.com/vjeux/react-css-in-js)

Or each of your headings is a React/Vue/Web/Polymer/etc component and that's a single edit. Also, sed.

And then the components get bloated to handle logic differences between views of the component, so you went from bloated CSS to bloated components and the need for everything to be a component in order to share a single look and feel.

Once the components get too bloated, you start forking them, and you are back to each page looking subtly different.

Sure, no magic bullet.

Sure. And in that case, just use inline styles (or CSS-in-JS, or whatever else you prefer).

Sure. I view tailwind as a moderate abstraction over inline styles.

"[...] you have to individually fix every heading on every page."

You should have utilized a template engine in the first place. So you'd only have to change the layout/partial/component that is responsible for rendering the heading. Moreover, you could also have extracted the component with css by creating a .title class and using @apply.

But can you realistically change the design centrally of something built only with utility css classes? If the class of an element doesn’t specify its semantics you cannot properly target it in a redesign without updating the markup.

I've never succeeded in that with semantic css either

it would still be a one line fix if you are building with components

Tailwind isn’t the first to take the utility class approach. Atomic CSS was an early implementation of the idea: http://acss.io

It doesn't have to be first to be bad. They can both be bad.

It's not necessarily bad. There are pros and cons to all css approaches. Atomic classes definitely have their fans. It's more a question of which pros and cons matter to you.

uikit as well (the CSS framework, not the Apple thing)

I find that the verbosity is annoying at first, but it makes it incredibly easy to come back to some old HTML and work out exactly what it's doing, and why. Even with Bootstrap, you need to maintain a mental model of what the classes are doing and how they compose, and each custom class adds more complexity to that mental model. Yes, Tailwind has lots of classes, but each class does one thing, so reasoning about the final composition is incredibly easy.

> Tailwind has lots of classes, but each class does one thing

I think this masks a lot of complexity that you have to manage when taking on this approach. And it's not because the approach is good or bad, more what it is or isn't suited for.

The example on the homepage is very slickly presented, but the end result markup is extremely verbose. If I have a Card component, I would like to update them all at once when needed which is what css classes are generally good for. I find BEM naming conventions much more friendly to come back to than markup full of miniature class names.

I had a similar recoil to this approach and then I tried it, and I think they are actually onto something.

Yes, you may have more than one card in your system, but in all likelihood you aren't repeating the HTML for that card more than once, rather you have it in a template of some kind which is called. So while you may have more than one card on your site, you probably don't have the template for it defined more than once. (at least ideally you don't)

For those cases where you do want to extract that code, Tailwind makes that easy to do.

Tailwind is a weird thing and like I said I really thought it was insane at first. But after rewriting a site in it in a few days I have to say it is better than the standard semantic CSS by a mile.

The recommended way to handle components is by using template partials or JS to manage your card component rather than CSS classes. [1]

Though, you can still use BEM with TailwindCSS through the @apply directive. Adam calls the directive a kind of "trick" to get more devs on board with utility-first but it does help a lot of you're used to reasoning about CSS with BEM.

[1] https://tailwindcss.com/docs/extracting-components

My sense is this is for people who do not know css to the level needed to implement BEM. Also, it replaces the cost of knowing css and naming things (class names) with the cost of learning the tailwindcss classes.

I will stick to BEM + colors and sizes maps because this feels almost like using the style tag on each element.

For non-css expert engineers writing spa components, tailwind can be useful.

I can also see that it’s not trivial to mix tailwindcss and scss processors so it’s a no for me.

It has the benefit to limit spacing and color sets to presets but I already do this in my BEM codebase.

what is BEM?

Block-Element-Modifier, a way to structure your CSS. http://getbem.com/

You can work with components too, just use the @apply directive. https://tailwindcss.com/course/composing-utilities-with-appl...

It’s common, even expected, to extract that card into a component of some kind (React, web components, mustache template, etc) so you still only have to update the css once.

Your components often get bloated since you have to account for subtle business logic differences between views.

Isn't that what the container/component split is for? Presentation logic in a container, markup and styling in a component. If you need to reuse the same visual component in logically different contexts you create a new container that mangles the props as appropriate.

Yeah, you can. I've just seen this result in really complicated components. Other styles of CSS naturally separate presentation from html markup generation, so the cost of forking and specialized components is much lower.

Sure, until, you need a variation on that card for some elements, and add some other tailwind classes to the HTML to do it. Everything seems to work fine for a while.

Then you update the styles of the card again but the new styles clash with the ones in those tailwind classes and you end with broken styles in some elements.

Mixing components and utility classes is a recipe for future chaos.

How is that different from any other css? I'd argue any css solution would have this problem with components.

edit: thinking more, you can override classes. So yeah, maybe utility/atomic classes are not as effective here.

No, you just create a new card component and adjust the tailwind classes on it.

Or, if it is a minor change, then conditionally include / exclude a small subset of tailwind classes.

The point is to not write your own CSS, you only use tailwind classes. In this way you can look at the template for each of your components and reason about / edit their style and layout easily.

This exactly. With more traditional approaches it can be very difficult to find exactly what css rules are affecting what elements. Tailwind is more verbose but also requires a lot less context to understand what’s going on.

It also makes responsive styling a lot easier in my experience.

If each class does one thing, what's the advantage over using inline styles?

It's good across projects/teams/job too. You know what everything does. You don't have to learn every btn--rounded--primary thing for every app you work on.

Another reason Bootstrap > Tailwind is consistency & context. Adding the class `alert alert-danger` to a div tells my coworkers that it's an "alert" & it will look like an alert everywhere. If I want to change how alerts look, I change the CSS

With Tailwind you'd have `bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative`. Then I'd have to change my HTML everywhere to update the appearance of alerts & its not always obvious that I'm looking at an alert in code.

> Then I'd have to change my HTML everywhere

Nope. Once you see same (sub)set of classes repeated, you would instead define .alert and .alert-danger using Tailwind's @apply directive, and you now have a single place to change how your `alert alert-danger` looks :)

Isn't that like recreating bootstrap component again? It's just that this time it's not created by default at first

I'd imagine a reusable React component something like:

<Alert type="danger"> Are you sure? </Alert>

Of course this solution would work in other templating engines as well.

The alternative would be extracting css components:

.alert { @apply px-4 py-3 ... }

.alert-danger { @apply bg-red-100 .. }

OK, this:

<div class="lg:flex lg:items-center lg:justify-between">`

Isn't this why we have CSS preprocessors? So we can do:

<div class="description-of-what-this-is">

.description-of-what-this-is { .lg_flex() .lg_items-center() .lg_justify_between(); }

Assuming there's enough complexity beneath the mixins to justify their use -- some of these might just be CSS properties.

You can do this with Tailwind as well: https://tailwindcss.com/docs/extracting-components

// in JS, then build .btn-blue { @apply bg-blue-500 text-white font-bold py-2 px-4 rounded; }

This feature makes it a very progressive library for various stages of development. Inline earlier, then gradually extracting the style for reuse in later stage. Besides, their documentation is really good for one to learn those newer css concept.

In that secenario why even use tailwind? Why not just normal css?

That assumes you have the means, the knowledge, and the time, to go through a build step.

What you find to be clean code might go the opposite way for someone (i.e. why would I use scss if utils are all I need?).

You might work with large scale apps where BEM may make more sense. You might work on a site builder where utils might be better. You might be creating splash pages for marketing purposes where going for element selectors may be enough.

Just use view templates to capture this if you need to reuse.

That's fair. However, it is pretty straightforward to extract these to something reusable using Sass, css-modules, or templating (Handlebars, Nunjucks, React, etc).

So you can move really fast and experiment when you need to, and then extract to something shared when you're ready to DRY it up.

Nobody likes the look of utility css frameworks, but once you use it, it’s tough to go back.

At that point, you're basically just using inline styles. Don't get the real benefit of this library.

You can move those clases into a css file.

button { @apply border bg-white; // ... }

i've grumbled about this, too.

Tailwind recommends PurgeCSS, but i'll plug my own lib here:


i have a specific section on how to handle tailwind's unorthodox classnames:


that is some awful looking css you have there.

The classes are exactly why it shines

I'm really surprised at the negativity in these comments. I'm drooling over how good this looks and can't wait to use it in my projects. $249 is nothing for the craftsmanship you're getting (and future components!). I've been following this project for a while and have seen some of the live-coding sessions--a ton of work went into picking the correct styles and fine-tuning each component.

Looks sexy. But can someone ELI5 why I'd use Tailwind over e.g. a Bootstrap theme? Not trying to be snarky - genuinely trying to understand the advantages.

The idea of utility CSS is that you have to set every single style yourself.

So for a button, you might have a class='rounded shadow p-4', which becomes rounded corners, drop shadow and a padding of 1rem.

On the one hand, you have to do a lot more to code. Instead of just adding class .btn in Bootstrap you would need to add all those classes.

On the other hand, the styles are not all the same as everyone eles's, and you can have different styles for one element if needed. You can have a button that only shares some styles, or a theme that has a lot of complimentary styles.

A downside of utility classes, is that you don't have a base to work off, you have to know what classes would go on a button in order to quickly get something nice.

The solution to that is a numerous collection of Tailwind Components. Copy the styles as ou need, and modify as you need.

Until now, there was no official collection. Some of my favorite collections are at https://tailwindcss.com/components https://www.tailwindtoolbox.com https://tailwindcomponents.com https://www.creative-tim.com/learning-lab/tailwind-starter-k... Forms: https://tailwindcss-custom-forms.netlify.com

But now we have an official collection from the framework creators themselves. Use them as a base, but - by changing a class or two, easily modify them for your project.

Of course, in Bootstrap, you could always have written your own classes to overwrite Bootstraps. That can be much more complex, and usually you wind with side effects. In my experience, the more you deviate from the prebuilt styles in semantic libs such as BS, the more hair you lose.

In addition to the other commenter, if you become more experience, you could roll your own Grid, Flexbox and some utility (like Tachyons CSS) styles.

Utility CSS allows you to change or customize far more flexible in a fast pace environment than Bootstrap.

If you prefer lighter CSS, Tachyons is another option which I found more easier to read even if I have a long classes.

For anyone who hasn't tried tailwind I really suggest that you give it a shot. It's made me 2-5x more productive when styling something from scratch.

Bulma user here. I tried tailwind but it never works for me but the Bulma another hand it works perfectly well.

I finished my frontend work in two days with Bulma. This is someone who had zero experience with front-end development.

Agreed. Bulma is definitely more readable and easier to get your head around.

Have you used Bulma? Wondering how it compares to it. It's tiring to learn yet another CSS library.

It's great there's yet another UI framework on its way. Choice is awesome.

I'm a frontend guy (among other things) and for past 2 years I've been using Nuxt (app server, node.js) and Vuetify (material UI framework for Vue.js). Given what kind of results that stack can (and does) achieve, I wonder if people in the same boat as me (using the same stack) would even attempt to use Tailwind CSS/UI.

Whatever the case is, I'm glad there's a project that's useful and that helps authors finance their effort. Thumbs up!

Judging from all the positive comments in this thread, clearly I must be missing something. This looks horrible to me. Instead of meaningful CSS classes you just get a bunch of small classes that do very small things, which you're supposed to combine until it looks like what you want. How is that better than writing your CSS manually?

(Again, I realise the failure is probably on me. But I don't get it.)

Their argument is that the idea of separating content from presentation was always a lie, and that your JS, CSS, and HTML code is always intertwined. I've found this to be partly true for web apps.

Tailwind is essentially unusable without a build step. You can configure it to make composite classes for common styles (button, card, etc.), but if you buy into their philosophy you'll probably want a component-based design (web components, React, Vue, etc).

It's better than working with CSS manually because you work at a slightly higher level. If it was transformed into a css-like language I would prefer that. As a non-UI expert, I also enjoy having an enumerable limited set of sane choices for most properties.

>if you buy into their philosophy you'll probably want a component-based design (web components, React, Vue, etc).

With tailwindcss or tachyons you get some of the benefits of component frameworks without having to use component frameworks, because you can colocate html & "styles" in regular template based systems and scope sections on a page this way. Great DX if you need to render sections conditionally, e.g. for ab testing.

If you think in sections rather than individual components anyway, which tailwind kind of promotes by design, you don't gain that much with a component framework.

The actual CSS functions like an inverted triangle (see ITCSS) the utility classes access from the html, so you won't have any specificity issues because it's already sorted out by having the CSS in a fixed order.

Another advantage is portability of sections between modern frontend JS frameworks and template based systems, you can just copy and paste things around, which is harder if the information about the styles is separated from the html, and without a fixed inverted triangle like CSS structure.

What if you want every link (from the perspective of the user, not based on the tag type) to have the exact same style? How would you do that without some sort of build step with an atomic unit for a link?

Isn't a section just a case of a component?

You could define the anchor element in the preflight.css file (normlize.css/reset).

Yeah, a section is a component, but in my book it also involves the visible page background where the element is located (you could override the page background with a section color), like a slice of the page.

Fair enough. I'd call that definition a component.

I use Tachyons, which is also utility-based (and, afaik, an inspiration to Tailwind). The primary improvement is that the amount of CSS you need to write is reduced by 90 % or more. Okay, but now you have to write and repeat all these CSS class names, so what have you gained? Not having to write CSS is more than enough for me, but another important thing is that you get all the information you need in one place to see how something is rendered. You also get that with inline styles, but they are much more verbose (at least compared to Tachyon's short class names), and there are some things that you cannot do with inline styles, but can do with classes. But you no longer have to go back and forth between the stylesheet and wherever you are performing your DOM-rendering to get an understanding of what's happening.

Tachyons has truly taken a lot of the pain of writing web applications away for me. It looks kind of ugly in the beginning, but I can't imagine going back to writing oodles of CSS again. Haven't used Tailwind though.

I’m using Tachyons over Tailwind because not needing a build step appeals to me. I vastly prefer the smaller footprint of Tachyons, but I do miss Tailwind’s comprehensive color palette sometimes. I could always manually add it in, but for now I’m sticking to Tachyons’s default colors to keep things simple.

I had that same initial reaction when I first read about Tailwind.

I am now a convert and although it's hard for me to articulate exactly where the magic lies, these are contributing factors:

- You can do the entire thing in HTML quickly, including media queries and pseudo-classes.

- The predefined sizes and other values are granular enough that you can do just about everything with them, but coarse enough that you often get it right in the first shot. In a sense, it's a little like going from drawing a chart on blank paper to grid paper.

- Tailwind intellisense in VSCode shows you the colors you likely need.

Each of these points are tiny and could easily be achieved in another way, but combined they have increased my personal joy in frontend development quite significantly.

The same comment is at the top of every post related to Tailwind. Read this section in the docs and try it out before judging:


The core principle is that you wrap up all UI elements into components. Most frontend and backend/template frameworks allow you to do this. You then verbosely apply the Tailwind classnames to perform styling, staying out of custom .css files all together.

This just seems like inline CSS with less verbosity. Where’s the semantic meaning?

In my experience trying to do semantic CSS just adds a lot of extra cognitive overhead and breaks down in the inevitable requirements churn every project goes through.

I was skeptical of Tailwind too until I actually tried it. It’s one of those things like JSX that defies received wisdom but in real use is very nice.

> In my experience trying to do semantic CSS just adds a lot of extra cognitive overhead.

Do people really struggle with this?

    <div class="hero">
        <h1 class="hero-title">Heading</h1>
        <p class="hero-tagline">Tagline</p>
It far more straight forward just to call something what it is and you can actually read the CSS afterwards.

Sure in a 4 line example it's fine. On a real site with 5 different kinds of hero elements, with some styles in common but a lot of small variations and each with its own responsive behavior it's not so easy anymore. Coming up with good names for things is one of the hardest jobs in programming and this style forces you to name everything.

I've been building sites the way you suggest for 20 years. I also had a negative knee jerk reaction to tailwind. But I had enough of an open mind to try it and now I have no interesting in going back.

> Coming up with good names for things is one of the hardest jobs in programming and this style forces you to name everything.

People say that. If you build stuff in components like you are supposed to you almost always have a server side component or component logic that you will have to name. So you are going to have to start naming things properly somewhere.

You are simply kicking the can down the road.

> I've been building sites the way you suggest for 20 years. I also had a negative knee jerk reaction to tailwind.

It isn't a negative kneejerk reaction. I've worked with sites where they have done similar things to tailwind and it is a nightmare to understand what is going on with the page.

> But I had enough of an open mind to try it and now I have no interesting in going back.

The markup is almost unreadable, it completely defeats the point of what CSS is supposed to do and it creates considerable mental overhead for someone who isn't familiar with it.

But I suppose I shouldn't really expect anything else from other web developers that over the last 20 odd years somehow manage to not understand the tech they are given.

That markup is almost unreadable for you.

And despite your crude last jibe at web developers attracted to Tailwind's model, most competent web developers will be able to quite easily pickup this very sane CSS utility framework :)

>And despite your crude last jibe at web developers attracted to Tailwind's model,

No my jibe was at web developers in general. CSS and HTML are quite simple really. If you actually keep things semantic and build your document properly with appropriate markup ... lo and behold things just work properly.

I can understand the divistush of the past when CSS 1 and 2 were quite limited. However today there is simply no excuse.

> most competent web developers will be able to quite easily pickup this very sane CSS utility framework :)

Sure I can read it. The problem is with things like this is that you are learning how to work with their model that basically doesn't work like CSS is supposed to work.

So you it essentially nullifies your existing skillset and forces you into using their framework. I bothered to actually learn CSS properly and understand the technology and then I have to work with something which basically throws that all out the window and forces me to work how they want me to build stuff. No thanks.

If you think that is a "sane" way of working, I really don't know what to say.

People say that. If you build stuff in components like you are supposed to you almost always have a server side component or component logic that you will have to name. So you are going to have to start naming things properly somewhere.

Sure, so you can do it once and use functional css to define the styles that go with that component right alongside the markup instead of having to maintain another css class name for that component in a separate file, mostly likely with arbitrary and inconsistent padding and margin and font-size values.

If you actually think ahead i.e. don't just start coding straight away you can avoid that. All you are doing is making excuses for not doing your job properly.

You really sound like someone that's never worked on big projects with changing requirements or a big development team.

Well you would be wrong then.

This is so much easier to parse too. If you need more rigidity, add BEM on top then you're good to go.

It's easier to parse but what does "hero" actually do? You need to go digging around in all your stylesheets to figure it out and in most cases actually load up the page and inspect it. That overhead is gone in a functional approach.

If you build things as components as you are supposed to (every backend and frontend framework has been geared around since the late 90s) Your CSS styling should correspond directly to your components (whether they are JS or a MVC partial view). So it should be obvious.

> You need to go digging around in all your stylesheets to figure it out and in most cases actually load up the page and inspect it.

When are you changing CSS and not inspecting the page at the same time? You are going to have to check your work. This doesn't happen if you keep things tidy as you go along. Working in a large team and/or scrum is no excuse for checking-in poor code.

You could also describe it with a comment <!-- hero -->, and/or deduce the structure from the actual html elment order.

You could however the problem is that the comment will invariably will be left after thing have changed and will just cause confusion.

Generally what the code is doing should be fairly obvious and should not need comments. Comments should be reserved where things aren't obvious.

I don't think it is a good idea to create code where it isnt obvious what it does. CSS is relatively simple tbh things really shouldn't be complicated.

It might not work in very large teams without an agreed on working style, but I don't see how it would be a problem in smaller teams or for individuals agreeing on using comments to their advantage.

There are some nice aspects:

- The classes cover many common use-cases and, in some cases, present a simpler "API" than hand-rolled CSS would

- You can eyeball a HTML fragment and get a good idea of how the pieces fit together, compared to the normal approach of needing to work out what each individual class does, and then how they fit together. It's easy to remember what the Tailwind classes are doing.

- It's dumb, but the ability copy-and-paste entire HTML fragments from one place to another and have the styling "just work" is slightly mind-blowing

- Some CSS attributes work oddly depending on the order in which they are applied, or the order of the composition of classes that both attempt to apply the same attribute, and that problem goes away with Tailwind

There are other advantages, but these were all quite surprising to me, because my expectations of CSS have always been quite low.

> It's dumb, but the ability copy-and-paste entire HTML fragments from one place to another and have the styling "just work" is slightly mind-blowing

Not really. styled-components makes this simple if you're using react.

If you have a few minutes, check out a screencast or two from their docs [0]. I was very much in agreement that utility-first looked pretty awful until I saw it in practice.

After watching a few of those I started thinking about how much faster it could be to use these utility classes instead of writing it by hand. Everywhere he adds a few quick classes I was thinking "here I'd be going back to the CSS, hunting for that class name, maybe duplicating it to create a unique variation... and it took him 7 seconds with a utility class. Hm."

Haven't gotten to try it on a project yet but it's on my list.

[0] https://tailwindcss.com/screencasts/

How is that better than writing your CSS manually?

My take is that it's not. It's just a convenient shortcut for those who aren't well versed in CSS.

I see what kind of problem they're trying to solve, but I think it collapses under its own weight the same as complete, closed components do - just later into the project.

Not sure how it'd be on a proper-production level app, but for side projects, being able to just iterate on a single element is pretty neat.

I don't necessarily want to remember 30 different context-specific class names when adding a new link or button on a simple page if I know a bit of syntax I can get exactly what I want, when I want it.

Again, it's very much a project specific choice, but when you're playing and tweaking and having fun with a design (or simply, iterating on one element multiple times), it's a nice library.

That being said, I can imagine a point where once you're happy with a design, there'd be a push to refactor.

I’m with you there. It looks nice, but I don’t want to learn all that css.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact