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.
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.
I was wondering if there was an approach for "classic", static, good ol backend rendered css.
Do you have a sketch/example of what you’re thinking about?
@noprompt thanks for replying. After I posted my question I found a few libs that do mostly what I want: https://github.com/JeromeDane/garden-css-modules, https://github.com/matthieu-beteille/cljs-css-modules, https://github.com/Jarzka/stylefy.
I have to investigate further, but the problem is that they seem to be focused on cljs.
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?
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.
I might be talking nonsense since, my css knowledge is very limited. It that is the case, my apologies.
Are you using something like Hiccup?
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.
Yes, hiccup.
The old-school one.
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?
Yes. Essentially, namespaces for our "components".
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.
I'd like to refactor everything to use something like Garden, but with that feature you just described.
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"}]
Or a similar idea if you want to include something like namespace or something else to easily identify where the thing came from.
Hadn't thought of that. That makes perfect sense, thanks!
(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
Just kinda messing around with the idea.
Yeah, that's almost exactly what I was thinking, including the ns
Then you can (def normal (make-name ".normal" *ns*))
or something and use that in your styles.
But you're quicker 😀
LOL
I always have a REPL open :)
Well almost always 😄
Is this a conventional use case? Are there any gotchas that my noob css mind can't think of?
I can’t think of any. As long as you’re generating a valid CSS identifier you’re good.
Yeah, sometimes it's better to test things out in the repl than to try to find libs that solve my problem!
Awesome! Thanks man, really appreciate your help!
Not a problem.
BTW, most of the libs I just linked provide a robust make-name
function that I can just copy and paste.
I think the only draw back I can see to this approach is for the HTML/Hiccup side of things.
If anyone goes down this road in the future
wdym?
Well you couldn’t use [:h1 {:class scratch/normal}]
because you’d wind up with <h1 class=".normal__45545"></h1>
You could generate the name without the .
however for the identifier and then use the garden.selectors
namespace for everything else.
(require '[garden.selectors :as css.$])
(def normal
(gensym "normal__"))
(def $normal
(css.$/selector (str "." normal)))
Makes sense. I'd have to come up with some kind of mapping between them.
If styles were XML…
One of these days I’m gonna get back to the front end.
My 200kb hot mess would be more like 2Mb hot mess 😂