JeromeDane / garden-css-modules

Apply CSS module style class name hashing to garden data in clojure and clojurescript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

garden-css-modules

Apply CSS module style class name hashing to Garden data in Clojure and ClojureScript. Learn more about the principle here.

WORK IN PROGRESS. NO GUARANTEES AT THIS POINT.

To Do

  • Handle keyframes
  • Implement production mode to short hash class + namespace
  • Allow concatination of hashed class names like {:class (my-style :foo :bar :baz)}
  • Get feedback from colleagues and iterate
  • Publish to clojars

Features

  • Automatic, unique hashing of CSS class names
  • Fully supports nested Garden declarations
  • Support for complex CSS selectors
  • Descriptive, namespaced class names in development
  • Short hashes in production mode (coming soon)

Example

Consider the following example namespace:

(ns garden-css-modules.example
    (:require [garden-css-modules.core :refer [modularize] :refer-macros [defstyle]]
              [reagent.core :as r]
              [garden.units :refer [em px]]))

(defstyle style
  [:.container {:font-family "arial,sans-serif"}
    [:h1 {:border-bottom [[(px 1) 'solid]]}]
    [:.code {:font-style 'italic
             :background "#ccc"
             :padding [[(em .25) (em .5)]]}]])

(defn app []
  [:div {:class (style :container)}
    [:h1 "Garden CSS Modules Demo App"]
    [:p "This is a demo. Edit "
        [:span {:class (style :code)} "garden-css-modules.example"]
        " to see live changes."]])

(r/render [app]
  (.getElementById js/document "app"))

This will create a small reagent component and mount it to the DOM element with ID of "app".

Resulting HTML:

<div class="container__garden-css-modules_example-1287325951">
  <h1>Garden CSS Modules Demo App</h1>
  <p>
    This is a demo. Edit
    <span class="code__garden-css-modules_example-132277090">garden-css-modules.example</span>
    to see live changes.</p>
</div>

Resulting CSS:

.container__garden-css-modules_example-1287325951 {
  font-family: arial,sans-serif;
}

.container__garden-css-modules_example-1287325951 h1 {
  border-bottom: 1px solid;
}

.container__garden-css-modules_example-1287325951 .code__garden-css-modules_example-132277090 {
  font-style: italic;
  background: #ccc;
  padding: 0.25em 0.5em;
}

Production Builds

You can reduce the length of class names to just the hash by running in production mode. Add :optimizations :advanced to your project.clj for ClojureScript when using the defstyle macro, or set ENV=prod or ENV=production in your environment variables if using the modularize function directly in a Clojure app. The example above would then result in the following HTML:

... and the following CSS:

.s1287325951{font-family:arial,sans-serif}.s1287325951 h1{border-bottom:1px solid}.s1287325951 .s132277090{font-style:italic;background:#ccc;padding:0.25em 0.5em}.s1287325951 a:hover{border-bottom:2px solid;text-decoration:none}

Development

lein figwheel will start an example app running on http://local.c0pt3r.com:3449/. This example app lets you easily play around with this library to see what it's capable of.

You can also start a repl with lein repl and connect using an nrepl client. Evaluate the garden-css-modules.core namespace, then call modularize. E.G:

(modularize
  [:div.foo.bar {:color "red"}
   [:a {}
     [:.link.yellow {:color "yellow"}]
     [:a.link.blue
      [:&;hover {:color "blue"}]]]
  [:.container {:color "blue"}])
  [".brother + .sister" {:color "orange"}])

This returns a map with the :styles key having the value of new garden data with all class names hashed and a :names map that allows you to look up the hashed name of any class name.

Testing

lein test

Credits

About

Apply CSS module style class name hashing to garden data in clojure and clojurescript

License:MIT License


Languages

Language:Clojure 97.8%Language:HTML 2.2%