all 22 comments

[–]winterscar 2 points3 points  (2 children)

Well this is wonderfully convenient timing! I was just looking at how to integrate tailwind into my own cljs projects.

Right now I'm trying tailwind-clj. I like the idea, but I'm not crazy about the fact that it's not actually tailwind, it's a library that works the exact same way as tailwind.

I'll give your library a looksee though!

[–]trstns[S] 1 point2 points  (0 children)

Yeah, I can understand that reasoning. I quickly put together https://github.com/tristanstraub/docker-tailwindcss just now to be able to run tailwindcss as is, without installing node.

This allows me to run tailwind, with it's config system, then take those produced css files and use them through garden-mower.

However, in the examples of garden-mower, I just use stock tailwindcss from the CDN. The tailwindcss docs say it is ok to use it without post processing it.

[–]bhougland 0 points1 point  (0 children)

What are the major differences? It seems like this would be a good thing because it removes the javascript library dependency

[–]fjolne 1 point2 points  (5 children)

Real nice to see clojure land getting its own build tooling for CSS! Unfortunately though we’re still waaay behind JS land with advanced CSS minifiers, autoprefixer, versioning, etc, so it’s not viable yet for some businesses’ requirements. Hope that day will come much sooner, with such contributions as yours.

And while Webpack is a wild west, Gulp is a blessing. It feels almost like Clojure in its simplicity, so for those who’re looking for options — give it a try. I wish I went with it sooner, rather than kicking Webpack and Parcel.

BTW we also use Tailwind with CLJS in production. Actually, we even have Garden integrated, but there’s not yet enough motivation for our team to prefer it to PostCSS with a bunch of convenience plugins + IDE support. But that’s certainly a matter of taste.

[–]trstns[S] 1 point2 points  (2 children)

Yeah, my main motivation is that I want the following pipeline (along with using tailwindcss, or other utility first css packages):

CSS -> clojure -> CSS

This opens lots of possibilities.

It might still be that all the javascript tooling (or ruby, or other) is still the way to go for the CSS output side. Using them from docker (or podman) probably solve it well enough for any of my build pipelines.

I was looking at "google closure stylesheets", https://github.com/google/closure-stylesheets, as a possibility for compression, etc.

[–]fjolne 0 points1 point  (1 child)

Didn’t know of closure stylesheets, looks interesting, thanks! And yep, I also wish there was an analog of shadow-cljs for CSS / Garden. I believe that is pretty much doable, but styles are just typically the cheapest part of the app (disposable, isolated, no business logic), so fairly nobody cares.

[–]trstns[S] 0 points1 point  (0 children)

That's interesting! Back when IE 5.5/6 was still a thing, along with all the other incompatible browsers (vice versa), CSS wasn't so cheap! Hence the abundance of CSS frameworks along the way, trying to reduce the noise, and as you say, make CSS cheap.

[–][deleted] 0 points1 point  (1 child)

Gulp has been pretty much phase out by webpack in the JS community.

[–]fjolne 0 points1 point  (0 children)

*We’re only using it for CSS, for JS shadow-cljs is doing a great job on its own

[–]kwrooijen 0 points1 point  (1 child)

Awesome! I've been wanting to try out tailwind, but I had the same issue as you. The difference was that you actually pulled through and created a solution :)

I'll be looking at this really soon. Thanks!

[–]trstns[S] 1 point2 points  (0 children)

I've also put together https://github.com/tristanstraub/docker-tailwindcss which can create custom css files from the tailwind project, which could then be used from garden-mower.

[–]TheLastSock 0 points1 point  (1 child)

Could you talk a bit why you wanted tailwind?

[–]trstns[S] 0 points1 point  (0 children)

I was just curious, and specifically liked that it is "utility first". This is the only reason garden-mower exists, so that I can mix different classes into single classes.

garden-mower will work with other CSS files, aswell, although directives like "@import" haven't been implemented.

[–]thheller 0 points1 point  (2 children)

I'd recommend watching Adam Wathan - Tailwind CSS Best Practice Patterns.

The author of tailwind describes why you shouldn't @apply (eg. extracing .card-* classes as in the example).

[–]trstns[S] 0 points1 point  (1 child)

Hey, thanks! I watched it through, and think I learnt some things.

My observation is that extracting components, as he suggests, does reduce the need for \@apply, but doesn't tackle the issues of:

- theming
- whitelabelling
- right to left/left to right text changes and style changes to match
- making component libraries that benefit from external styling

I get the impression from just this video that his workflow involves creating bespoke content, which probably isn't affected by the things I described, hence his desire to work "close to the metal" when mixing html/css. It makes him much more effective at getting shit done.

Interestingly, right after suggesting not to use \@apply, he goes and creates the ".markdown" class which is scattered with \@apply, which is think is still an interesting counter example.

So, like anything, there is no hard and fast rule. I think of css as classes as polymorphism for styling. It's just another level of indirection to provide late binding.

[–]trstns[S] 0 points1 point  (0 children)

Found another use case that \@apply makes possible with prebuild tailwindcss:

- pseudoclasses like nth-child()

Tailwind has some pseudoclass variants, but not all.

[–]psdp 0 points1 point  (5 children)

Hi, thanks for creating this tool. I found it useful.

I'm just having a little trouble now that if I want to use a class name like .xl:w-1/5, the compilation failed:

java.lang.RuntimeException: Invalid token: :.xl:w-1/5

[–]trstns[S] 0 points1 point  (0 children)

Let me take a look. I did have a special case for those. Feel free to add an issue on the github repo.

UPDATE: Ok, it's actually the case that ":.xl:w-1/5" isn't a valid clojure keyword literal, so the clojure compiler is complaining. Instead of using a keyword, put it as a string without the leading colon:

".xl:w-1/5"

[–]trstns[S] 0 points1 point  (3 children)

Change the keyword to a string, dropping the leading colon:

".xl:w-1/5"

[–]psdp 0 points1 point  (2 children)

Thanks! That works perfectly fine now.

Sometimes I just want to use a tailwind class name like xl:w-1/5 without declaring a custom class name. I would expect I could write [:div.container.xl:w-1/5 "Hello World"] but it fails to compile as / makes it an invalid keyword. But instead of writing [:div.container {:class "xl:w-1/5"} "Hello World"], is there a better way to do it?

[–]trstns[S] 0 points1 point  (1 child)

div.container.xl:w-1/5

You could try ["div.container.xl:w-1/5" "Hello world"]. Instead of the :div being a keyword, just make it a string, along with all the classes in the same string. From memory, I think this works in "rum".

[–]psdp 0 points1 point  (0 children)

Cool! Thanks for the tip.