css-lite is a library for generating CSS from an s-exp based syntax. When compiled with Parenscript loaded in the Lisp image, it also provides the same CSS generation facilities in Parenscript-generated JavaScript code.
First, install Quicklisp.
After that, type in your Lisp prompt the following:
(ql:quickload 'css-lite)It should download and load css-lite. This download is only done once, after that Quicklisp will always load your local copy of css-lite.
Note: In previous versions of css-lite there was a bug where you
sometimes couldn’t call (ql:quickload 'css-lite) without having
previously called (ql:quickload 'parenscript). This bug has
hopefully now been fixed.
After loading the css-lite library, you are now ready to try these examples.
Set the width of the “body” tag to be 70%
(css-lite:css
(("body") (:width "70%")))
Output:
"
body {
width:70%;
}
"
By default, css-lite doesn’t indent the properties. If you wish to
indent them, see the documentation for the variable
css-lite:*indent-css*, or the section “Change the indentation” of
this README. For example, if you change the value of the variable
css-lite:*indent-css* to 4, this would be the output:
"
body {
width:70%;
}
"
Set the height of the ID “foo” to 50px and the width to 10em
(css-lite:css
(("#foo")
(:height "50px"
:width "10em")))
Output:
"
#foo {
height:50px;
width:10em;
}
"
To do the same thing, but to a class “foo”, simply replace “#foo” with “.foo”.
(css-lite:css
((".foo")
(:height "50px"
:width "10em")))
Output:
"
.foo {
height:50px;
width:10em;
}
"
Define the properties of rules “#foo” and “#foo li”
(css-lite:css
(("#foo")
(:length "50px"
:margin "50 px 30 px"
:border "1px solid red")
(("li")
(:width "50px"
:float "left"
:margin "50 px 30 px"
:border "1px solid red"))))
Output:
"
#foo {
length:50px;
margin:50 px 30 px;
border:1px solid red;
}
#foo li {
width:50px;
float:left;
margin:50 px 30 px;
border:1px solid red;
}
"
In the third example, the rules “margin:50 px 30 px;” and “border:1px solid red;” are repeated twice. css-lite has something called CSS variables that allow to abstract this.
You create a CSS variable by using the macro css-lite:make-css-var.
(css-lite:make-css-var my-favorite-border-var '(:border "1px solid red")) (css-lite:make-css-var my-margin-var '(:margin "50px 30px"))
Then you could write the third example as this:
(css-lite:css
(("#foo")
(:length "50px"
my-margin-var
my-favorite-border-var)
(("li")
(:width "50px"
:float "left"
my-margin-var
my-favorite-border-var))))
Output:
"
#foo {
length:50px;
margin:50px 30px;
border:1px solid red;
}
#foo li {
width:50px;
float:left;
margin:50px 30px;
border:1px solid red;
}
"
In addition to the CSS variables, css-lite also provides the ability to define CSS functions. This allows you to perform arbitrary modifications on the rules.
This function is declared using the macro css-lite:make-css-func
and can receive any number of arguments. However, it should return
a list with 2 values, the first being the name of the property and
the second its value.
For example, to create a function that receives the name of a property and its value in inches and converts that value into centimeters use this:
(css-lite:make-css-func convert-in-to-cm (property-name value)
;; Assumes that `value' is a string with the following
;; format: XXin, where XX represents a number greater than 0
(let* ((inches (parse-integer
(string-right-trim "in " value)))
(centimeters (round (* inches 2.54))))
(list property-name
(concatenate 'string
(write-to-string centimeters)
"cm"))))
So this call:
(convert-in-to-cm :width "10in")
Returns this list:
(:WIDTH "4cm")
So to use this function to convert the height of the identifier “#foo” from inches to centimeters, you would write this code:
(css-lite:css
(("#foo")
(:length "50px"
my-margin-var
(convert-in-to-cm :width "10in")
my-favorite-border-var)))
Output:
"
#foo {
length:50px;
margin:50px 30px;
width:4cm;
border:1px solid red;
}
"
To add a CSS comment use the function css-lite:comment
(css-lite:css
(("body")
((css-lite:comment "These are the rules for the body tag")
:width "80%"
:float "left")))
Output:
"
body {
/*These are the rules for the body tag*/
width:80%;
float:left;
}
"
To see more examples, see the file example-usage.lisp
As you can see be the above examples, by default, css-lite doesn’t indent the rules.
However you can customize this behaviour by changing the value of
the variable css-lite:*indent-css*.
There are three possible values:
- nil - The default value, indicates that no indentation should be performed
- the symbol ‘tab - Indicates that the rules should be indented using a #\Tab character
- a number greater than 0 - Indicates that the rules should be indented with that many #\Space characters.
For example, to indent the rules with 4 spaces, you would type:
(setf css-lite:*indent-css* 4)
The next time you call the css-lite:css function, the code will be
indented with 4 spaces.
For example, calling the function css-lite:css with this value:
(css-lite:css
(("body")
((css-lite:comment "These are the rules for the body tag")
:width "80%"
:float "left")))
Output:
"
body {
/*These are the rules for the body tag*/
width:80%;
float:left;
}
"
Test implemented using the FiveAM test library.
Run tests via the ASDF :TEST-OP
(asdf:oos ':test-op 'css-lite/test)
Or using the FiveAM run command
(fiveam:run! :css-lite)