A clojure library to generate CSS code using an embedded domain-specific language (EDSL). In plain words: generate CSS files
by writing clojure code.
You can go here to read more about cssgen.
Using clojure instead of plain CSS you get a lot of benefices. You can use the full power of the language to do things
- Define constants and use them in your rules
(def width (px 960))
- Operate with your constants using clojure expressions
(def main-width (* width 0.62))
- Define nested rules
(rule "a.plain" :color :inherit :text-decoration :inherit :cursor :inherit (rule "&:active, &:focus" :outline :none)))
- Define reusable CSS snippets using plain old clojure functions and vars
(def has-layout (mixin ; This makes ie6 get layout :display "inline-block" ; and this puts it back to block (rule "&" :display :block))) (def clearfix (mixin :overflow :hidden has-layout))
- Generate readable styles with better code organization
(rule "#nav" (horizontal-list (px 9)) (rule "a" (link-colors my-link-color my-visited-color my-hover-color)))
- Easy CSS ‘hacks’
(defn- float-side [side] (mixin :display :inline :float side)) (defvar float-left (float-side :left) "Implementation of float:left with fix for double-margin bug") (defvar float-right (float-side :right) "Implementation of float:right with fix for double-margin bug") (rule "#secondary" float-right)
The easiest way to install cssgen is by using Leiningen. Just add the following dependency to your project.clj file:
I’ll show some examples of use, but you should read the wiki for more details and information.
- CSS rules: to create a simple rule you use the
rulefunction, passing the selector as first argument, and a
series of property pairs.
(rule "ul.nav, ol" :color :black :background-color :#ddd :padding [:1px "2px" (px 3) 0])
- Property values could be
- any other type convertible to string with
- values sequences
- special constructions like
(col :#aaa)(more about this
If a property key must be associated with several values, you use a sequence of values, like in the padding
property above. Of course, if everything is “literal”, you could simply do
:padding "1px 2px 3px 4px".
- You can nest rules:
(rule "#main, #secondary" :padding "10px" (rule "h1" ; this will generate a rule for "#main h1, #secondary h1" :color :blue))
- If you need the parent selector on the nested rule, you can use “&” and it will get replaced:
(rule "a" :color "#00C" (rule "&:hover" ; this will generate a rule for a:hover :color "#0CC"))
- You can define mixins with multiple rules and properties using functions or vars. Those can later be used in other
(defn link-colors ([normal] (link-colors normal nil)) ([normal hover] (mixin :color normal (if visited (rule "&:visited" :color visited)) (if hover (rule "&:hover" :color hover))))) (rule "a" (link-colors "#00c" "#0cc"))
- As you can see in the previous example, nils in the properties list will be ignored:
- You can easily define constants
(def width (px 960)) (def h1-font-size (em 1.5)) (def h1-color (col :#0000ca)) (def h2-color (col :#0dd)) (def h3-color ($ :#0dd)) ; $ is just an alias for col (def form-size (% 60))
- And use the basic arithmetic operations on them
(def main-width (* 0.7 width)) (def h2-font-size (- h1-font-size (em 0.3))) (def h4-color (/ (+ h2-color h3-color) 2))
- To generate a new CSS file from the current clj code do:
(use 'cssgen.use) (css-ns killerapp.css.screen (:use (killerapp.css reset layout colors))) (css-file "public/css/screen.css" ;this is the path to the target CSS file ....... ....... ; all your rules .......)
css-ns you could use the normal
(ns) call, but it gets a little tricky since we are redefining arithmetic
- More syntactic sugar
- Helper functions to operate with colors and lengths
- Helpers to define dimensions and colors
- Methods to define rules without actually generating any CSS file
- Watcher to re-generate css files if source changed ???
- Property namespaces (font-*)
- Write a sass “compiler” to migrate from sass to cssgen
- Use that compiler to generate the whole compass tree in cssgen.
- Command line interface
wiki for more usage information.Check the
If you have a feature request, problem or comment, just drop me a line.