你如果会用 Excel,那 Grid 就应该不陌生。
不过老实讲,我也不太会用 Excel。
其实他已经 CR 好一阵子了,目前多数主流的 CSS 框架已经开始采用。所以并不是你不会用或是没有使用到这个东西,而是你已经在用了,但是你不知道他背後是使用 Grid Layout 而已。
Grid 的基本结构就跟我刚刚提到的 Excel 很像,他是一个矩形区块,包含了栏与列的设定。具体想要解决的问题在於「排版」这件事情,但试着回想这将近 20 年来排版的变化,是不是又很像回到了 <table>
的年代呢?
Grid Layout 基本上包含了下列结构:
相较之下,他没有像是 Flexbox 有所谓的 轴方向 的问题。
基本的 Grid 容器组成就是这样,看起来很简单。由於没有 Flexbox 的主要轴、交叉轴的问题,所以操作起来相对会比 Flexbox 容易一点点。
首先,宣告一个 Grid 容器一样是使用 display
属性,
display: grid
亦即使用区块(Box Level)来设定容器。display: inline-grid
亦即使用行内(Inline Level)来设定容器。这里跟 Flexbox 一样,被定义出来的容器属於 grid formatting context,所以原本在 Flexbox 上面会失效的事情,在这边也一样会失效。
float
, clear
会被忽略。vertical-align
无法应用在 Flex 元件上。::first-line
, ::first-letter
这两个拟似元件无法套用至容器上。同样的,倘若元素指定 display: inline-grid
的话,在计算样式值(Computed Value)会呈现 grid
而不是 inline-grid
,这边也是跟 Flexbox 一模一样。
最大的不同点在於,Grid Layout 带来了 格线轨道(Grid track)的概念。
一个 Grid 容器依据横向(row)与纵向(column)来分割,这个分割的动作就是一个 格线轨道(Grid track)。这个轨道又可以区分为 网格单元(Grid cell)与 网格格线(Grid line)两个面向。然後,网格单元与格线还可以区分出 命名单元(区域) 或 命名格线 的差异。
在这里先有个底就好,後面会大量提及这些事情。
Grid 容器本身可以设定一定尺寸,但若不指定容器尺寸的情况下,Grid 容器尺寸会依照这些项目的总和来决定外部尺寸,
min-content
或 max-content
)这样会决定出 Grid 的最小或最大尺寸该是多少。通常在 轨道尺寸 够用的情况下都不会有太大问题。问题在於不够用的情况,倘若真的不够用,就会采用轨道尺寸下的 min-content
来当作轨道尺寸,你的 Grid 容器尺寸设定基本上会无效。我後面会继续举例,这边就先有个概念即可。
另外,倘若装置对於网格有其限制,那麽在网格容器内的网格格线就会被限制。
关於尺寸限制其实不太容易遇到,除非你故意的,或是你真的在一些比较特殊的显示装置要使用的时候,才必须留意这件事情。
在 Grid 容器当中,被 grid-template-rows
与 grid-template-columns
分割出来的区域,叫做网格单元(Grid cell),而这个容器单元会有所谓的格线,这个格线就是网格格线(Grid line)。
上图用数字标出来的就是网格格线(Grid line),网格格线还有分成两种:
关於 Implicit Grid 我後面会介绍,如果你想看官方解释也可以:
但我不保证看得懂。
这边与 Flex 不同的点在於,他的样式应用非常多,也相对复杂。
样式 | 可用值 | 预设值 |
---|---|---|
grid-template-columns |
none , <轨迹清单> |
none |
grid-template-rows |
none , <轨迹清单> |
none |
grid-template-areas |
none , <字串> |
none |
grid-template |
上述三个设定的简写 | none |
grid-auto-columns |
<轨迹尺寸> |
auto |
grid-auto-rows |
<轨迹尺寸> |
auto |
grid-auto-flow |
row , column , dense |
row |
grid |
上述全部的简写 | none |
以上是一个 Grid 容器可以设定,关於容器本身的样式。接着我们来看看里面的设定值到底写了些什麽东西。
我们在设定网格的时候,比较常见的作法会类似这样,
.grid-container {
display: grid;
grid-template-columns: 100px 500px;
grid-template-rows: 100px 100px 100px;
}
欧,你说我怎麽不用 fr
来当例子?这个新的单位後面会提到。这样我们就可以拥有一个很简单的网格容器,他包含了,
100px
与 500px
100px
这边也可以搭 CSS 运算涵式或关键字使用,例如,
.grid-container {
grid-template-columns: 100px repeat(50px, 3) minmax(min-content, 1vw);
}
另外,前述有提到了网格格线(Grid line),在这边可以替你的格线命名,预设在不命名的情况下,都是以 数字 来定义网格格线,
.grid-container {
grid-template-row: [first side-begin] 100px [side-ended main-begin] 100px [main-ended last];
}
格线名命名的规则就是用 []
把他包起来,这样你的格线就会有一个特别的名字。另外请留意,不要用 -start
或 -end
来当作名称,这样的命名方式会踩到网格格线的雷。另外,名字可以一样,但在指定的时候必须要特别指定你要在哪一个格线。
当你使用命名格线时,在指定网格单元时就可以使用名称,而不是去计算数字,相对来说会比较方便一些。但如果你把网格格线的名称都设定成同一个名字,那你在取用的时候还是要指定对应的数字才行。
但,都要你取名字了,尽量还是不要一样比较好。
至於
-start
与-end
的雷,後续提到隐性网格会继续讲。
grid-template-areas
的字串定义这个样式的使用方式比较特别,他是需要定义每一个 网格单元 的名字,也就是说,我们可以写成类似这样,
.grid-container {
display: grid;
grid-template-areas:
"nav nav nav"
"sidebar main main"
"sidebar main main"
"sidebar main main";
}
所以,这个时候你的 HTML 就只会有三个元件,
<div class="grid-container">
<nav class="nav">
</nav>
<aside class="sidebar">
</aside>
<main class="main">
</main>
</div>
而这三个元件搭配的设定会是这样,
.nav {
grid-area: nav;
}
.sidebar {
grid-area: sidebar;
}
.main {
grid-area: main;
}
最终你会得到这样的结构,
当然,这种写法不是没有限制的,
.
来忽略(不使用)该区域所以说,以下的写法 皆不合法,
/* 以下写法不合法 */
.grid-container {
display: grid;
grid-template-areas:
"nav nav nav"
"sidebar main main"
"sidebar sidebar main"
"sidebar main main";
}
/* 以下写法不合法 */
.grid-container {
display: grid;
grid-template-areas:
"nav nav nav"
"sidebar main main"
"sidebar . main"
"sidebar main main";
/* 以下写法不合法 */
.grid-container {
display: grid;
grid-template-areas:
"nav nav nav"
"sidebar main main"
"sidebar main"
"sidebar main main";
}
另外,除了容器本身限制之外,当你的网格元件使用了 未命名 的网格单元时,会对隐性网格格线产生副作用。这个部分我後面会再次提及。
隐性网格(Implicit Grid)在网格系统中是一个很特别的存在。官方对他的说明简单的解释可以这麽形容,
你的设定不足以画出一个网格,所以我
鸡婆的帮你把缺的格线补上。
何谓设定不足以画出网格?例如,
grid-template-columns
)或列(grid-template-rows
)grid-area
却不存在於 grid-template-areas
当中隐性网格有两个样式可以使用,
grid-auto-columns
grid-auto-rows
设定的数值仅接受这些,
auto
min-content
max-content
fr
minmax()
10%
)关於隐性网格在这边就不赘述,後面会继续提到这个东西。
网格单元的顺序其实跟 Flexbox 使用 order
的方式是一样的,不过,他可以使用 z-index
来定义哪一个格子比较高。
通常会搭配 z-index
大多数是网格容器本身有卷动需求的时候会特别这样做。
基本上网格容器的对齐跟 Flexbox 几乎是完全一样。我在这边如果再讲一次好像又太浪费篇幅。基本上以下这些东西跟 Flexbox 完全一样,
align-items
align-self
align-content
justify-content
然後网格系统多了这几个,仅能在 Grid 容器下使用,
justify-items
justify-self
place-items
place-self
place-content
间隔的部分也跟 Flexbox 使用同一套 gap
,其实就是共用同一套 w3c 的规范,
其实这边没有什麽新的东西,除了 Grid 才能使用的对齐方式外,其他的东西都跟 Flexbox 几乎一样。
justify-items
与 justify-self
是在容器系统中,Grid 单元主要轴向维度作对齐的样式设定。与 align-items
, align-self
则是交叉向维度做对齐(或填充)的样式。
Grid Layout 并没有指定主要轴与交叉轴,这边的轴向设定是跟着系统的文字流向而决定的。所以他没有像是 Flexbox 可以明确的指定谁是主要轴,谁是交叉轴。
以下稍微说明一下 Grid 多出来的几样东西,
样式 | 设定值 | 预设值 |
---|---|---|
justify-items |
normal , stretch , <baseline-position> , <overflow-position>? , [ <self-position>, left, right ] , legacy , legacy && [ left | right | center ] |
legacy |
justify-self |
auto , normal , stretch , <baseline-position>, <overflow-position>? [ <self-position>, left, right ] |
auto |
place-items |
<'align-items'> <'justify-items'>? |
无特定预设值 |
place-self |
<'align-self'> <'justify-self'>? |
无特定预设值 |
place-content |
<'align-content'> <'justify-content'>? |
无特定预设值 |
基本上可以当作是在 Flexbox 上因为需要多行而无法特别设定的东西,在 Grid 里面可以直接设定这样的样式。当然,如果你的 Grid 单元数量没有到两个栏或列以上,其实是看不出什麽效果的。
今天先这样,Grid 容器基本上东西太多,要一次讲完有点困难。明天会搭配图片来解说各种关於容器的设定,还有一些比较基本的运算方式。
目录与小节:
[CSS] Flex/Grid Layout Modules, part 1
部落格同步放送:
[CSS] Flex/Grid Layout Modules, part 6
<<: [Day03] swift & kotlin 入门篇!(1) 基础语法-变数与常数宣告
>>: [FGL] OPEN WINDOW WITH 画面档
前情提要: 在上一集解释了工具力的来源 方函式:还记得之前提到的建构式模式吗? 只要提供一个原型,就...
耶,到了第二天了,虽然还不是很懂VR软件要怎麽开发,也没有头盔,总之就先下载Unity再说~ 下...
好消息,我找到一个贴文跟一个影片,所以逛头盔这件事可以延後一点做: How to use Unity...
千丝万缕就像风一样的吹过,但总要抓住想要的那一丝一缕。 《iT邦帮忙铁人赛的观点》(以下简称铁人赛)...
本来要搭文湖线,坐到南京复兴站,结果,我到大直站就下车了,走出捷运站後,叫了计程车,回阳光街。 返回...