Go to file
Shinmera e00b7c8e6b Added binary generation tools. 2014-09-05 13:15:58 +02:00
LICENSE MAKE IT SO 2014-09-03 14:43:10 +02:00
README.md Minor textual fixes 2014-09-05 12:32:28 +02:00
about.html Minor textual fixes 2014-09-05 12:32:28 +02:00
binary-lass.asd Added binary generation tools. 2014-09-05 13:15:58 +02:00
binary.lisp Added binary generation tools. 2014-09-05 13:15:58 +02:00
compiler.lisp Fixed dumb mistake 2014-09-05 11:34:08 +02:00
generate-binary.sh Added binary generation tools. 2014-09-05 13:15:58 +02:00
lass.asd Version bump, added description 2014-09-05 11:34:19 +02:00
lass.lisp Added COMPILE-AND-WRITE 2014-09-05 12:14:57 +02:00
package.lisp Added COMPILE-AND-WRITE 2014-09-05 12:14:57 +02:00
special.lisp Fix to COMPILE-ATTR-COMPARATOR and TRANSFORM 2014-09-05 12:15:19 +02:00
writer.lisp Changed pretty-writing of selector alternatives to use newlines. 2014-09-05 12:21:20 +02:00

README.md

About LASS

Writing CSS files comes with a lot of repetition and is generally much too verbose. With lispy syntax, shortcuts, and improvements, LASS aims to help you out in writing CSS quick and easy. LASS was largely inspired by SASS.

How To

LASS supports two modes, one being directly in your lisp code, the other in pure LASS files. Adding LASS into your code is easy:

(lass:compile-and-write
 '(div
   :background black))

"div{
    background: black;
}"

LASS works on the following simple principles: A list is a block. The first argument in the list is a selector. The body of the list makes up the properties and sub-blocks. A property is started with a keyword that is used as the property name. Following is a bunch of property arguments until a new keyword, list, or the end is reached. A list inside a block is, again, a block with the twist that the parent block's selector is prepended to the sub-block's selector.

(lass:compile-and-write
 '(nav
   (ul
    :list-style none
    (li
     :margin 0 :padding 0
     :display inline-block)))))

"nav ul{
    list-style: none;
}

nav ul li{
    margin: 0;
    padding: 0;
    display: inline-block;
}"

Since LASS' COMPILE-SHEET simply takes a bunch of lists as its argument, you can use the backquote and comma to integrate variables from your lisp environment:

(let ((color "#0088EE"))
  (lass:compile-and-write
   `(div
     :background ,color))))

"div{
    background: #0088EE;
}"

Alternatively however, and this is especially useful in pure LASS files, you can use the LET block to create LASS-specific bindings:

(lass:compile-and-write
 '(:let ((color "#0088EE"))
   (div
    :background #(color))))

"div{
    background: #0088EE;
}"

LASS' selector mechanism is very flexible and allows for some complex logic to reduce duplication:

(lass:compile-and-write
 '(article
   ((:or p blockquote)
    :margin 0 :padding 0

    (a
     :color black)
      
    ((:and a :hover)
     :color darkred))))

"article p, article blockquote{
    margin: 0;
    padding: 0;
}

article p a, article blockquote a{
    color: black;
}

article p a:hover, article blockquote a:hover{
    color: darkred;
}"

But it can go even further:

(lass:compile-and-write
 '((:and
    (:or article section)
    (:= data-author (:or yukari ran chen))
    (:nth-child (:or 1 2 3)))
   :display none))

"article[data-author=\"yukari\"]:nth-child(1),
 article[data-author=\"yukari\"]:nth-child(2),
 article[data-author=\"yukari\"]:nth-child(3),
 article[data-author=\"ran\"]:nth-child(1),
 article[data-author=\"ran\"]:nth-child(2),
 article[data-author=\"ran\"]:nth-child(3),
 article[data-author=\"chen\"]:nth-child(1),
 article[data-author=\"chen\"]:nth-child(2),
 article[data-author=\"chen\"]:nth-child(3),
 section[data-author=\"yukari\"]:nth-child(1),
 section[data-author=\"yukari\"]:nth-child(2),
 section[data-author=\"yukari\"]:nth-child(3),
 section[data-author=\"ran\"]:nth-child(1),
 section[data-author=\"ran\"]:nth-child(2),
 section[data-author=\"ran\"]:nth-child(3),
 section[data-author=\"chen\"]:nth-child(1),
 section[data-author=\"chen\"]:nth-child(2),
 section[data-author=\"chen\"]:nth-child(3){
    display: none;
}"

Whoa nelly!

Some CSS properties are not fully specified yet and require browser-specific prefixes. LASS can help you with that, too:

(lass:compile-and-write
 '(.fun
   :linear-gradient "deg(45)" black 0% darkgray 100%
   :transform rotate -45deg))

".fun{
    background: -moz-linear-gradient(deg(45), black 0%, darkgray 100%);
    background: -o-linear-gradient(deg(45), black 0%, darkgray 100%);
    background: -webkit-linear-gradient(deg(45), black 0%, darkgray 100%);
    background: -ms-linear-gradient(deg(45), black 0%, darkgray 100%);
    background: linear-gradient(deg(45), black 0%, darkgray 100%);
    -moz-transform: rotate(-45deg);
    -o-transform: rotate(-45deg);
    -webkit-transform: rotate(-45deg);
    -ms-transform: rotate(-45deg);
    transform: rotate(-45deg);
}"

LASS also supports the various @QUERY operator blocks:

(lass:compile-and-write
 '(:media "(max-width: 800px)"
   (div
    :margin 0)))

"@media (max-width: 800px){
    div{
        margin: 0;
    }
}"

By default LASS activates pretty-printing and inserts newlines and spaces where appropriate in order to make the result readable and easy to debug. However, you can also deactivate that and directly produce minified CSS:

(let ((lass:*pretty* NIL))
  (lass:compile-and-write
   '(:media "(max-width: 800px)"
     (div
      :margin 0))))

"@media (max-width: 800px){div{margin:0;}}"

As mentioned above you can write pure LASS files to compile down to a CSS file. To do that, simply use GENERATE:

generate-example

Extending LASS

Pretty much every part of LASS is extensible through methods. Most useful will however probably be the DEFINE-SPECIAL-PROPERTY, DEFINE-BROWSER-PROPERY and DEFINE-SPECIAL-SELECTOR helper-macros. Here's some examples from the SPECIAL.LISP file that defines some standard special handlers:

(define-special-property font-family (&rest faces)
  (list (make-property "font-family" (format NIL "~{~a~^, ~}" (mapcar #'resolve faces)))))

(define-browser-property linear-gradient (direction &rest colors)
  (:default (property)
    (make-property "background" (format NIL "~a(~a~{, ~a ~a~})"
                                         property (resolve direction) (mapcar #'resolve colors)))))

For more control, have a look at the various COMPILE-* generic functions.