GregPhx

GregPhx

To have 'mix phx.new --no-tailwind' to just do not use Tailwind, but still create basic CSS

Greetings Everyone!!!

A little bit of my background so it could be easier to understand where my comments are coming from, and to take them with a grain of salt…or lots of.

Background

I started coding back in 1989. A few years later I was writing code with VIM in Unix: FoxBase+ and C. So, I am very used to code on a simple and fun programming language, and in a not so fun but powerful language, hence, I am used to allocate memory when needed and freeing it when no longer needed, and yes, I still use Short integers when available: The very first computer I used had 128Kb of RAM, the Tandy Color Computer 3. Some habits are hard to break, and I really want my programs to be thin and light. I am barely starting with Elixir, Phoenix, LiveView, HTML and CSS, thus… I really see no point on using Tailwind. I started using Linux in the mid '90s because I love the freedom it provides, so I totally agree that everybody is free to choose if they want to use certain tool, or not. Everybody is free to chose their poison. No questions asked (my VERY PERSONAL point of view).

Suggestion

Could it be possible to have mix to create code like this:

# === core_components.ex ===
  def modal(assigns) do
    ~H"""
    <div
    [...]

      # WITH Tailwind (Hard-coded styles, I guess)
      class="relative z-50 hidden"

      # WITHOUT Tailwind
      class="sample_modal"
# ===  priv/static/assets/app.css ===
/* Created on the fly WITH Tailwind */
.relative{
  position: relative;
}
.z-50{
  z-index: 50;
}
.hidden{
  display: none;
}

/* Hard-coded WITHOUT Tailwind */
.sample_modal {
  position: relative;
  z-index: 50;
  display: none;
}

Explanation

As of now, it seems like I am being punished for not using Tailwind.

I have a few plain text lines above my form when the put_flash is invoked (:info, or :error) because there are no styles at all, and I have no clue about what styles to use to have those lines to show up as Green/Red pop-ups with CSS.

Either, 1) I will have to study what all those Tailwind classes to know what CSS they are using in order to replicate the basic behavior, or 2) I will have to create another project using Tailwind to get all those classes and then gather the CSS needed to achieve the basic behavior.

Both cases, as I mentioned before, seem like I am being punished for not using Tailwind. As far as I understand the parameter is --no-tailwind, not --no-css.

Best regards,

Greg

Marked As Solved

josevalim

josevalim

Creator of Elixir

Agreed. The built-in CSS for --no-tailwind should cover core components, phx.gen.auth and phx.gen.live. Let’s revisit it later!

Also Liked

garrison

garrison

I was trying to exercise some restraint in not getting into this but since it seems the discussion has drifted in this direction anyway, I’d like to argue in defense of OP and against Tailwind as a default.

I think Tailwind was a mistake - both for the “industry” and for Phoenix. Like many I actually quite liked using Tailwind in the past, but it is fundamentally a degenerate solution. Throwing away standards in favor of a bespoke class generator tool solves some of the problems with CSS, but at the cost of, well, throwing away standards. If you use Tailwind you are always one step behind real CSS - one abstraction layer deep for no real reason. It creates real confusion, like you see in this thread. Also, the classes-in-HTML are a mess - a tired criticism, but it’s still, like, true.

There are two problems Tailwind solves: one is maintainability, which it solves by co-locating CSS styles with HTML. Inline styles almost solve this problem, but they don’t. Tailwind does.

The second problem Tailwind solves is generating a good design system (spacing, colors, font scales) out of the box. Tailwind does this really well, well enough that I think the colors more than anything were the main driver of adoption. The maintainability is a bonus.

The problem, again, is that Tailwind is a degenerate, nonstandard solution. The correct solution to maintainability is scoped styles. Not the scoped styles in the CSS spec, which unfortunately are kind-of useless, but component-scoped styles. In Phoenix, this means scoping styles to heex templates (e.g. function components, views, liveviews, etc).

To my knowledge, the first attempt to implement this with Phoenix was the Surface project. Unfortunately, that project contains a lot of other functionality, much of which was then ported to Phoenix (heex), and I don’t think a lot of people even know about it.

Again to my knowledge, the second attempt was my own. It is actually possible to hack scoped styles on top of Phoenix components by hijacking the heex macros and extracting a <style> tag from the content. I have been using this library to build my own apps for a while now and I can confirm that the approach scales. Note that this library is not production-ready for anyone except me - in particular, the CSS parser was a proof of concept and does not emit useful error messages (and there are some other annoyances). I intend to clean it up for others to use at some point.

Importantly, corp_style (my library) also implements design systems as a set of conveniences for generating CSS variables, with inheritance. This works really well, and combined with component-scoped styles it is a worthy Tailwind replacement.

With this approach the CSS you write is real CSS, with real CSS variables. It’s easy to learn and does not pollute your source HTML (in devtools it just looks like normal CSS). I really feel this is the approach Phoenix should take down the road. It is the framework’s responsibility to implement component functionality, not delegate to Tailwind.

steffend

steffend

Phoenix Core Team

This is included in Augment Tailwind with DaisyUI by SteffenDE · Pull Request #6123 · phoenixframework/phoenix · GitHub. Instead of getting an unstyled application apart from the home page with --no-tailwind, people will now get a fully styled app: phoenix/installer/templates/phx_static/default.css at a37b9179e7ed13b1c367fd9bf9f1a6847a01faa0 · phoenixframework/phoenix · GitHub.

While this is not “basic” CSS - it’s still a very large file created by Tailwind + daisyUI - it is a lot better than no style and it’s basically the “just make it work” approach suggested by @GregPhx.

garrison

garrison

For the record I agree with you, and I think defaulting to Tailwind was a mistake which will have to be rectified some day.

But with that said, the default components are provided mainly as an example to get started. A lot of people are using Tailwind, so they wrote the “example” components in Tailwind.

You can simply remove the tailwind classes and style the components yourself, or write your own using them as an example. Personally, the first thing I do in a new Phoenix project is nuke core_components.ex and import my own :slight_smile:

Nearly all of Tailwind’s classes have very obvious 1:1 mappings with CSS, down to the name - this probably won’t be as difficult as you think. Their docs are also very clear.

Where Next?

Popular in Proposals: Ideas Top

benkimpel
Background I work at a hedge fund and our traders need highly dynamic UIs (think splitters, tabbed panels, tree lists, enormous data grid...
New
tubedude
Hey, Earlier i posted a question, but after some research I think a proposal is due. Working on a Phoenix Live View app, I needed clien...
New
GregPhx
Greetings Everyone!!! A little bit of my background so it could be easier to understand where my comments are coming from, and to take t...
New
iaguirre88
Hi, everyone! Sometimes, you might want to build your app using Phoenix just for the backend and use another tool for the frontend (such...
New
MUSTDOS
Hello all! assign(socket, :name, “Elixir”) Why can’t we have assign/stream take a group of atoms and maps/structs as a default to r...
New
Jskalc
Hi everyone! Recently I was thinking a lot about the way HEEX renders lists. People are generally surprised about huge payloads being sen...
New
manhvu
In a large repo, working with module need to add alias too much is quite annoyed and not good for organizing code. I think better add su...
New
markevans
Hi! I’m excited about everything that’s going on re. gradual typing and am really pleased to see that Jose and the team seem to be think...
New
superchris
Hello! After seeing a couple of posts from Chris and Jose about supporting web components in LiveView, I thought it would be great to ini...
New
bamorim
Story behind Recently, I gave a talk on a meetup about improving performance of Phoenix applications and the example app was a LiveView ...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43591 214
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

We're in Beta

About us Mission Statement