Document the practical process of generating CSS using the Common Lisp package CL-CSS [1].
Original: https://github.com/SunDawning/literate-programming/blob/master/on-cl-css.org
[Created]:<2018-05-05 Sat 17:45:59 UTC+08:00>
[Update]:<2018-05-05 Sat 19:06:32 UTC+08:00>
CL-CSS supports multiple ways to splice the list of CSS to be generated. A CSS rule can freely use symbols, strings, and keywords, but in order to make the code appear to have a uniform format, artificially regulate a part of a CSS rule type.
The specification is as follows:
Shaped like:
(css
`(("body"
:margin "5px"
:padding "0px")))
"body { margin: 5px; padding: 0px; }
"
The following situations are allowed for CL-CSS but not within the specification:
(let ((color "black"))
(css
`((body
:margin 5px)
("#root"
:margin 5px)
(footer
:border ,(format nil "1px solid ~A" color)))))
"body { margin: 5px; }
#root { margin: 5px; }
footer { border: 1px solid black; }
"
The reasons for using this specification can also be seen in the above situation:
The "css" operator only accepts one argument of "rules" ({list}), and each element in the argument ({list}} represents a CSS rule.
A standard CSS rule:
When a CSS rule actually generates CSS, the CSS selector is placed outside the curly braces, and the rest are placed inside braces. The list in the CSS rule represents nested CSS rules.
In nested CSS rules:
(css
`(("body"
:margin "5px")
("@print"
("@media (max-width:640px)"
("body"
:margin "3px"))
("@media (max-width:360px)"
("body"
:margin "0")))))
Standard nested CSS will be generated:
"body { margin: 5px; }
@print { @media (max-width:640px) { body { margin: 3px; } } @media (max-width:360px) { body { margin: 0; } } }
"
"@media" is actually a kind of selector. According to the type of selector in the specification, these CSS rules starting with @ can be written according to the specification pattern:
(css
`(("@media (max-width:640px)"
("body"
:margin "5px"))
("@media (max-width:360px)"
("body"
:margin "0"))))
produce:
"@media (max-width:640px) { body { margin: 5px; } }
@media (max-width:360px) { body { margin: 0; } }
"
The standard @keyframes rule [2]:
@keyframes mymove
{
from {top:0px;}
to {top:200px;}
}
According to Handle CSS rules starting with @
In the example, "@keyframes", "from" and "to" can actually be considered as selectors, but "from" will be used as a nested rule:
(css
`(("@keyframes mymove"
("from"
:top "0px")
("to"
:top "200px"))))
"@keyframes mymove {from {top: 0px; } to { top: 200px; } }
""
Progress such as "0%" and "100%" is actually a selector. For standard CSS rules:
@keyframes mymove
{
0% {top:0px;}
25% {top:200px;}
50% {top:100px;}
75% {top:200px;}
100% {top:0px;}
}
You can create CSS rules like this:
(css
`(("@keyframes mymove"
("0%"
:top "0px")
("25%"
:top "200px")
("50%"
:top "100px")
("75%"
:top "200px")
("100%"
:top "0px"))))
generate:
"@keyframes mymove { 0% { top: 0px; } 25% { top: 200px; } 50% { top: 100px; } 75% { top: 200px; } 100% { top: 0px; } }
"
Create css.lisp file
Create a global variable to represent a CSS rule
(defparameter *key*
`((".keys"
:display "flex")))
(defparameter *do-not-use-right-key*
`((".keys"
:user-select "none")))
Stitch multiple CSS rules
(defparameter *css*
(css
`(,@*do-not-use-right-key*
,@*key*)))
On the basis of the Mosaic multiple CSS rules, save the CSS string as a file:
(with-open-file (out "/tmp/css.css"
:direction :output
:if-exists :supersede)
(princ *css* out))
CL-CSS has a "compile-css" operator to output CSS rules to a file in one step:
(compile-css "/tmp/css.css"
'((body :margin 5px :padding 0px)))
The two methods have their own strengths and the same goal.
[1]: cl-css | Quickdocs: http://quickdocs.org/cl-css/
[2]: CSS3 @keyframes rules:
http://www.w3school.com.cn/cssref/pr_keyframes.asp