grid-kiss让网格制作变得更容易

发布于 大漠

去年在CSS Conf科普了一下《CSS Grid Layout》相关的概念。会后PostCSS的作者@Andrey Sitnik给我力荐grid-kiss这个PostCSS插件。说这个插件可以让CSS Grid变得更为简单。一直都想尝试一下,就是没动手,今天体验了一下,还是很有意思的。今天花点时间整理一下,跟大家一起分享。

CSS Grid是什么

在详细介绍这个插件之前,先简单的告诉大家,我们这里所说的Grid是CSS布局中的一个模块。它不是早前所说的网格系统(Grid system),而是CSS 布局自带的一个布局模块。这个模块被称为CSS Grid,也有人把其称为CSS原生网格。

如果你从未接触过CSS Grid相关的知识,建议你先阅读站上早前分享过的CSS Grid相关教程。特别推荐大家阅读这篇译文《CSS Grid布局指南》,如果你觉得译文质量不够好,你也可以移步阅读@Chris House写的原文《A Complete Guide to CSS Grid Layout》。

这里假设你已经对CSS Grid有了一定的基础了解,哪怕是最基础的知识。因为我们今天不是来介绍CSS Grid的基础知识,而是介绍如何使用PostCSS插件grid-kiss让制作网格变得更容易、更简单。如果你感兴趣的话,欢迎继续往下阅读。

grid-kiss目的

grid-kiss是PostCSS万千插件中的一个,旨在用一个形象的网格(代码中画的网格)来取代CSS Grid自带的24个属性。简单的说,就是grid-kiss把在代码中画好的网格编译出CSS Grid对应的网格属性。

先来看个示例

上面也说过了,grid-kiss是用来把画好的网格编译成CSS对应的网格属性。那究竟是怎么样的,先给大家看一个作者在Github提供的示例,让大家在脑海中有一个简单印象。

比如,在编译前的CSS代码中有这样一段代码:

body {
    grid-kiss:
        "+-------------------------------+      "
        "|           header ↑            | 120px"
        "+-------------------------------+      "
        "                                       "
        "+-- 30% ---+  +--- auto --------+      "
        "| .sidebar |  |       main      | auto "
        "+----------+  +-----------------+      "
        "                                       "
        "+-------------------------------+      "
        "|              ↓                | 60px "
        "|         → footer ←            |      "
        "+-------------------------------+      "
}

经过PostCSS编译之后出来的CSS代码:

body > header {
    grid-area: header;
    align-self: start
}

body > .sidebar {
    grid-area: sidebar
}

body > main {
    grid-area: main
}

body > footer {
    grid-area: footer;
    justify-self: center;
    align-self: end
}

body {
    display: grid;
    align-content: space-between;
    grid-template-rows: 120px 1fr 60px;
    grid-template-columns: 30% 1fr;
    grid-template-areas: 
    "header  header"
    "sidebar main  "
    "footer  footer"
}

在浏览器中将看到如下图的效果:

如果你想立马体验的话,你可以通过playground在线工具尝试一把。另外还可以在Codepen上看看@jonathanneal在Codepen上提供的插件模板

如果grid-kiss和媒体查询结合在一起,可以轻易的实现响应式布局效果。如下图所示:

是不是很神奇,是不是没想到未来的CSS还可以这么的写。可以说,大家把CSS都给玩坏了。同时也能证明@Sylvain写的这个PostCSS插件是多么的强大,又是多有意思。

配置环境

文章开头就说了grid-kiss是PostCSS的一个插件,如果你想要正常的使用这个插件,或者尝试玩一把另类的网格制作方式。那么本地就要有一个PostCSS的工作环境。当然了,如果你为了省事的话,你可以使用playground。这里还是说怎么在本地使用吧。

我个人喜欢使用PostCSS和Gulp配合使用,如果从没接触过PostCSS,也不用担心,你可以通过PostCSS深入学习这个系列中的《PostCSS深入学习:Gulp设置》一文配置好环境。接下来的内容假设你配置好PostCSS和Gulp的本地环境。

环境有了,咱们就来安装grid-kiss吧。你可以通过yarn或者npm的方式来进行安装。

yarn:

yarn add postcss-grid-kiss --dev

npm:

npm install postcss-grid-kiss --save-dev

我采用的是后面这种方式安装的。安装完成后,需要在gulpfile.js做一些简单的配置:

var gridkiss = require('postcss-grid-kiss');

gulp.task('css', function(){
    var processors = [
        // autoprefixer(browserOptions),
        cssnext(browserOptions),
        gridkiss({
            fallback: false,
            screwIE: false,
            optimizeCalc: false
        })
    ];

    return gulp.src('./src/*.css')
        .pipe(postcss(processors))
        .pipe(gulp.dest('./dest'));
});

其中最重要的,也是很关键的部分:

gridkiss({
    fallback: false,
    screwIE: false,
    optimizeCalc: false
})

这三个是grid-kiss的配置选项。具体这几个选项是什么意思?稍后介绍。为了让你能本地更好的运行起来,可以把gulpfile.jspackage.json保存到你项目的根目录下。同时建议你的测试项目结构如图那样:

这个时候打开命令终端,把路径切换到项目根目下,执行:

npm i

然后在命令终端执行gulp命令。这个时候src/style.css(编译前的样式文件)就会编译到dest/style.css(编译后的样式文件)。同时也表明你的环境是OK的。后面我们的样式都是在src/style.css中编辑。另外,你的命令终端不要关闭,这样你只要修改了style.css文件,保存之后,dest/style.css就会自动更新。

配置参数

前面的环境配置中也展示了,grid-kiss有三个选项,在使用的时候可以自行配置。

postcss([ gridkiss({ ...options }) ])

fallback

截至2016年12月,CSS Grid布局规范只是一个候选规范,并没有得到广泛的支持。到2017年3月,支持的浏览器会越来越多,Chrome和Firefox将开始默认支持Grid布局。其中,Mozilla将在3月7日发布的Firefox 52版本上开始支持。@meyerweb也说CSS Grid就要来了

那么grid-kiss提供了一个配置项fallback用来做浏览器降级处理。其默认值是false,如果把它设置为true。就会对CSS Grid做降级处理,通过positioncalc()模拟网格布局,让不支持CSS Grid的浏览器也能正常的访问。

screwIE

这个选项是用来忽略IE浏览器的降级处理,其默认值falsescrewIE生效有一个条件,那就是fallback设置了true

由于IE不支持@supports,所以grid-kiss需要通过添加一个特殊的媒体查询@media screen and (min-width:\0)只让IE识别。

如果你的项目不需要考虑IE浏览器,又为了减少编译出来的文件体积,你可以这样设置grid-kiss:

postcss([ gridkiss({ fallback: true, screwIE: true }) ])

optimizeCalc

optimizeCalc默认值是true。主要用来尽可能简化calc()表达式。和screwIE类似,如果要让optimizeCalc生效,前提是fallback设置的值为true

有关于grid-kiss这三个配置参数的详细介绍可以点击原作者做的相关阐述

grid-kiss使用方式

文章开头,看到的示例是通过中折线-和加号+来在文件中绘制网格。除此之外还有另外两种方式。

┌ ┐ └ ┘│ ─:

div {
    grid-kiss:
    "┌──────┐  ┌──────┐         "
    "│      │  │  ↑   │         "
    "│      │  │ bar →│  200px  "
    "│  ↓   │  └──────┘         "
    "│ baz  │              -    "
    "│  ↑   │  ┌──────┐         "
    "│      │  │  ↑   │  200px  "
    "└──────┘  │      │         "
    "          │ foo  │    -    "
    "┌──────┐  │      │         "
    "│ qux  │  │  ↓   │  200px  "
    "│  ↓   │  │      │         "
    "└─20em─┘  └──────┘         "
}

╔ ╗ ╚ ╝║ ═

main {
    grid-kiss:
    "╔═══════╗  ╔════════════════╗      "
    "║       ║  ║    .article    ║ auto "
    "║   ↑   ║  ╚════════════════╝      "
    "║  nav  ║  ╔════╗  ╔════════╗      "
    "║       ║  ║    ║  ║ aside →║ 240px"
    "╚═ 25% ═╝  ╚════╝  ╚═ 80em ═╝      "
}

如何绘制网格

前面简单的展示了绘制网格的方式。那么在实际绘制网格,可以依据下面几点来操作:

  • 绘制不同的区域,可以得到不同的网格。你可以使用一些工作来帮助你绘制网格,比如AsciiFlow
  • 在每个区写一个CSS选择器来匹配相应的元素。它可以是一个元素标签、类名或ID选择器或其他有效的选择器
  • 匹配的元素必须是网格元素的子元素
  • 单独的每一行由一个换行符(\n)来决定,而且每一行具有相同的缩进
  • 每一行的开始和结束由一个双引号(")来控制
  • 确定每个转角是正确对齐,可以使用+来控制,然后另一个+表示创建新一列

更多的使用方式,这里就不一一阐述了,感兴趣的可以查看插件提供的使用文档。另外把对齐方式在这里展示一下:

水平对齐方式控制

justify-content: stretch

"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"

justify-content: start

"+---+ +---+ +---+    "
"| a | | b | | c |    "
"+---+ +---+ +---+    "
"+---+ +---+ +---+    "
"| d | | e | | f |    "
"+---+ +---+ +---+    "
"+---+ +---+ +---+    "
"| g | | h | | i |    "
"+---+ +---+ +---+    "

justify-content:end

"    +---+ +---+ +---+"
"    | a | | b | | c |"
"    +---+ +---+ +---+"
"    +---+ +---+ +---+"
"    | d | | e | | f |"
"    +---+ +---+ +---+"
"    +---+ +---+ +---+"
"    | g | | h | | i |"
"    +---+ +---+ +---+"

justify-content:center

"    +---+ +---+ +---+    "
"    | a | | b | | c |    "
"    +---+ +---+ +---+    "
"    +---+ +---+ +---+    "
"    | d | | e | | f |    "
"    +---+ +---+ +---+    "
"    +---+ +---+ +---+    "
"    | g | | h | | i |    "
"    +---+ +---+ +---+    "

justify-content: space-between

"+---+    +---+    +---+"
"| a |    | b |    | c |"
"+---+    +---+    +---+"
"+---+    +---+    +---+"
"| d |    | e |    | f |"
"+---+    +---+    +---+"
"+---+    +---+    +---+"
"| g |    | h |    | i |"
"+---+    +---+    +---+"

justify-content: space-evenly

"    +---+  +---+  +---+    "
"    | a |  | b |  | c |    "
"    +---+  +---+  +---+    "
"    +---+  +---+  +---+    "
"    | d |  | e |  | f |    "
"    +---+  +---+  +---+    "
"    +---+  +---+  +---+    "
"    | g |  | h |  | i |    "
"    +---+  +---+  +---+    "

justify-content:space-around

"  +---+    +---+    +---+  "
"  | a |    | b |    | c |  "
"  +---+    +---+    +---+  "
"  +---+    +---+    +---+  "
"  | d |    | e |    | f |  "
"  +---+    +---+    +---+  "
"  +---+    +---+    +---+  "
"  | g |    | h |    | i |  "
"  +---+    +---+    +---+  "

垂直对齐方式控制

align-content: stretch

"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"

align-content: start

"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"
"                 "
"                 "

align-content: end

"                 "
"                 "
"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"

align-content: center

"                 "
"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"
"                 "

align-content: space-between

"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"                 "
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"                 "
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"

align-content: space-evenly

"                 "
"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"                 "
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"                 "
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"
"                 "

align-content: space-around

"                 "
"+---+ +---+ +---+"
"| a | | b | | c |"
"+---+ +---+ +---+"
"                 "
"                 "
"+---+ +---+ +---+"
"| d | | e | | f |"
"+---+ +---+ +---+"
"                 "
"                 "
"+---+ +---+ +---+"
"| g | | h | | i |"
"+---+ +---+ +---+"
"                 "

区域内水平对齐方式

justify-self: start

使用<

+-------------+    +-------------+  
| .item-a  <  | or | .item-a  ←  |
+-------------+    +-------------+

justify-self: end

使用>

+-------------+    +-------------+
|  >  .item-a | or |  →  .item-a |
+-------------+    +-------------+

justify-self: stretch

使用>>

+--------------+    +--------------+
| < .item-a  > | or | ← .item-a  → |
+--------------+    +--------------+

justify-self:center

使用><或者

+--------------+    +--------------+
| > .item-a  < | or | → .item-a  ← |
+--------------+    +--------------+

区域内垂直对齐方式

align-self:start

使用^或者

+-------------+    +-------------+
|   .item-a   | or |   .item-a   |
|      ^      |    |      ↑      |
+-------------+    +-------------+

align-self: end

使用v

+-------------+    +-------------+
|      v      | or |      ↓      |
|   .item-a   |    |   .item-a   |
+-------------+    +-------------+

align-self: stretch

使用^v或者

+-------------+    +-------------+
|      ^      |    |      ↑      |
|   .item-a   | or |   .item-a   |
|      v      |    |      ↓      |
+-------------+    +-------------+

align-self: center

使用v^或者

+-------------+    +-------------+
|      v      |    |      ↓      |
|   .item-a   | or |   .item-a   |
|      ^      |    |      ↑      |
+-------------+    +-------------+

上面展示了网格内对齐方式,下面来实战一下,看一个小示例:

.grid {
    grid-kiss:
        "    +-------+ +-------+ +-------+    "
        "    |  .a   | |  .b   | |  .c   |    "
        "    +-------+ +-------+ +-------+    "
        "    +-------+ +-------+ +-------+    "
        "    |  .d   | |  .e   | |  .f   |    "
        "    +-------+ +-------+ +-------+    "
        "    +-------+ +-------+ +-------+    "
        "    |  .g   | |  .h   | |  .i   |    "
        "    +-------+ +-------+ +-------+    "
        "    | 200px | | 200px | | 200px |   "
}

示例效果如下图所示:

grid-kiss中不足之处

上面演示了grid-kiss制作CSS Grid。那么是不是就说grid-kiss就完全能编译出CSS Grid规范中对应中所有的属性呢?那么支持的属性有:

  • display:grid
  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • justify-content
  • align-content
  • grid-area
  • justify-self
  • align-self

不支持的属性有:

  • grid-column-gap
  • grid-row-gap
  • grid-gap
  • justify-items
  • align-items
  • grid-auto-columns
  • grid-auto-rows
  • grid-auto-flow
  • grid
  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
  • grid-column
  • grid-row

有关于这方面的详细介绍,可以点击这里

总结

如果你耐心的看到这里,那说明你对grid-kiss有所了解了。如果你跟着上面的一起操作过的话,那你对其有了更深入的了解。由于CSS Grid还没有得到很好的支持,不过这样尝试也不未尝不可。自己尝试下来,虽然它能更形象的帮助我们实现CSS Grid布局。但并不能说他就是万能的,比如说前面就提到过,这个插件还有很多CSS Grid对应的属性不支持。抛开这方面而言,在编辑器里绘制多格还是需要一定的时间,如果你是处女座,那有可能更纠结。另外如果你对CSS Grid的每个属性都非常的了解的话,使用手写属性制作网格有可能还是要比这个方式更快。

今天把这个抛出来,让大家体验一下另类的CSS玩法。特别是有了PostCSS之后,可以说,CSS可以有更多的玩法。如果你感兴趣,你也可以玩出另类。(^_^)。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.fedev.cn/preprocessor/keep-css-grids-simple-with-postcss-grid-kiss.htmlNike Shox TLX 0018