记录使用Common Lisp包CL-CSS[1]生成CSS的实践过程。
原文:https://github.com/SunDawning/literate-programming/blob/master/on-cl-css.org
[创建时间]:<2018-05-05 Sat 17:45:59 UTC+08:00>
[更新时间]:<2018-05-05 Sat 19:06:32 UTC+08:00>
编写CSS规则的范式
CL-CSS支持多种方式来拼接将要生成CSS的列表,一条CSS规则里能自由地使用符号、字符串、关键字,但为了让代码看起来具有统一的格式,人为地规范一条CSS规则各部分的类型。
规范如下:
- 选择器设置为字符串类型
- 选择器与属性之间换行
- 一行一条属性和值
- 值为字符串类型
- 使用反引号"`"而不是引号"'"
形如:
(css
`(("body"
:margin "5px"
:padding "0px")))
"body { margin: 5px; padding: 0px; }
"
以下情况CL-CSS都允许使用,但不在规范内:
(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; }
"
从上述情况里也可以看出使用该规范的原因:
- 选择器不只有单一的符号,还有各种各样的类选择器、ID选择器、多个选择器等等,这些选择器只能使用字符串。
- 值不只有单一的值,还有由空格拼接起来的多个值,多个值只能使用字符串。
- 反引号允许直接内嵌变量,便于引用常用颜色、常用规则。
CL-CSS生成CSS的规则
"css"操作符只接受一个"rules"∈{列表}的自变量,自变量里的每个元素∈{列表}代表一条CSS规则。
一条标准的CSS规则:
- 由选择器、属性、值三部分组成,属性和值成对存在,数量不限,一条CSS规则里只允许存在一个选择器。
- 由选择器、嵌套的规则两部分组成,嵌套的规则本身就是一条标准的CSS规则
一条CSS规则实际生成CSS的时候,CSS选择器放在大括号的外面,其余的都放在大括号里面,CSS规则里的列表表示嵌套的CSS规则。
在层层嵌套的CSS规则中:
(css
`(("body"
:margin "5px")
("@print"
("@media (max-width:640px)"
("body"
:margin "3px"))
("@media (max-width:360px)"
("body"
:margin "0")))))
将生成标准的嵌套的CSS:
"body { margin: 5px; }
@print { @media (max-width:640px) { body { margin: 3px; } } @media (max-width:360px) { body { margin: 0; } } }
"
处理以@开头的CSS规则
"@media"实际上也是一种选择器,按照规范里的选择器的类型,将这些以@开头的CSS规则照规范的模式书写即可:
(css
`(("@media (max-width:640px)"
("body"
:margin "5px"))
("@media (max-width:360px)"
("body"
:margin "0"))))
产生:
"@media (max-width:640px) { body { margin: 5px; } }
@media (max-width:360px) { body { margin: 0; } }
"
处理@keyframes规则
标准的@keyframes规则[2]:
@keyframes mymove
{
from {top:0px;}
to {top:200px;}
}
根据 处理以@开头的CSS规则
里的示例,"@keyframes"、"from"和"to"实际都可以看作是选择器,只是"from"将作为一个嵌套的规则:
(css
`(("@keyframes mymove"
("from"
:top "0px")
("to"
:top "200px"))))
"@keyframes mymove { from { top: 0px; } to { top: 200px; } }
"
诸如"0%"、"100%"等进度,实际也是选择器。对于标准的CSS规则:
@keyframes mymove
{
0% {top:0px;}
25% {top:200px;}
50% {top:100px;}
75% {top:200px;}
100% {top:0px;}
}
可以如此创建CSS规则:
(css
`(("@keyframes mymove"
("0%"
:top "0px")
("25%"
:top "200px")
("50%"
:top "100px")
("75%"
:top "200px")
("100%"
:top "0px"))))
生成:
"@keyframes mymove { 0% { top: 0px; } 25% { top: 200px; } 50% { top: 100px; } 75% { top: 200px; } 100% { top: 0px; } }
"
模块化拼接多条CSS规则
创建css.lisp文件
创建全局变量来代表某条CSS规则
(defparameter *key* `((".keys" :display "flex"))) (defparameter *do-not-use-right-key* `((".keys" :user-select "none")))
拼接多条CSS规则
(defparameter *css* (css `(,@*do-not-use-right-key* ,@*key*)))
生成标准的CSS文件
在 模块化拼接多条CSS规则 基础上,将CSS字符串保存为文件:
(with-open-file (out "/tmp/css.css"
:direction :output
:if-exists :supersede)
(princ *css* out))
CL-CSS存在"compile-css"操作符,将CSS规则一步位的输出到文件:
(compile-css "/tmp/css.css"
'((body :margin 5px :padding 0px)))
两种方法,各有所长,殊途同归。
Footnotes
[1]: cl-css | Quickdocs: http://quickdocs.org/cl-css/
[2]: CSS3 @keyframes 规则:
http://www.w3school.com.cn/cssref/pr_keyframes.asp