Fork me on GitHub
#garden
<
2021-01-07
>
GusWill02:01:23

Hi! First post here! 🙂 So, I'm just getting started with the CSS-in-clojure approach and I was wondering if there's any way to namespace/scope my css with garden.

GusWill02:01:12

I found one lib that seems to do what I need (https://github.com/roosta/herb), but it also seems like it generates css in js.

GusWill02:01:02

I was wondering if there was an approach for "classic", static, good ol backend rendered css.

noprompt15:01:41

Do you have a sketch/example of what you’re thinking about?

GusWill15:01:10

I have to investigate further, but the problem is that they seem to be focused on cljs.

GusWill15:01:06

I'm looking for something that implements something like this: https://glenmaddern.com/articles/css-modules but not is JS, just a plain CSS file. Makes sense?

GusWill15:01:24

Those libs contain a runtime that does the CSS injection, etc. I'd prefer not to pay the JS performance price because the project where I want to introduce it is mostly classic server-rendered html.

GusWill15:01:40

I might be talking nonsense since, my css knowledge is very limited. It that is the case, my apologies.

noprompt15:01:25

Are you using something like Hiccup?

GusWill15:01:45

In the end my real problem is: our css is a real mess and, after working with React's scoped styles, I'd like that, but for a plain back-end rendered site.

GusWill15:01:49

Yes, hiccup.

GusWill15:01:57

The old-school one.

noprompt15:01:46

It seems like you essentially want a unique name that you don’t have to maintain but, at the same time, be able to refer to it with a nice name, yes?

GusWill15:01:36

Yes. Essentially, namespaces for our "components".

GusWill15:01:07

Right now we have a hot mess of 200kb of CSS that we have no idea which parts can be deleted and which parts are connected to what.

GusWill15:01:52

I'd like to refactor everything to use something like Garden, but with that feature you just described.

noprompt15:01:35

If it’s safe to assume things are compiled together then you could use gensym for making unique names.

(let [normal (gensym ".normal__")]
  [normal {:font-weight "normal"}])
;; =>
[.normal__49244 {:font-weight "normal"}]

noprompt15:01:27

Or a similar idea if you want to include something like namespace or something else to easily identify where the thing came from.

GusWill15:01:55

Hadn't thought of that. That makes perfect sense, thanks!

noprompt15:01:02

(let [css-munge (fn [s]
                  (clojure.string/replace s #"\." "$"))
      make-name (fn [prefix ns]
                  (gensym (str prefix "__" (css-munge (ns-name ns)) "__")))]
  (make-name ".normal" *ns*))
;; =>
.normal__scratch__49273

noprompt15:01:17

Just kinda messing around with the idea.

GusWill15:01:01

Yeah, that's almost exactly what I was thinking, including the ns

noprompt15:01:18

Then you can (def normal (make-name ".normal" *ns*)) or something and use that in your styles.

GusWill15:01:24

But you're quicker 😀

noprompt15:01:52

I always have a REPL open :)

noprompt15:01:09

Well almost always 😄

GusWill15:01:22

Is this a conventional use case? Are there any gotchas that my noob css mind can't think of?

noprompt15:01:35

I can’t think of any. As long as you’re generating a valid CSS identifier you’re good.

GusWill15:01:38

Yeah, sometimes it's better to test things out in the repl than to try to find libs that solve my problem!

GusWill15:01:13

Awesome! Thanks man, really appreciate your help!

noprompt15:01:23

Not a problem.

GusWill15:01:47

BTW, most of the libs I just linked provide a robust make-name function that I can just copy and paste.

noprompt15:01:15

I think the only draw back I can see to this approach is for the HTML/Hiccup side of things.

GusWill15:01:18

If anyone goes down this road in the future

noprompt15:01:15

Well you couldn’t use [:h1 {:class scratch/normal}] because you’d wind up with <h1 class=".normal__45545"></h1>

noprompt15:01:15

You could generate the name without the . however for the identifier and then use the garden.selectors namespace for everything else.

noprompt16:01:25

(require '[garden.selectors :as css.$])

(def normal
  (gensym "normal__"))

(def $normal
  (css.$/selector (str "." normal)))

GusWill16:01:49

Makes sense. I'd have to come up with some kind of mapping between them.

noprompt16:01:25

If styles were XML…

GusWill16:01:29

My 200kb hot mess would be more like 2Mb hot mess 😂

😆 3
noprompt16:01:55

One of these days I’m gonna get back to the front end.