Adding `--tailwind` flag to

I heard on a podcast episode on Thinking |> Elixir that there could be some TailwindCSS support when generating new Phoenix projects.

I’d love to work on this feature, but before I start slinging code, I’d like some buy-in from the Phoenix team. Are there any thoughts on how Tailwind could be included in a new Phoenix project?

Should this be the default for new Phoenix projects, instead of the included Milligram CSS? I like how Milligram is super easy as a drop-in without really any work to pull it out if you wanted to use a different CSS framework. Literally delete the phoenix.css file and you’re done.

Should this be opt-in via a --tailwind flag on the generator? I’m inclined to go this way, since including Tailwind also has some workflow changes, and several files. Adam Wathan seems to suggest avoiding using Sass when also using PostCSS to avoid some glitches; so I’m also thinking that this --tailwind flag would also not include sass by default and instead setup Sass-like features through PostCSS

  • postcss-import
  • postcss-nested

other thoughts? Also heads up, there’s an in-progress guide for integrating TailwindCSS into Phoenix from the site


I hate Tailwind. It’s overrated. Company I worked for used LiveView and Tailwind for their CSS. They end up with all these small classes in their html templates which leads to a huge copy paste mess. Tailwind doesn’t encourage them to create reusable classes for cross-view components.
Then you have to learn a whole new language, the mapping between Tailwind classes and the actual css. E.g. items-center <> align-items: center. I had then constantly a tab open to find those mappings.
It is also polluting the templates with a huge amount of CSS specific details. Templates become unreadable.
For the next job, I’ll have to ask the company if they use Tailwind…


I actually love tailwind and I appreciate your opinion on tailwind, but I don’t see how your comment adds any value to the question above.

To the question, I don’t think tailwind should be the default. I would like it, but I think it’s too opinionated to be a default.
As an extra option, I’m not sure either, it’s an extra option to support.

Would it be possible to extend the mix task as a separate package so that the support burden doesn’t fall on the Phoenix team?


But why? As you have pointed out in next paragraph:

For me the simpler the tooling (and that implies less moving parts, which mean less flags) the better. Make it easy to add Tailwind (or any other CSS framework in fact) post-factum instead of complicating the project generator. It will be easier and more future-proof when next “big thing” will come after Tailwind.


I want to share some drawbacks before devs decide to adopt Tailwind for their codebase. Reading that it could be somehow integrated into Phoenix, even optionally, personally disturbs me. It will naturally encourage more devs to adopt it.
See then my comment as a vote for: let’s not add Tailwind into Phoenix at all.


I think this type of thing really brings to attention features that exist in other frameworks but don’t here. If we had application template support as a feature (like Rails) this could be a solved problem outside of the official generator, but we’d still have what feels to be native support from a mix usability POV.

It was once talked about but here but ultimately shut down: Phoenix Application Template customization

One thing I learned from working with dozens of teams (freelance dev) and dozens of my own projects is that it’s super handy to start new projects with front-end decisions already made. If no such support is built into a generator, then people end up making custom skeleton / base projects and result in using find / replace to adjust names in a brittle but working way.

Also one thing I learned from having training material that tens of thousands of people use is that it’s not possible to make everyone happy, especially when it comes to front-end decisions. There’s not only bootstrap vs tailwind (and others) but then there’s stimulus vs alpine vs vue vs react too for the JS.

And then there’s LV vs not LV in the Phoenix case.

This story already unfolded in Laravel where they have a bunch of these options built into their official generators (they have a LV alternative tool), and it had pretty mixed results from the community because it ended up being choice overload and it felt like too many opinions and complexity was introduced. So much that the creator of Laravel was getting verbally assaulted online.

Rails seems to have gotten it right tho. Keep the official generator simple enough that out of the box you get a working example but don’t make front-end opinions beyond getting the plumbing set up (webpack, etc.). Where Phoenix differs is the lack of an application template system where the community can easily extend the main generated template with custom stuff.


Rails has lots of front-end integrations in their generator. I think I understand what you’re saying but your example doesn’t seem to line up to me.

The value of adding generator flags is productivity. Saving a couple of minutes to get a project running. Just like the --live flag. That’s the value that a new flag brings. Another example: today it generates with Webpack, but I could appreciate it having an option for Snowpack or esbuild.

I do agree making Tailwind the default may not be best for all projects.


True, I guess they added a bunch of things with the webpacker update. I haven’t generated a Rails project with the default generator in a really really long time. What’s interesting is the docs you linked for Rails avoids listing any options for CSS, it’s mainly JS choices related to webpacker.

What I was trying to say was this decision becomes less important at the official generator level when features like this exist at the framework level. Then it’s really easy for the community to add whatever customizations they want into a generated project in a consistent way instead of resorting to regex based sed / grep replacements and insertions.

Even if --tailwind became an option officially, there’s still many personal decisions related to that set up. Are you going to use SASS or not? Which postcss extensions are you going to use? What tailwind 2.0 color palette do you want to enable by default? Any other custom tailwind config options? Are you going to do the undocumented but working “before / after” include pattern to reduce webpack reload times from 5 seconds to 100ms when you change your CSS? It’s also going to be coupled into webpack since it requires installing JS libraries.


think you can relatively easy abstract those long and reusable lines of (tailwind)classes

I think tailwind out of the box is an excellent choice, especially for beginners where installing npm packages and changing a webpack config can be quite the challenge…


I do this! I use @apply for most styling and then make small tweaks in the templates when they differ in some way from the normal theme.


Whole heartedly agree that we shouldn’t make it part of Phoenix generators.

I think Tailwind is based on an anti pattern and encourages coupling of styling to markup. It is a leaky abstraction and, respectfully, I don’t think as a community we should encourage using it by embedding it into the framework. It should be fairly easy for those who to opt in to paste a line of html and import it from a CDN or install it as a node module.

I REALLY like Elm, but I won’t propose it will be part of the default Phoenix generators, because I know for a lot of projects it is absolutely not the right choice. And Elm can be harder to setup on a new project compared to Tailwind but I still don’t see a justification for that.

At the end of the day it is an opinion to use it and has been a contentious one in a few companies I worked for (not just because of my opinions on it, many agreed that we should not be using it for similar reasons).


If you think tailwind is an anti-pattern - you must have missed the CSS in JS ‘hype’… CSS-in-JS - Wikipedia

Like most, I thought tailwind looked a bit rough - but after only a few hours using it - I have become a convert.

Even the creator of tailwind agrees at first glance it does not look good:

I’ve written a few thousand words on why traditional “semantic class names” are the reason CSS is hard to maintain, but the truth is you’re never going to believe me until you actually try it. If you can suppress the urge to retch long enough to give it a chance, I really think you’ll wonder how you ever worked with CSS any other way.

They have an entire carousel on the tailwind site of testimonials of folks who thought it weird at first sight but once using it recognize its’ potential.

Tailwind lets you make style changes without ever opening a css file. I think most people agree that HTML + CSS + JS all fall into the UI concern category - and as demonstrated with CSS in JS - it is not an anti pattern to mix these together. Tools like alpine take it a step further, and all UI concerns live in your HTML.

I think one lesson from tailwind is that technologies like LESS/SASS are falling out of favour and are being replaced with PostCSS - PostCSS - Wikipedia

The phoenix team should consider adopting postcss + some plugins and removing node-sass + sass-loader. That would make adopting tailwind a lot easier than it is today.

When migrating phoenix to webpack 5, might be worth also tackling this^

Am fighting a bit with a webpack5 + tailwind phoenix setup currently - could make a PR if things stabilize a bit. Might still be too early for webpack 5…

Yea including it in phoenix is probably not the best idea - but making adopting it easier would be nice…


There is a PR for webpack 5, it’s from this post… Upgrade to webpack 5

I can tell the resulting webpack.config.js is more simple.

1 Like

Me thinks you are looking for this link. Upgrade to webpack 5

1 Like

Have you seen webpacker though?

I agree. I don’t see any reason the Phoenix team should devote their time to adding individual CSS frameworks. The same goes for JS. Just let people include their Webpack bundles in the static assets easily like you are supposed to do.

Why is there even a need for Phoenix to “integrate” with any specific CSS framework?

1 Like

I think it would be much better to focus on making the generators as easy to extend as possible. This way people who want things like tailwind or anything else can create the necessary extensions to do that. Unfortunately every time I’ve tried to take a stab at customizing the generators, I get a little overwhelmed. I need to take a week or so and dedicate all my attention to learning how to create my own generators.


I 100% agree, though it’s nice and convenient when people build generators to consider such frameworks it also comes with the cost of maintaining that dependency.

At the end of the day, this all has everything to do with webpack/postcss and tailwind and almost nothing todo with phoenix. If someone wants to make a nice generator or setup wizard for installing postcss and all its dependency along with tailwind into webpack that would be most likely the sole concern of webpack.


I have yet to try this project out myself and unfortunately it does not appear to be open source (which would allow the community to extend it) but I feel it is worth mentioning on this thread, as it claims to provide the ability to generate a new phoenix project with Tailwind and a few other customizations


is there any reason why a Tailwind generator couldn’t be outside of core but a contrib on Hex?