On CL-CSS

in common-lisp •  7 years ago  (edited)

记录使用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规则

  1. 创建css.lisp文件

  2. 创建全局变量来代表某条CSS规则

    (defparameter *key*
      `((".keys"
         :display "flex")))
    
    (defparameter *do-not-use-right-key*
      `((".keys"
         :user-select "none")))
    
  3. 拼接多条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

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!