Giter Club home page Giter Club logo

cssgen's Introduction

cssgen

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.

Please take a look at the upcoming syntax in version 0.3.0, tell me what you think: 0.3.0-SNAPSHOT

Using clojure instead of plain CSS you get a lot of benefices. You can use the full power of the language to do things
like:

  • 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)

Installation

The easiest way to install cssgen is by using Leiningen. Just add the following dependency to your project.clj file:


    [cssgen "0.2.6"]

Usage

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 rule function, 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
    • keywords,
    • strings,
    • any other type convertible to string with as-str,
    • values sequences
    • special constructions like (px 9), (% 30), (col :#aaa) (more about this
      later).

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
    definitions

    (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
      .......)

Instead of css-ns you could use the normal (ns) call, but it gets a little tricky since we are redefining arithmetic
operations.

ToDo

  • 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.
  • Document
  • Command line interface

Check the wiki for more usage information.

If you have a feature request, problem or comment, just drop me a line.

cssgen's People

Contributors

paraseba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cssgen's Issues

Error when trying make CSS file

Can't dynamically bind non-dynamic var: clojure.contrib.io/*append*

Perhaps this isn't compatible with recent versions of clojure?

Problem with new-style contrib

I cannot seem to get cssgen to work with clojure 1.3.0 and new style contribs.

cssgen depends on org.clojure/algo.generic. Referred version of that library has code under namespace clojure.algo.generic. Yet cssgen.use/css-ns refers to clojure.contrib.generic.arihmetic, which looks like old contrib stuff.

What's the correct fix so old libs work, too?

Using jolby/colors

It might be worth using something like jolby/colors for all the color props. That way we can use whatever representation we like, and just pass in a color.

For instance, I like to work with HSL because it's easier to grok, but ultimately I don't care what it ends up as in the stylesheet.

Requiring types %

If I require css.types instead of use, say for instance

(require '[css.types :as ct])

Then ct/% will throw

java.lang.Exception: Invalid token: ct/
  [Thrown class clojure.lang.LispReader$ReaderException]

On the other hand a 'use' works just fine.
This is specifically in the case of '%' all others work just fine its probably a reader issue.

I like your types idea and am enjoying using the cssgen library

Error when trying make CSS file

Can't dynamically bind non-dynamic var: clojure.contrib.io/*append*

Perhaps this isn't compatible with recent versions of clojure?

@ getting a little redundant with nesting

Not a terminal issue, but a touch on the annoying side. I've been porting a few libraries to cssgen, because I prefer to write clojure code over Ruby. I'm running into a redundancy issue with parsing @

For instance
["@Keyframes flash"
["0%, 50%, 100%" :opacity :1]
["25%, 75%" :opacity :0]]

Becomes
@Keyframes flash {

} @Keyframes flash 0%, @Keyframes flash 50%, @Keyframes flash 100% {
opacity: 1;
}
@Keyframes flash 25%, @Keyframes flash 75% {
opacity: 0;
}

I understand the way nesting is designed in CSSGen and for most instances it is perfect, but in the event of designing responsive sites or utilizing CSS3 features it creates a lot of unnecessary bloat.

If I can figure out an elegant solution, I'll send you a pull. Right now my work-around is too jank.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.