Ha, this was sort of my whole argument about vanilla CSS in phx_new in the first place, without add-ons be is esbuild plugin or adding npm back, it brings more complexity in terms of cross browser stuff whereas Tailwind is dealing with that on their full time. I think argument kinda got lost at one point as I unsuccessfully tried to avoid debating the merits of Tailwind
Quick route check
It was not my intention to imply that certain technology is, or is not, the right tool for a job. I learned a couple of decades ago, the hard way, that that’s a never ending story. Is like arguing about what ice cream is better: Vanilla or Chocolate. It’s a no body wins situation.
My point is that the parameter is --no-tailwind
not --no-css
.
I think you guys are overthinking this. I’ll say it again: I am barely starting to learn, not only HTML&CSS but also Elixir/Phoenix, so very likely my approach is wrong, so … let me explain so you guys could see where I might be wrong.
Propositions
Having Tailwind to create the basic CSS file would avoid the non-trivial maintenance burden.
The “just make it work” proposition.
Whenever mix phx.new
is invoked with the --no-tailwind
parameter, just have mix
to run Tailwind once. The tool will read those Tailwind classes that were left-in as references and will create a basic CSS file.
The “thank you core developers for your effort” proposition.
Whenever mix phx.new
is invoked with the --no-tailwind
parameter, just have mix
to run Tailwind once, and then gather all the classes into an object class.
Let’s say this class in the core_components.ex
file:
class="mt-2 block w-full rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
It would be amazing if that class could be replaced by an “input-25” class, or any other number or name, and gather all the CSS properties under that class!!! Something like:
.input-25 {
display: block;
width: 100%;
background-color: white;
/* lots of properties missing because I don't know them yet */
}
Just a few properties that I recognize, but the idea is to gather all the properties of all those Tailwind classes into a class for that specific object.
Details
Chris McChord mentioned in Elixir, The Documentary that Phoenix is like a “batteries included” framework, thus I think that having a basic CSS file will help a lot to everybody who is barely starting in the Web Development world, like me.
I agree with @tozz, he mentioned that …
I understand that the proposed core_components.ex
file is useless for a lot of experienced developers, it is logic then that programmers just nuke it. Having that in mind I think it would be a lot easier for an experienced developer to nuke the core_components.ex
and the app.css
files than for a newbie guy like me to write the CSS styles from the ground. That will be a real challenge.
Whenever mix phx.new
is invoked, a sample page is created, as of now, with a swirly thing on the right side. That sample home page has a very good amount of Tailwind classes, even though is going to be removed 99.99999999% of the times. Since the life expectancy of that page is very short, very few people cares about the CSS code in that page, even when the project is created with the --no-tailwind
parameter active.
So, if the welcome page looks good even when Tailwind is not used, I think it will be very helpful for all newbies like me to have good looking core components, since it will be very hard for us to have them looking nice. Thus my point, the parameters is --no-tailwind
not --no-css
.
That’s why it sounds logic to me to have Tailwind to run one time to create the CSS file when --no-tailwind
is used.
- The developer won’t use Tailwind while coding, as expected.
- No maintenance burden since Tailwind will create the CSS file.
- Tailwind will improve all the wonderful things people says it does.
- Newbies like me will have a basic CSS for a decent looking web application.
- Newbies like me won’t have the challenge of writing CSS from zero.
- Experienced programmer could clean a couple of files very easy.
Extra
Oh…my…God!!! I have been having a real hard time switching to the Functional Web Development side after +35 years of Imperative programming. It has been a real challenge for me. So, knowing that I am using the same approach José Valim would use, is kind of refreshing. It seems like I am in the right route:
( Thank you José for Elixir!!! Such an amazing tool. )
I am barely starting with HTML&CSS, this is my very first Web app, so I understand I will make lots of mistakes.
:root {
/* Proposed colors */
--app-dark-blue: #0047ab;
--app-night-blue: #1976d2;
--app-board-blue: #292b2c;
--app-blue-night: #000033;
--app-regular-yellow: #FFD700;
--app-golden-yellow: #FFD700;
--app-light-yellow: #FFED4A;
--app-highlight-color: white;
--app-login-shadow: #555555;
/* Application colors */
--main-bg-color: var(--app-blue-night);
--main-fg-color: var(--app-light-yellow);
--second-bg-color: var(--app-dark-blue);
--second-fg-color: var(--app-golden-yellow);
--highlight-color: var(--app-highlight-color);
--shadow-login: var(--app-login-shadow);
}
I am hoping to just change the paragraph with the Application colors to change the whole theme on my app. I hope I can achieve that.
Since I am UI challenged, whenever I have a button that looks good, or just OK, I want all my buttons to look the same. I don’t have the intention to design several button styles, and the same is true for the other objects. Thus, I don’t see a reason to use Tailwind. But, that’s just me. Every body else could use Tailwind if that’s what they want, or to prefer Chocolate ice cream. It’s their choice.
Best regards,
Greg
I had considered prefixing, but other than that and bundling is there anything else that you would be missing without Tailwind or a full NPM toolchain? My impression is that modern CSS and JS have gotten pretty good and can be used mostly out of the box nowadays.
The thing about prefixing and bundling is that they are both actually really simple. Like I said, in order to implement scoping you have to parse a proper CSS AST anyway, so at that point prefixing is trivial. Similarly, bundling is essentially what my library is already doing! It’s bundling the (scoped) CSS found in all of the component templates. Extending this to CSS files would also be trivial - it’s something I’ve considered, but I’m not convinced bundling is useful on the modern web anyway.
The point being, if prefixing and bundling is all you need, I think in the future Phoenix could provide both of those things, out of the box, in Elixir. We don’t need a node toolchain at all!
Of course, I was trying to avoid it from my very first comment. But I think we all knew it was inevitable…
Since you are new to CSS, you have not yet had a chance to experience the problems that Tailwind solves. Once you have maintained a large codebase with many components and styles you will find that it becomes quite difficult to keep track of the styles and class names at scale. You will also find that you have to be careful to build “design systems” from the beginning and stick to them, or things will diverge quickly across your app.
These are the problems that Tailwind solves. Now Tailwind is obviously not the only solution to these problems, and that’s what we’ve been discussing.
Not really not. A total Elixir solution is a whole different story and yes, CSS has definitely gotten more consistent (we’re just using straight up vanilla CSS and esbuild at work and it’s been fine). Of course that means the Phoenix Team needing to maintain, but I’m going to stop pretending I know what they can or can’t take on And ya, don’t get me wrong, I would not be mad if something scoped selectors replaced Tailwind in phx_new.
The “real” work is writing the CSS parser/generator, which is needed for scoped/co-located styles anyway. Phoenix already has an HTML parser for heex, so this isn’t a stretch (and Jose seems to like the idea, at least down the road).
For prefixing you need to maintain a database of prefixes. I don’t think this would be too hard because you can just mirror them from whatever autoprefixer uses. Wrap them in an (optional) Elixir package (like the timezone db packages) and put it behind a flag in phx_new for people who want that functionality.
And no esbuild rsbuild, etc either, because that would be cheating. It is the end game.
For the record, you don’t actually need to bundle JS. I actually plan to ditch esbuild in my projects eventually and ship the vanilla JS unbundled, because I would prefer that my users be able to inspect the full source in devtools instead of seeing minified/mangled code.
The only reason I haven’t done this is because it’s more work since esbuild works out of the box…
But if you want Typescript support (at least for compilation) then you need something to strip the types. We could probably do that!
Typescript is moving to a go base implementation, I heard, so I am afraid it is going to be more complex than striping the types.
I’ve already ditch everything in some of my projects. No Typescript, no JSX, no build. Many nice thing are off-limit for me now but the freedom from the shackle is worth it. Don’t get me wrong, I like Typescript, I like JSX, I even like Tailwind. However, I hate the toolchain story in the javascript world.
That’s the type checker. Stripping the types is much easier - it’s what esbuild does out of the box. I think maintaining a full TS type-checker in Elixir would cross the boundary into insanity
We’re in the same boat. Every time I replace something with my own tool my quality of life goes up, especially if that thing was written in JS. I have removed Node from my life and swore never to let it back in. Elixir keeps me sane.
Next on the chopping block is Postgres. That one is not going to be easy, but I have made progress.
I think part of your proposition is something we gave up on recently in Update home.css for phx.new --no-tailwind by rhcarvalho · Pull Request #5828 · phoenixframework/phoenix · GitHub, namely including the CSS styles for classes referenced in core_components.ex
in the baked in CSS file generated when you use --no-tailwind
.
On top of that, your proposal also involves concatenating utility classes into something like a single “arbitrarily-named” (in some sensible way) class per component.
If just the first part is already useful to you, the steps in the PR description can be used to generate a complete app.css
you can then drop-in a project with --no-tailwind
and still have a base style for all components.
@rhcarvalho after reading through this I’m btw thinking that my decision was wrong. But your PR didn’t go far enough. Including the CoreComponent classes in the home.css doesn’t make much sense because it’s only used for the homepage. So other pages would still be unstyled. Instead, we could have a CSS file that contains all the needed classes and include that as app.css or a separate file imported in app.css.
We can maybe revisit this after the new proposal from José: Augment Tailwind with Daisy UI · Issue #6121 · phoenixframework/phoenix · GitHub
Yeah, I agree with you. The motivation at the time was different, but a coincidence that it relates to this thread.
Still I’m not sure how far that would go, because having an app.css
while not being able to easily change classes and recompile the CSS file is of limited utility, right? Like if one change from text-zinc-500
to text-blue-500
they’d end up with an unstyled component and at some point unused utility classes in the CSS bundle.
Oh, cool, I’ll have a look!
Agreed. The built-in CSS for --no-tailwind should cover core components, phx.gen.auth and phx.gen.live. Let’s revisit it later!
Expanding on your “not sure how far that would go” comment, I would like to offer my point of view. I really hope it would make some sense.
I am an “UI Challenged” developer, working for 35+ years in imperative programming, barely starting with Web Development (Elixir, HTML & CSS). My logical approach happens to be the one Jose Valim has also.
Under those circumstances, all I need is a basic theme for my app (using CSS variables maybe) that I would update very few times. I have no interest on styling my Customers module different from my Suppliers or Invoicing modules, or several single components different from the rest. Tailwind is great whenever you are trying to style a lot of components on the fly. Whenever using the same theme for the whole app, in my opinion, Tailwind just adds an unneeded abstraction layer thus, I will use the --no-tailwind
option when creating my project. Then, “not being able to easily change classes and recompile the CSS file” is an expected behaviour, and I won’t try to change a class name expecting Tailwind to do its magic, since I instructed mix
not to use Tailwind while coding my app.
Best regards,
Greg.
P.S. I really appreciate the effort the Phoenixframework group is doing to improve this amazing tool.
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.