你用什么姿势使用CSS Grid?

1,333 阅读4分钟

Grid 是一个栅栏系统,你可以把它想像成他是一个 Table,有一些像是 Table 的概念例如合并储存格 行列、直列

与 Flexbox 相比,就是从一维变成了二维,占比是可由内外部决定,大部分情况是由外部宣告

来看一下语法

先确认一下 CSS Grid 会长什么样子

.grid-wrapper{
  display: grid;
  grid-auto-flow: column dense;
  grid-auto-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 0px 0px;
}

or

.grid-wrapper{
 grid-template-areas:
    ". head"
    "nav main"
    ". footer";
}
.header  { grid-area: 1 / 1 / 2 / 4 }
.main    { grid-area: 2 / 1 / 4 / 2 }
.anv { grid-area: 2 / 3 / 5 / 4 }
.footer  { grid-area: 4 / 1 / 5 / 2 }

看起来有点杂,但其实我们主要会用到 grid-template-columngap

  • grid-template-column 代表横列放几个,并且占比多少
  • grid-template-row 代表直列放几个,并且占比多少,不过如果我们想要做到 flexbox 那样自动超出占比换行,设定为 1fr 即可
  • gap 内间距,下面会提到

内间距 Gap

在 Grid 中,不使用 百分比做网格,而是真的实际的占用几块 (ex: 5fr),所以不会有 Gap 不被百分比计算的问题 (ex: Flexbox), 这部分对 Grid 来说是相对优势,因为就不需要在外层使用 Row 负margin 来做抵销 Col Padding

确认对齐

先测试一下对齐方式,深入你记忆中。

CleanShot 2023-10-27 at 11.44.48@2x.png

演示連結

为什么排版是填满的,明明我的宽度就是设定 auto?

CleanShot 2023-10-27 at 11.45.11@2x.png 没错,这就是 Flexbox 跟 Grid 的对齐特性,在 Normal 的情况下子项目会填满,如果你不想填满,那你需要给他对齐模式。

然后我们会发现,他一样像 Flexbox 一样,虽然一样有 Column、Row, 但没有 的主轴与交错线不同的问题,

另外 items 跟 content 的定义也需要明确厘清 (ex: align-items、align-content)

  • items: 个别项目对齐
  • content: 内容对齐方式
  • place-content: 同时设定 align-content 和 justify-content
  • place-items: 同时设定 align-items 和 justify-items

排列方向

左到右排列,还是上到下排列,类似 flex-direction

Flexbox column 的对齐演示,就是使用这样的方式,我希望他从上到下 超过换行,而不是从左到右 超过换行 Sample

.grid-wrapper{
    grid-auto-flow: column;
}

使用元件来做

import {Grid} from 'bear-react-grid';

<Grid col={3} className="g-4">
    <div>child</div>
    <div>child</div>
    <div>child</div>
</Grid>

这样代表 grid-auto-columns: repeat(3, auto),CSS IN JS 会得 children.count() 作为一般排版使用 Gap 为 2px 但如果你今天是要做商品列表,你可以指定占比:

import {Grid, auto} from 'bear-react-grid';

<Grid col={auto(3)} className="g-3">
    <div>child 1</div>
    <div>child 2</div>
    <div>child 3</div>
    <div>child 4</div>
    <div>child 5</div>
    <div>child 6</div>
</Grid>

这样就会 3个一列,多出3个自动换行

相关参数可参照 CSS Grid Component

对齐

如果要对齐,你可以使用公用类样式:

import {Grid} from 'bear-react-grid';

<Grid col={3} className="justify-content-start align-content-start g-3"
>
    <div>child 1</div>
    <div>child 2</div>
    <div>child 3</div>
</Grid>

公用类样式也有提供响应式设定

合并

如果你有合并需求,或是你想要由内部决定,你可以:

import {Grid} from 'bear-react-grid';

<Grid col={3} className="g-3">
    <div className="g-col-2">child 1</div>
    <div>child 2</div>
    <div className="g-col-2">child 1</div>
    <div>child 2</div>
</Grid>

相关参数可参照 CSS Grid Col Component

响应式

如果你有响应式的需求,你可以:

import {Grid, auto} from 'bear-react-grid';

<Grid col={1} md={`200px ${auto(2)}`} className="g-3">

    <div className="g-col-md-2">child 1</div>
    <div>child 2</div>
    <div>child 3</div>
    <div>child 4</div>
</Grid>

结论 (2023.10.27 更新)

在常规的时候,我建议直接使用组合技

  • Layout
    • Container(ex: g-?) > Row(ex: g-?) > Col + Utilities CSS
    • Container(ex: g-?) > Col + Utilities CSS
    • Col + Utilities CSS
  • Card List in % (不是依卡片本身的宽度)
    • Grid + Utilities CSS(ex: g-?)

      因為 Flex not use % + gap

  • Card
    • Flex + Utilities CSS(ex: gap-?)
    • Grid + Utilities CSS(ex: g-?) (如果Flex不好處理就使用)

例如

import {auto,Flex,Grid} from 'bear-react-grid';

<Flex className="gap-3">

等同於

<Grid col={auto(2)} className="justify-content-start">

<Flex col="column" className="g-3">

等同於

<Grid col={1}>

可以 Flex,就不一定需要 Grid,因为你可能还需要处理 对齐的问题来取消自动撑开

而对于复杂样式的时候,例如一个甘特图,切分各区块的命名,那就额外宣告一个 Styled-component 去定义

这边也推荐一个方便制作复杂 Grid 的工具 grid.layoutit.com/

以上使用的 Grid 元件是 bear-react-grid

bear-react-grid.pages.dev 首页也是使用这个方式来排版

不管使用的是什么CSS工具(scss、css module、bootstrap、uno、tailwind css 等等),但一定要要有栅栏可以统一排版方式,與快速排版的功能 即正确的姿势


2023.10.18 补充一下,因为有小伙伴觉得这个 Blog 玩玩就好,如果是公司在用的话还是算了,不是的,其实我不管在公司产品、专案 或者 接案都是用这个方案来实作

我想说的重点是,你需要有一个负责排版的系统 boostrap grid styem 或是 tailwind grid system 也好,都行。只要不是瞎所有自定义,「一句我想跟设计稿一样」

而我选的是 styled-components + boostrap 设计模式的 自开发 CSS IN JS