# The CSS problem

**URL:** https://clojureverse.org/t/the-css-problem/9599
**Category:** Watercooler
**Created:** [December 9, 2022, 6:06am UTC](https://clojureverse.org/t/the-css-problem/9599 "2022-12-09T06:06:35Z")
**Posts on this page:** 1
**Showing post:** 35

<div class="post-metadata">

### Author: ![kennytilton](https://clojureverse.org/letter_avatar_proxy/v4/letter/k/c5a1d2/32.png) [@kennytilton](https://clojureverse.org/u/kennytilton)
#### Post date: [January 31, 2023, 5:11pm UTC](https://clojureverse.org/t/the-css-problem/9599/35 "2023-01-31T17:11:32Z")

</div>

Don’t know about “brilliant”, and not a standalone CSS solution, but my [Web/MX](https://github.com/kennytilton/web-mx) hack (ne mxWeb) offers a radically _different_ solution. Key qualities:

- it still works with stylesheets via the `class` attribute;
- the in-line style of a widget can be defined reactively, via a CLJS formula that keeps up with other app state. Or at least examines other widget state to decide its CSS;
- so, yeah, we have dynamic CSS without juggling classes; and
- the style attribute can be expressed as an object with individual reactive properties per style attribute. Prolly not huge performance win, but certainly easier to fine-tune or just understand a widget’s styling.

These examples are from the huge-ish Web/MX demo app [“AskHN Who’s Hiring?”](https://github.com/kennytilton/matrix/tree/main/cljc/whoshiring). (Live version built with the JS version of Web/MX is [here](https://kennytilton.github.io/whoishiring/).). Now the examples.

A primitive rule building a style string reactively, to show/hide a star in the header of a job which the user has scored:

```auto
(span {:style (cF (str "color:black;max-height:16px;margin-right:9px; display:"
                        (if (or (deets? me)
                              (zero? (memo/job-memo job :stars)))
                          "none" "block")))}
      (utl/unesc "&#x2b51"))

```

A case that shows dynamic CSS classes, in support of animation, as well as more structured specification of `:style`:

```auto
(div {:class (cF (if (deets? me) "slideIn" "slideOut"))
        :style (cF {:margin "6px"
                    :background "#fff"
                    :display (if (deets? me) "block" "none")})}
  ...etc)

```

And a full-blown `css-inline` model:

```auto
(make-css-inline me
    :border "none"
    :font-size "14px"
    :display (cF (if (and (rx-completed rx)
                       (not (rx-due-by rx)))
                   "none" "block"))
    :background-color (cF (when-let [clock (mxu-find-class (:tag @me) "std-clock")]
                            (if-let [due (rx-due-by rx)]
                              (if (rx-completed rx)
                                _cache ;; cF expansion has _cache (prior value) in lexical scope
                                (let [time-left (- due (mget clock :clock))]
                                  (cond
                                    (neg? time-left) "red"
                                    (< time-left (* 24 3600 1000)) "coral"
                                    (< time-left (* 2 24 3600 1000)) "yellow"
                                    :default "green")))
                              "#e8e8e8"))))

```

One thing not shown is that, since Web/MX accepts a map of CSS attributes, it would not be hard to fake in-line CSS composition with a clever set of routines, perhaps by rolling our own fake CSS class tags and driving the final CSS map off that. But that sounds like we would descend into CSS combination hell pretty quickly. There if we want it, tho.

Finally, again, this is not a standalone solution. I offer this more as an example of how much goodness falls out of making widget properties individually reactive. I will yap more about this in the formal announcement of Web/MX. RSN.

---

_[View the full topic](https://clojureverse.org/t/the-css-problem/9599)._
