Skip to content

Instantly share code, notes, and snippets.

@superstructor
Last active February 11, 2021 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save superstructor/7ef7e5a80553e7abdee33bd73825da05 to your computer and use it in GitHub Desktop.
Save superstructor/7ef7e5a80553e7abdee33bd73825da05 to your computer and use it in GitHub Desktop.
re-com-css
Table 1. Comparison of re-com CSS Options
Current Inline Styles 'Utility First' CSS Garden CSS Garden 'CSS in [CL]JS'

Removes re-com.css

Reverses CSS→DOM Dep

Composable

'Pruning' not Required

Styles as Data

Styles in Namespace

Styles near Component

Stateful Styling

Turn Off Default Styles

Modularity

Full Power of CSS

Performant

Score

4/12

9/12

6/12

7/12

12/12

Percent

33%

75%

50%

58%

100%

Goals

  • Reversal of dependency of CSS-on-DOM to DOM-on-CSS ('utility first' inspired)
  • Co-location of styling with CLJS (again, 'utility first' inspired which achieves this via class naming)
  • Modularity between components and seperation of concerns (i.e. datepicker styles won't impact input-text styles)
  • Re-usability of common styles
  • Performance (e.g. in v-table, scrolling 1-million rows)
  • way to turn off default styles - day8/re-com#51
  • way to inject 'utility first' classes for stateful things; e.g. :parts {:next-year:hover ... :next-year:disabled...
  • way to transform/replace styles without passing per-component instance args (aka theming, or 'changing default colours') - day8/re-com#123

Options

Option 1. 'Utility First' CSS

E.g. https://tachyons.io/, https://tailwindcss.com/

Advantages:

  • pre-made libraries
  • composable
  • reversal of CSS->DOM depenedency
  • easy to implement

Disadvantages:

  • not possible to run pruning tools to remove unused classes from CSS when using hiccup embedded in CLJS, tooling is built for the vanilla-JS world.
  • readability can be poor.
  • limits flexibility or power of CSS. E.g. https://www.npmjs.com/package/tailwindcss-grid even says

It's not really practical to expose all of the power of CSS Grid through utilities, but this plugin is a good example of using CSS Grid to replace a cell-only float or Flexbox grid.

  • you end up using a mix of full CSS and 'utility first' anyway, aka 'utility last' is always the end game of 'utility first' then we come back to the same problem we are trying to solve.
  • styles are not data

Option 2. Pure Garden

E.g.

(stylesheet/inject-garden-stylesheet!
  [
    [:.rc-datepicker-selected
     :.rc-datepicker-selected:hover
     {:background-color :#357ebd
      :border-color     :#3071a9
      :color            :#FFF}]])

Advantages:

  • no longer shipping re-com.css as a seperate file
  • styles can be in the same namespace as code
  • styles are data
  • easy to turn off default styles

Disadvantages:

  • styles are not truely co-located with components, can be a few hundred lines of CLJS seperation
  • no modularity/seperation of concerns; Garden CSS is a global namespace
  • DOM still depends on CSS (i.e. semantic classes)

Option 3. 'Component CSS' or 'CSS in [CL]JS' w/ Garden

E.g.

Advantages:

  • no longer shipping re-com.css as a seperate file
  • styles can be in the same namespace as code
  • styles are data
  • co-location of styles with components
  • composable
  • reversal of CSS->DOM depenedency
  • full power and expressiveness of CSS (via Garden)
  • 'automatic' attachment of classnames to components

Spade:

(ns re-com.datepicker)

(defclass next-year-nav-style
  [enabled?]
  [:path
   {:fill (if enabled? :#357ebd :#999)}]
  [:&:hover
   {:background-color :#357ebd
    :cursor "pointer"}
   [:path
    {:fill (if enabled? :#fff :#999)}]])
    
(defn- next-year-nav
  [& {:keys [display-month maximum disabled? parts]}]
  (let [next-year-date-time  (inc-year @display-month)
        next-year-enabled?   (if maximum (cljs-time/before? next-year-date-time maximum) true)]
    (when (not disabled?)
      [:<>
       [line]
       [box
        :class   (str "rc-datepicker-next-year " (next-year-nav-style next-year-enabled?))
        ...]])))

Herb: Fail. Not possible to implement the box:hover style on the svg/path child of the box. It does have ^{:pseudo {:hover {:fill ... but this could only be applied as path:hover {:fill ... (as we want to fill the path) NOT box:hover path {:fill ... which limits the interactive area for the user's pointer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment