Modern CSS with Tailwind Book Club!

Welcome to our Modern CSS with Tailwind Book Club! :048:

With Tailwind now the default CSS framework shipped with Phoenix we thought this would be a nice book club to run here :003:

The book cub is being led by @BartOtten and participants are:













Everyone is welcome to join in the book club themselves or to simply comment on anything you find interesting :023:

I’m looking forward to hearing how everyone gets on with the book and what everyone thinks of Tailwind - I wonder if we’ll see the common story of “I hate it!” to later “I love it!” that we hear so much of! :lol:


Hey all, I am excited! We are currently started using Tailwind in our first bigger project, and I’m eager to learn more about it! Thanks @AstonJ for organizing the book club!

1 Like

You’re welcome Kevin!

I had a few spares minutes last night so read the intro. It seems Tailwind’s selling points are:

  • You spend less time writing CSS
  • You don’t really use CSS classes (such as button)
  • Instead you use utility classes that map to css, eg m-4 gives you margin: 1rem or text-lg gives you font-size: 1.125rem
  • You can however group a collection of classes for easy reuse, and Tailwind provides an @apply directive for this, however it’s recommended that you use features of your programming language or framework to manage this.


The immediate thought that comes to mind is that you’ll be repeating things - a lot - so every time you want to use something you’ll need to repeat all those utility classes, eg:

<button​ class="bg-green-500 text-white font-bold​ py-3 px-4 rounded-lg text-center">​
  Click Me​ 

Instead of:

<button class="button is-primary">Click Me</button>

Be interesting to see how easy @apply is and how Phoenix helps manage it all.

Look forward to hearing what you all think as you work your way through the book!

I bought a print copy of that book and read most of it.

I think I know enough about CSS already where a “cookbook” style book would benefit me more.

These few sentences get me most of where I need to be:

  • It’s like Bootstrap utility classes, but it’s all utility classes.
  • The JIT compiler reads your source code and spits out CSS based on the classes it saw.
  • Components make it DRY.

So I think I would benefit more from “here’s how to do a common paradigm in Tailwind.”

I think it’s a good book, I’m just not the target audience maybe. I like things like “Elixir for Programmers” (Is that a thing? If not it should be!)


I am working on a project that uses Phoenix as a backend with some administrator functions using liveview and Sveltekit as frontend. I have used Tailwind before but have not learned so much about it, more “copy and paste” from other sources and adjust it for my purpose.
I also picked up the recommendation not to use @apply. In Svelte trying to make js-file with exported string constants that I import in my components. I will try the same in Phoenix.

1 Like

Hi all,

Nice to see this book club going forward! I was and still am eager to read the book, but the flu got me into bed last week. Managed to load the book on my e-reader, just to go back to sleep. Reading while having a short-term memory of less than a minute is ill-advised. And reviewing the book with a bad mood won’t do my opinion any good.

So let me just post my “Introduction”

Why interested in Tailwind?


Being a developer with great interest in UX (I studied it) I have more CSS-skills than most developers. My first website was structured using HTML tables, then came CSS floats and ‘recently’ flex-box and grid. So I am mostly comfortable with just CSS. At times, it can be challenging though.

CSS is hard so let’s use…

I always found it interesting how many developers invest time in 10 languages, but forget the most universal one on the internet: CSS. Just like Javascript, every browser ships with an engine capable of using it. And even when you can write perfect code in X, when not being able to show-off on the web it’s not gonna sell*.

It makes me a bit sad to hear CSS is hard from people who only watched 3 Youtube videos, 5 blog posts and gave up on it. They wouldn’t give up on another language as soon as their first logic mistake would make it cripple.

CSS is like a text book for children: learn letters (meh) → learn words (meh) → learn contextual meaning (nice!). The first steps don’t get you anywhere let alone a dopamine shot to get you exited and carry on learning. However, once you finished all steps, you can be an independent writer and publisher!

Over the decades we have seen many CSS component frameworks and a few utility frameworks to make it easier to style websites. The component frameworks come down to a set of classes so you don’t have to write from scratch. Those are comic books:

A CSS Component framework is like a comic book for children: view pages (nice!), view boxes (event better!), learn sentences (or not). The first steps are already rewarding! Once you completed your journey, you can copy paste sentences from other books as you know the text belong to whatever is in en drawing.

And then we have the utility frameworks. Some are almost languages on their own with conventions, syntax and tooling. The learning curve is told to be better than ‘native’ CSS:

A CSS utility framework is like a icon wall for children: learn icons (meh), combine icons (yeah)! You don’t know any letters, but you can explain yourself by pointing at pictures. Your expression is limited by the icons made available though. It’s okey because you got your dopamine shots! Once you master it, you can express yourself with unique combinations of available icons.

Back to Tailwind

Tailwind is is a utility framework, and once again with the promise to solve anything. It got a hype, Phoenix ships with it…so maybe this time it is the solution…?

  1. does it actually solve anything?
  2. can’t it be solved with native CSS?
  3. how does it scale?
  4. how to keep your app consistent?
  5. …or is it just Javascript guys reinventing the wheel once again because they could not easily use styles in JS. You know, because copying ‘line-height: 1.75rem’ from the browser inspector into JSX won’t work.

I see some club members have already been started; how is the rest doing?

  • some of my libs actually got more used due to having a properly styled demo page…yep, docs don’t count in the first 2 minuters of attention.

I will look forward to hearing what you think Bart!

Btw for anyone interested in getting up to speed with CSS, an article popped up on DT recently which might be worth a read :smiley:

I don’t believe the recomendation is to avoid @apply completely, but rather to prefer using components/partials to componentise an application. @apply is handy when the abstraction cannot be acheived with components.

1 Like

7 posts were split to a new topic: General Tailwind discussion split from Book Club thread

Dear readers,

Although I do love discussing all the things we are about to read, let’s not get ahead of it please. The reason why we read this book is because we want to acquire knowledge! As a result we might post ‘dumb’ questions while we are at chapter 1.

The list with questions I posted was not supposed to be answered by anyone other than the book :slight_smile:

So please, let’s stop discussing the grand scheme of things for now; we can do so later when everyone had read the book.


Good idea Bart :smiley:

I’ve split the discussion into a dedicated thread and moved it here: (it’ll remain open for a month after the last reply, so people are more than welcome to join or carry on the discussion there if they like - just don’t forget to be nice :blush:)

1 Like

Hi, everyone, unfortunately I’m a bit busy this month, so I won’t be able to focus on it as much as I’d like =/
but I started it last weekend.

Even though I had heard about Tailwind, I had never used it or read the docs :sweat_smile:

So I’m taking the club as a opportunity to see how it works and what I can achieve with it.

At the introductory chapter I felt the way the author said I would “ugh” hahaha
Honestly I don’t really like that big amount of classes :sweat_smile:
I was expecting something more like bootstrap maybe…

Then I moved on to the first chapter, I followed the examples, and I might say I changed my mind a bit, I started to get the “feel of it”
It’s kind cool to add classes instead of writing css rules on the components, however I feel this might get messy if I wanna keep a pattern through the whole system.
Well, I guess there’s probably a solution for this.

Waiting for the weekend to continue it =)

1 Like

This is my review of chapter #1. I am a Tailwind noob and still in the predicted “ugh”-phase and this review will likely reflect so.

Chapter 1: Getting Started with Tailwind

Tailwind uses a CLI to extract class names that you use in your code which match certain Tailwind patterns and generates CSS for you based on those findings. It’s does so fairly naive, not checking if the ‘pattern’ is actually used for CSS. My text about m-4 would trigger the inclusion of .m-4 { margin: 1rem;}. The book calls it “set up to run fast” and “not try and guess”.

This seems a bit hacky to me and the authors seems to know the audience as he defends this behaviour (Note the British spelling!) in the next two paragraphs. However, to me, “try and guess” is not the only option for being fast. Treesitter is fast and knows what is what without “try and guess” so what Tailwind does is taking shortcuts / skipping hard parts. And Tailwind class names being “odd enough” and “a few extra accidental classes don’t matter” are not the best point to be made. Even if true, it feels like the author is defending a weak point of Tailwind (CLI) a bit too much.

Adding Tailwind too Your App.

It comes with the disclaimer that this section might be outdated soon, but still it’s good a general overview is provided. It does the job of showing what bolts are needed and is easily adaptable to not React/Webpack apps.

At the end Tailwind modifiers are mentioned and where to place them in the import CSS. As I am still unknown about modifiers, it confuses me a bit as I have no use for that info at the time.

Quick Start

This one got me dazzled and not in a good way. It starts with some very simple HTML which it expanded in the next iteration. Somehow, a class="flex" sneaks in with the second iteration without being mentioned at all. However, that’s only the start. In the next iteration the author really adds some styling to the example saying “The Tailwind classes I’m using do a pretty good job of representing my intend”.

It might be just me, but I see no mapping between intent and the classes at all. “flex” is no intend and how is “order-last” a good representation of “put the logo to the right”? It’s simply the same as with normal CSS: you have your intend and have to figure out how to get to it. Tailwind is doing nothing over CSS in the given example. It then continues to add more classes -which feel like shorthand inline CSS- to the example.

ps. margin: 1rem; padding: 1rem is closer to intend then m-4 p-4 when you want a margin and a padding of 1rem.

Just to finish it off it ends with “but the process didn’t involve us putting a Tailwind class in and being surprised that it affected something on the page we weren’t expecting.” No, no unexpected cascade(!) results but neither would someone have those with inline CSS.

Conclusion chapter 1

This chapter did not convince me in any way. It felt a bit “some things are not good but they are still good cause it doesn’t matter”. It also takes the argument against CSS that is gives unexpected results, but does so with stuff CSS will do just as fine without

  • installation procedure
  • need of a fast parser
  • maybe some accidental extra classes

How about the other readers?

Did they feel the same way about this chapter? Did I miss something important in this chapter which might change my opinion on it? Let me know!


Hey @BartOtten,

thanks for the extensive summary of the first chapter. I was also thrown off by the class=flex but think that is there by accident, because at that point there shouldn’t be any classes in the markup. And I also think, that there could have been a better example for how to show the first use of a few Tailwind classes, for example a simple Button with some styles added one after another to see how to build up the classes.

I didn’t post anything since this book club started, so I want to apologize and add some of my thoughts about Tailwind now.

A while ago I tried Tailwind for a personal prototype of mine, but I didn’t like it and reverted to good old classic CSS after a while. But watching Chris McCords Talk (Timestamped) about the new Phoenix CoreComponents and the default Tailwind classes, it clicked for me. I really recommend the 12 minutes about the Tailwind part of his talk. There will be “class soup” but when you use the benefits of a component framework, then it will make sense and it has a few additional advantages.
We started a project at work and the frontend is using Tailwind. It takes some discipline to put everything in components and not just throw Tailwind classes all around.

I will continue with chapter 2 today and hope that with reading the book to gain some more insights how to use Tailwind more efficiently and productively. Have a nice weekend, everyone!


You’re welcome. I deliberately stayed away from other information sources about Tailwind as I knew this book club would start. So for the time being this book is gonna be my “source of truth” and I will judge Tailwind by it. Not to say that when this book won’t succeed in convincing me I won’t have another look at Tailwind.

This is my review of chapter #2 . I am a Tailwind noob and still in the predicted “ugh”-phase and this review will likely reflect so.

Chapter 2: Tailwind Basics

This chapter starts with a little introduction about the naming of classes in in Tailwind, and how utility class names differ from semantic class names. It then goes on to tell why and how Tailwind can work with large sites.

It lists a few advantages I will not summarize here (you have to read the book!). But one of the advantages is that Tailwind can use “modifiers” to define special behavior for things such as “hover and differently sized screens”. This is impossible with inline CSS. I consider this advantage a knock-out for inline CSS. But this major difference it not mentioned.

Not for the first time, the claim is made that with Tailwind the scope of changes is exceptionally clear. So far there has not been an example to proof how it differs from other CSS solutions. It also mentions the class names of Tailwind being “cryptic” at first; (almost) conflicting with the “The Tailwind classes I’m using do a pretty good job of representing my intend of the first chapter; something I already wrote about.

The first part of this chapter ends with the notion that with Tailwind you can create CSS classes from a list of utilities, but advises to leave it up to the front-end stack you are using (which hopefully already uses some de-duplication pattern)

The second part and third part handle some very basic things like naming convention and reset CSS.


This section starts with the advise given earlier: use whatever you already use to prevent duplication. For React devs this means: create a React component with the styling in it.

This section makes me laugh. Can’t help it but it seems utterly clumsy.

  • For React 3 components are created: Header, SubHeader and SubSubHeader. The next example uses a plain JS function named title to return a list of ultility classes. Let’s apply those to H6: SubSubSubSubSubHeader and subSubSubSubSubTitle()! Guess we are back at “naming things is hard”.
  • Then two examples in Ruby on Rail are shown. One is to create a function (just like JS) and the other one uses an ERB partial saying “the syntax is a bit weird”.
  • Glad there is a solution to all the madness: using the css directive @apply.

What I’ve learned so far:

  • The solution to prevent duplication requires you to come up with names.
  • Creating components/partials can cause code with weird syntax AND you still need to come up with those names.
  • When all gets ugly, you can use @apply…just know you will have to…come up with some names.

I feel like we are going in circles, just so Tailwind can get away with “duplication is not an issue” and “with Tailwind you don’t have to come up with names for your shared CSS properties”.

Glad those names are not CSS names cause those were really hard to come up with according to Tailwind :wink:

Next up: The @apply directive.
Just to make this one clear I copy the code block:

@layer component {
   .title {@apply text, text-6xl}
   .subtitle {@apply text, text-4xl}
   .subsubtitle {@apply text, text-lg}

Looks a awful lot like LESS and SASS, doesn’t it? Except of course the names. These are Tailwind names not LESS or SASS names and certainly not CSS names cause those were ‘really hard to come up with’. :confused:

You might not have noticed, but I am getting sarcastic the more I read. I am not sure if it’s the way the book claims advantages without backing them up with proof (it could have done easily with the inline CSS knockout!) or the fact that I feel like I am directed in circles with the ‘duplications & naming’ issue. All I know is I need a break to clear my mind.

Edit: it just feels to me (so far!) Tailwind has two major advantages: it’s can do things inline CSS can not and it’s short syntax pattern is solid. And those advantages are major already! The rest of the claimed advantages just cause doubt due to them being seemingly in conflict.


Just finished chapter 2.

I see that tailwind was probably thought to be used along with other tecnologies, like react, rails, phoenix… but if the idea is to create a component with TW classes, I could pretty much use plain css that any dev is more familair with.

as BartOtten mentioned modifiers are nice, since that’s not possible with inline css.

Now, something I’d complain about the book is that the examples aren’t that clear.
For ex, in the @apply part the author says to add this:

@layer components {
.title { @apply text-6xl font-bold }
.subtitle { @apply text-4xl font-semibold }
.subsubtitle { @apply text-lg font-medium italic }

but add where? anywhere? am I supposed to run something for it to work?
I had to check the docs to discover…


Hi everyone, just finished chapter 3.
This chapter is about typography so the author shows a lot of utility classes to format text (color, space, size …).
Unfortunately there’s nothing I’d like to highlight…
The next chapter seems more interesting, looking forward for it.

1 Like

Hi again =)
It’s saturday morning and I just finished reading chapter 4.

This chapter is about “the box”, so it’s showed a lot of classes to format margin, padding, borders and so on.

I’d say that after a while you get used to TW’s nomenclatures, and are able to guess the names that will be used to differents utilities.

Well, now I’m kind in the middle of the book, I think it could be nicier if it were a web book, with an online editor, something like w3school, where you could read it and manipulate the examples all in the same page. That would be cool.

1 Like

Speaking of the box, and to higghjack the thread a bit, Every Layout is also a must read and worth the money for the full version: Boxes: Every Layout

1 Like

This would have been my next book if it wasn’t for Aston highjacking my time for a LiveView bookclub. Thanks for the suggestion in this thread!