Reputation: 5924
In reagent, one can specify inline CSS styles like this:
[:div {:style {:border "1px solid red"}} "My Text"]
garden can make such CSS properties containing several values in a list more generic. Vectors for comma separated lists and nested vectors (used here) for space separated lists:
(require '[garden.core :refer [style]])
(style {:border [[:1px :solid :black]]})
;= "border: 1px solid red;"
How can those things be combined? Reagent seems to be stubborn only accepting hash-maps for the style attribute. Accepting a string as well would be a solution here.
Generally, of inline-styles aren't a good choice in a long term. So one could solve that by attaching a class to the div
and by specifying its style globally by gardens css
function.
Class Example:
[:div.myclass "My Text"]
(css [:.myclass {:border [[:1px :solid :black]]}])
;= ".myclass {\n border: 1px solid black;\n}"
However, sometimes it's good to start with inline styles, so: Is there a way to do it the way that is described above?
Upvotes: 5
Views: 2800
Reputation: 2473
I'm using garden
with goog.style/installSafeStyleSheet
, as suggested by ClojureMostly.
I'm also playing with generating scoped css, currently with (random-uuid)
. If I get it to work nicely, I'll update this answer.
(ns stuff
(:require
[goog.dom :as gdom]
[goog.style :as gstyle]
[garden.core :refer [css]])
(:import [goog.html SafeStyleSheet]
[goog.string Const]))
(defn install-styles! []
(gstyle/installSafeStyleSheet
(SafeStyleSheet/fromConstant
(Const/from
(css [:.someclass {:color 'red}])))))
(def ref-to-installed-style (install-styles!))
(defn app []
[:h1.someclass "Red Hello world!"])
;; Reagent and Figwheel stuff. On figwheel reload, call
;; (gstyle/uninstallStyles ref-to-installed-style), and then
;; install it again, to avoid duplication.
Note: there might be a bug here, if the component is rendered before the styles are installed. Still not sure how to fix that.
Upvotes: 0
Reputation: 51
Take a look at stylefy. It allows you to attach styles defined as data to reagent components: For example:
(def button-style {:padding "25px"
:background-color "#BBBBBB"
:border "1px solid black"})
(defn- button [text]
[:div (use-style button-style)
text])
Upvotes: 1
Reputation: 5924
The hash-map that can optionally be supplied to reagent's hiccup vectors is basically an abstraction over the HTML attributes of the specified html element. (As they are represented in the DOM)
Additionally another hash-map can be nested when attached to the keyword :style
. This is an abstraction of the element's style properties. Which is a different thing that the one above. For that reason one could argue that those two things would have better been kept apart, however it simpler like this in another way.
Manipulating an element's style properties by setting it's style attribute would mean that the whole style string has to be parsed when only one part changes. So having an extra-option for providing a style-string in hiccup wouldn't help that much.
It looks like garden can only render to strings. I'd suggest it could be helpful if it would also render to a hash-map.
Here however is a workaround, that lets reagent and garden work together:
(defn css-map [s]
(->> (style s)
(re-seq #"(.*): (.*);(?:\n|$)")
(reduce (fn [m [_ k v]]
(assoc m k v))
{})))
(css-map {:border [[:1px :solid :red]]
:background-color (rgb 33 5 0)})
;= {"border" "1px solid red", "background-color" "#210500"}
The performance will suffer from this of course. If someone knows a better solution, I'd still be curious to know.
Upvotes: 2