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 https://github.com/phoenixframework/phoenix/pull/6123. 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

sbennett33
When building a component library, it is often useful to give users the ability to customize the underlying element or component to use. ...
New
beepboop
(re-post of: Feature idea: measure and expose socket latency · Issue #1890 · phoenixframework/phoenix_live_view · GitHub) This is relate...
New
andreamancuso
Hey folks, This might sound niche, but I think it’s worth bringing up - especially given Phoenix’s reputation for being lightweight, por...
New
mortenlund
Hi! I would like to suggest a new callback in the lifecycle of the Live Component which is unmount. Sometimes it is nice to be able to ...
New
Oliver
One common problem we face in constructing lists is that there is (AFAIK) no support for conditionally inserting members into list declar...
New
superchris
Currently there is no out of the box way to support DOM Custom Events in phoenix. I’ve created a separate library to do this, but I’d lov...
New
mxgrn
As one edits a Phoenix LiveView form in a modal, it’s very easy to accidentally press ‘Esc’ and lose all the edits. Similar to data-conf...
New
7rans
I implemented Access behavior for a struct today. Pseudo-code… defmodule MyStruct do defstruct data: %{} @behaviour Access # ... ...
New
dibok
Hi, I’m trying to use phoenix.js in my Qt QML project which has it’s own buildin JavaScript engine. Problem is that (what I googled so f...
New
New

Other popular topics Top

axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
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
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31013 112
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
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
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

We're in Beta

About us Mission Statement