资讯专栏INFORMATION COLUMN

[译] Grid 布局完全指南

Baoyuan / 676人阅读

摘要:如果你定义的内容包含重复部分,你可以使用标记去组织它。另外,也有一个比较复杂但是方便的语法指定三个属性,示例如下与以下代码是等价的因为无法隐式重置属性,与。

简介

CSS 栅格布局 (亦称 "Grid"),是一个基于栅格的二维布局系统,旨在彻底改变基于网格用户界面的设计。CSS 一直以来并没有把布局做的足够好。刚开始,我们使用 tables,后来是 floats,positioning 和 inline-block,这些本质上是一些 hacks 而且许多重要功能尚未解决(例如垂直居中)。Flexbox 可以做到这些,但是它主要用来一些简单的一维布局,并不适合复杂的二维布局(当然 Flexbox 与 Grid 可以一并使用)。Grid 是第一个为了解决布局问题的 CSS 模块,只要我们做过网页,就会遇到这些问题。

有两件事情在激励着我创作这篇指南,首先是 Rachel Andrew 那本非常不错的书 Get Ready for CSS Grid Layout.,清晰透彻地介绍了 Grid,它是本篇文章的基础。我强烈建议你去购买并且阅读它。另一件事是 Chris Coyier 的文章 A Complete Guide to Flexbox,是关于 flexbox 的首选资源。它帮助了很多人,当你 Google "flexbox" 的时候,第一眼便能够看见它。或许你已经注意到我的文章与它有很大相似之处,但我们有什么理由不借鉴它呢?

我会把 Grid 在最新版本规范上的概念呈现出来。因此,我将不会照顾过期的 IE 语法。当规范成熟时,我将尽可能去定期更新。

基础与浏览器支持

开始 Grid 是简单的,你仅仅需要在容器(container)元素上定义一个栅格使用 display: grid,并通过 grid-template-columnsgrid-template-rows 设置行与列。通过设置 grid-columngrid-row 把子元素置于栅格中。与 flexbox 类似,栅格项目(items)的顺序是无关紧要的,你可以通过 CSS 来控制顺序。当使用媒体查询时,改变它们的顺序是极其简单的。假设你设计好了网页的布局,但你需要适应不同的屏幕宽度,这仅仅需要几行代码,Grid 是最为有效的模块。

关于 Grid 一件非常重要的事情是你还不能够在生产环境中使用它。它目前仅仅是一个 W3C工作草案,而且不能够被任何浏览器默认支持。虽然IE10 与 IE11 能够支持它,但使用了过期语法旧的实现。为了现在能够体验 Grid,最好的方法是使用 Chrome, Opera 或者 Firefox,并且开启特定的标志。在 Chrome 中,导航到 chrome://flags 并且开启 “experimental web platform features”。在 Opera 中同样如此(opera://flags)。在 Firefox 中,开启标志 layout.css.grid.enabled(about:config)。

这有一张浏览器支持表格,我将保持更新。

Chrome 29+ (Behind flag)
Safari Not supported
Firefox 40+ (Behind flag)
Opera 28+ (Behind flag)
IE 10+ (Old syntax)
Android Not supported
iOS Not supported

译者注:现在有些最新浏览器的最新版本已经能够支持,可以查看 caniuse 网站。

你在生产环境中使用它仅仅是一个时间问题。但是,学习正在当下!

重要术语

在深入了解 Grid 概念之前,了解它的术语是极为重要的。因为在此涉及到的术语概念相似,不易混淆。不过不用担心,他们并没有很多。

Grid Container (栅格容器)

设置 display: grid 的元素,它是所有栅格项目的直接父级元素。在这个例子中,container 是栅格的容器。

Grid Item (栅格项目)

栅格容器的直接子代。在这里 item 是栅格项目,而 sub-item 不是栅格项目。

Grid Line (栅格线)

组成栅格结构的分割线。它们位于行与列的两侧,有的是垂直的(列栅格线),有的是水平的(行栅格线)。以下黄色线是一个列栅格线。

Grid Track (栅格轨迹)

相邻栅格线的区域。你可以认为他们是栅格的一行或者一列。以下是第二与第三栅格线间的栅格轨迹。

Grid Cell (栅格格子)

相邻行栅格线与相邻列栅格线间的区域。它是栅格的独立“单元”。以下栅格格子位于1,2行栅格线与2,3列栅格线间。

Grid Area (栅格区域)

被四个栅格线围绕的区域。一个栅格区域由任意数量的栅格格子组成。以下栅格区域位于1,3行栅格线与1,3列栅格线间。

栅格属性内容表

属于栅格容器的属性:

display

grid-template-columns

grid-template-rows

grid-template-areas

grid-column-gap

grid-row-gap

grid-gap

justify-items

align-items

justify-content

align-content

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-area

justify-self

align-self

栅格容器属性(Grid Container) display

定义该元素为栅格项目,并且为它的内容建立一个新的栅格格式上下文(grid formatting context)

译者注:还记得 BFC 与 IFC 吗?

属性值:

grid 生成块状栅格

inline-grid 生成行间栅格

subgrid 如果你的栅格容器本身是一个栅格项目的话(例如:嵌套栅格),你可以根据它的父元素而不是它自己,指定行列大小。

.container{
  display: grid | inline-grid | subgrid;
}

注意:columnfloatclearvertical-align 在栅格容器上无效。

grid-template-columns
grid-template-rows

通过空格分隔的值定义栅格的行与列。值代表轨迹大小(track size),它们中间的间隙代表栅格线。

属性值:

可以是长度,百分比,或者栅格中的空白空间(使用 fr

任意名字,任君选择

.container{
  grid-template-columns:  ... |   ...;
  grid-template-rows:  ... |   ...;
}

示例:

当你在轨迹值之间预留空格时,栅格线会被自动分配为数值名字。

.container{
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

你也可以为栅格线设置名字,注意栅格线名字的括号语法:

.container{
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

注意一条线可以有多个名字。例如,这里第二条线有两个名字:row1-end 和 row2-start。

.container{
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

如果你定义的内容包含重复部分,你可以使用 repeat() 标记去组织它。

.container{
  grid-template-columns: repeat(3, 20px [col-start]) 5%;
}

与以下代码是等价的

.container{
  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}

fr 允许你设置轨迹大小为栅格容器的一部分。例如,以下示例将设置每个项目为栅格容器的三分之一。

.container{
  grid-template-columns: 1fr 1fr 1fr;
}

空白空间将在固定项目 之后 被计算。在这个例子中,给 fr 分配的全部空余时间不包括 50px。

.container{
  grid-template-columns: 1fr 50px 1fr 1fr;
}
grid-template-areas

通过指定栅格区域的名字来定义栅格模板,这样栅格项目会通过 grid-area 属性来指定区域。重复栅格区域的名字将会合并栅格格子,一个句点表示一个空的栅格格子。语法本身提供了一个可视化的栅格结构。

属性值:

在项目中使用 grid-area 属性指定的栅格区域

. 句点表示空白栅格格子

none 不定义栅格区域

.container{
  grid-template-areas: " | . | none | ..."
                       "..."
}

示例:

.item-a{
  grid-area: header;
}
.item-b{
  grid-area: main;
}
.item-c{
  grid-area: sidebar;
}
.item-d{
  grid-area: footer;
}

.container{
  grid-template-columns: 50px 50px 50px 50px;
  grid-template-rows: auto;
  grid-template-areas: "header header header header"
                       "main main . sidebar"
                       "footer footer footer footer"
}

这将建造一个三行四列的栅格。第一行全部由 header 区域组成,第二行由两个 main 区域,一个空白格子与一个 sidebar 区域组成。最后一行全部由 footer 组成。

你声明的每行都需要有相同数量的栅格格子。

你可以使用任意数量无空格分割的相邻句点去表示单个空白栅格格子。

译者注:grid-template-areas: "first . last"grid-template-areas: "first ...... last" 等价。

注意,这种语法仅仅能命名区域,而无法命名栅格线。实际上,当你使用这种语法的时候,栅格区域两端的栅格线已被自动命名。如果你的栅格区域叫 foo,栅格区域开始的行与列将被命名为 foo-start,而结束的行与列将被命名为 foo-end。这意味着一些栅格线会有很多名字,比如上述例子的最左边的栅格线将会有三个名字:header-start, main-start 和 footer-start。

grid-template

grid-template-columnsgrid-template-rowsgrid-template-areas 的简写。

属性值:

none 设置这三个属性为初始属性

subgrid 设置 grid-template-rowsgrid-template-columnssubgridgrid-template-areas 为初始值。

/ 设置 grid-template-columnsgrid-template-rows 为各自指定的值。而 grid-template-areasnone

.container{
  grid-template: none | subgrid |  / ;
}

另外,也有一个比较复杂但是方便的语法指定三个属性,示例如下

.container{
  grid-template: auto 50px auto /
    [row1-start] 25px "header header header" [row1-end]
    [row2-start] "footer footer footer" 25px [row2-end];
}

与以下代码是等价的:

.container{
  grid-template-columns: auto 50px auto;
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-areas: 
    "header header header" 
    "footer footer footer";
}

因为 grid-template 无法 隐式 重置属性(grid-auto-columnsgrid-auto-rowsgrid-auto-flow)。或许你想做更多的事,那么推荐你使用 grid 属性去替代 grid-template

grid-column-gap
grid-row-gap

指定栅格线的大小,你可以理解它为设置行/列间隙。

属性值:

长度值

.container{
  grid-column-gap: ;
  grid-row-gap: ;
}

示例:

.container{
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  grid-column-gap: 10px;
  grid-row-gap: 15px;
}

栅格间隙仅仅在行/列 之间,不包括最外部的边。

grid-gap

grid-column-gapgrid-row-gap 的简写。

属性值:

长度值

.container{
  grid-gap:  ;
}

示例:

.container{
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  grid-gap: 10px 15px;
}

如果没有设置 grid-row-gap,它将于 grid-column-gap 保持一致。

justify-items

使栅格项目中的内容与 轴对齐(相应地,align-items 轴对齐)。这个属性值应用在容器中的所有项目上。

属性值:

start 使内容与栅格区域左侧对齐

end 使内容与栅格区域右侧对齐

center 使内容在栅格区域中居中

stretch 使内容充满整个栅格区域的宽(默认属性)

.container{
  justify-items: start | end | center | stretch;
}

示例

.container{
  justify-items: start;
}

.container{
  justify-items: end;
}

.container{
  justify-items: center;
}

.container{
  justify-items: stretch;
}

这个行为也可以通过 justify-self 属性设置在独立的栅格项目上。

align-items

使栅格项目中的内容与 轴对齐(相应地,justify-items 轴对齐)。这个属性值应用在容器中的所有项目上。

属性值:

start 使内容与栅格区域顶部对齐

end 使内容与栅格区域底部对齐

center 使内容在栅格区域中居中

stretch 使内容充满整个栅格区域的高(默认属性)

.container{
  align-items: start | end | center | stretch;
}

示例:

.container{
  align-items: start;
}

.container{
  align-items: end;
}

.container{
  align-items: center;
}

.container{
  align-items: stretch;
}

这个行为也可以通过 align-self 属性设置在独立的栅格项目上。

justify-content

有时候,栅格的总大小小于栅格容器的大小,比如你使用 px 给所有的栅格项目设置了固定大小。本例中,你可以设置栅格容器中栅格的对齐。这个属性会使栅格与 轴对齐(相应地,align-content 会使栅格与 轴对齐)。

属性值:

start 与栅格容器的左侧对齐

end 与栅格容器的右侧对齐

center 在栅格容器中居中

stretch 调整栅格项目的大小,使栅格充满整个栅格容器。

space-around 每两个项目之间留有相同的空白,在最左端与最右端为一半大小的空白。

space-between 每两个项目之间留有相同的空白,在最左端与最右端不留空白。

space-evenly 每两个项目之间留有相同的空白,包括两端。

.container {
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}

示例:

.container{
  justify-content: start;
}

.container{
  justify-content: end;  
}

.container{
  justify-content: center;  
}

.container{
  justify-content: stretch;  
}

.container{
  justify-content: space-around;  
}

.container{
  justify-content: space-between;  
}

.container{
  justify-content: space-evenly;  
}

align-content

有时候,栅格的总大小小于栅格容器的大小,比如你使用 px 给所有的栅格项目设置了固定大小。本例中,你可以设置栅格容器中栅格的对齐。这个属性会使栅格与 轴对齐(相应地,align-content 会使栅格与 轴对齐)。

属性值:

start 与栅格容器的顶部对齐

end 与栅格容器的底部对齐

center 在栅格容器中居中

stretch 调整栅格项目的大小,使栅格充满整个栅格容器。

space-around 每两个项目之间留有相同的空白,在最左端与最右端为一半大小的空白。

space-between 每两个项目之间留有相同的空白,在最左端与最右端不留空白。

space-evenly 每两个项目之间留有相同的空白,包括两端。

.container{
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}

示例:

.container{
  align-content: start;  
}

.container{
  align-content: end;  
}

.container{
  align-content: center;  
}

.container{
  align-content: stretch;  
}

.container{
  align-content: space-around;  
}

.container{
  align-content: space-between;  
}

.container{
  align-content: space-evenly;  
}

grid-auto-columns
grid-auto-rows

指定自动生成的栅格轨迹的大小(亦称隐式栅格轨迹)。当你显式定位行与列的时候(通过 grid-template-rows / grid-template-columns),隐式栅格轨迹会在定义的栅格外被创建。

属性值:

可以是长度,百分比或者 fr

.container{
  grid-auto-columns:  ...;
  grid-auto-rows:  ...;
}

举例了解隐式栅格轨迹是如何被创建的,考虑以下示例:

.container{
  grid-template-columns: 60px 60px;
  grid-template-rows: 90px 90px
}

本示例建造了 2 * 2 的栅格。

你使用 [grid-column](#prop-grid-column) 与 grid-row 去定位你的项目如下:

.item-a{
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}
.item-b{
  grid-column: 5 / 6;
  grid-row: 2 / 3;
}

我们告知 .item-b 在 5-6 列间,但我们从未定义第五列或者第六列。因为我们引用的栅格线不存在,宽度为0的隐式栅格轨迹将会创建去填充空白。我们可以使用 grid-auto-columnsgrid-auto-rows 去指定这些轨迹的宽。

译者注:经译者测试,并非以宽度为0的 implicit track 去填充。w3c auto-tracks 上表明 grid-auto-columns 的默认值为 auto,则超过的列将会平分空白空间。

.container{
  grid-auto-columns: 60px;
}

grid-auto-flow

如果你的栅格项目没有显式地在栅格中设置位置,自动放置算法便会生效。这个属性控制自动放置算法的的运作。

属性值:

row 自动放置算法将按行依次排列,按需添加新行。

column 自动放置算法将按列依次排列,按需添加新列。

dense 如果较小的项目出现靠后时,自动防止算法将尽可能早地填充栅格的空白格子

.container{
  grid-auto-flow: row | column | row dense | column dense
}

注意 dense 可能使你的项目次序颠倒。

示例:

考虑以下 html:

item-a
item-b
item-c
item-d
item-e

你定义了一个两行五列的栅格,并设置它的 grid-auto-flow 属性为 row (默认属性便是 row)。

.container{
    display: grid;
    grid-template-columns: 60px 60px 60px 60px 60px;
    grid-template-rows: 30px 30px;
    grid-auto-flow: row;
}

当我们把项目放置在栅格中的时候,明确指定以下两个项目的位置

.item-a{
    grid-column: 1;
    grid-row: 1 / 3;
}
.item-e{
    grid-column: 5;
    grid-row: 1 / 3;
}

因为我们设置了 grid-auto-flow 属性为 row,呈现在我们眼前的栅格便是如下这个样子。注意,这三个项目(item-bitem-citem-d)并没有特意指定位置。

如果设置 grid-auto-flow 的属性为 column,item-bitem-citem-d** 将按列以此排序。

.container{
    display: grid;
    grid-template-columns: 60px 60px 60px 60px 60px;
    grid-template-rows: 30px 30px;
    grid-auto-flow: column;
}

grid

以下属性的缩写:grid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columns,与 [grid-auto-flow](#prop-grid-auto-flow)。它也可以设置 grid-column-gapgrid-row-gap为默认值,即使并没有在 grid 中明确设置。

属性值:

none 设置所有子属性的值为初始值。

/ 仅仅设置这两个属性值,其它子属性值为初始值。

[ [ / ] ] 如果 grid-auto-columns 属性值确实,则采用 grid-auto-rows的值。如果属性值均缺失,则采用默认值。

.container{
    grid: none |  /  |  [ [/ ]];
}

以下两种写法是等价的:

.container{
    grid: 200px auto / 1fr auto 1fr;
}
.container{
    grid-template-rows: 200px auto;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: none;
}

以下两种写法也是等价的:

.container{
    grid: column 1fr / auto;
}
.container{
    grid-auto-flow: column;
    grid-auto-rows: 1fr;
    grid-auto-columns: auto;
}

另外你可以设置更为复杂但相当方便的语法一次性设置所有属性。你可以指定grid-template-areasgrid-auto-rowsgrid-auto-columns,其他子属性将被设为默认值。你需要指定栅格线与轨迹大小,这很容易用一个例子表示:

.container{
    grid: [row1-start] "header header header" 1fr [row1-end]
          [row2-start] "footer footer footer" 25px [row2-end]
          / auto 50px auto;
}

与以下写法是等价的:

.container{
    grid-template-areas: "header header header"
                         "footer footer footer";
    grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
    grid-template-columns: auto 50px auto;    
}
栅格项目属性 (Grid Items) grid-column-start
grid-column-end
grid-row-start
grid-row-end

通过指定栅格线来确定栅格项目的位置。grid-column-start / grid-row-start 代表项目开始的线,grid-column-end/grid-row-end 代表项目结束的线。

属性值:

可以是一个表示栅格线名字或数字。

span 项目将横跨指定数量栅格轨迹

span 项目将横跨至指定名字的栅格线

auto 自动放置,自动跨越轨迹或者默认跨越轨迹

.item{
  grid-column-start:  |  | span  | span  | auto
  grid-column-end:  |  | span  | span  | auto
  grid-row-start:  |  | span  | span  | auto
  grid-row-end:  |  | span  | span  | auto
}

示例:

.item-a{
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start
  grid-row-end: 3
}

.item-b{
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2
  grid-row-end: span 2
}

如果没有指定 grid-column-end/grid-row-end,项目默认横跨一个轨迹。

项目可能会互相重叠,你可以使用 z-index 控制它们的层叠顺序(stacking order)。

grid-column
grid-row

各自表示grid-column-start + grid-column-endgrid-row-start + grid-row-end的缩写。

属性值:

/ 接收 grid-column-start 同样的属性值,包括 span

.item{
  grid-column:  /  |  / span ;
  grid-row:  /  |  / span ;
}

Example:

.item-c{
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}

如果没有指定 end line,项目将默认跨越一个轨迹。

grid-area

当创建栅格容器使用 grid-template-areas 属性时,可以通过制定区域名字确定栅格项目的位置。同样,它也可以作为以下属性的缩写:grid-row-start + grid-column-start + grid-row-end + grid-column-end

属性值:

/ / /

.item{
  grid-area:  |  /  /  / ;
}

示例:

你可以给项目设置名字:

.item-d{
  grid-area: header
}

也可以作为grid-row-start + grid-column-start + grid-row-end + grid-column-end 的缩写:

.item-d{
  grid-area: 1 / col4-start / last-line / 6
}

justify-self

使栅格项目中的内容与 轴对齐(相应地,align-self 轴对齐)。本属性值适用于单个项目的内容。

属性值:

start 使内容与栅格区域左侧对齐

end 使内容与栅格区域右侧对齐

center 使内容在栅格区域中居中

stretch 使内容充满整个栅格区域的宽(默认属性)

.item{
  justify-self: start | end | center | stretch;
}

示例:

.item-a{
  justify-self: start;
}

.item-a{
  justify-self: end;
}

.item-a{
  justify-self: center;
}

.item-a{
  justify-self: stretch;
}

为了对栅格项目中的所有项目设置对齐,可以是指栅格容器的 justify-items 属性。

align-self

使栅格项目中的内容与 轴对齐(相应地,justify-self轴对齐)。本属性值适用于单个项目的内容。

属性值:

start 使内容与栅格区域顶部对齐

end 使内容与栅格区域底部对齐

center 使内容在栅格区域中居中

stretch 使内容充满整个栅格区域的高(默认属性)

.item{
  align-self: start | end | center | stretch;
}

示例:

.item-a{
  align-self: start;
}

.item-a{
  align-self: end;
}

.item-a{
  align-self: center;
}

.item-a{
  align-self: stretch;
}

为了对栅格项目中的所有项目设置对齐,可以设置栅格容器的 align-items 属性。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/116460.html

相关文章

  • 面试宝典

    摘要:有谈谈面试与面试题对于前端面试的一些看法。动态规划算法的思想及实现方法帮大家理清动态规划的解决思路以及原理方法前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。极客学院前端练习题道练习题,面试季练练手。 由数据绑定和排序引入的几个 JavaScript 知识点 在 JavaScript 的数据绑定和做简单的表格排序中遇到的几个知识点 [[JS 基础...

    neu 评论0 收藏0
  • Flexbox完全指南

    摘要:本文译自这里,针对本文介绍的属性列个提纲伸缩容器属性伸缩项目属性以后再布局时可以考虑用啦背景布局模块目前上一次工作草案的叫法旨在提供一种更高效的方式来布局排列及分配容器中项目的空间,即便容器大小是未知或动态变化的因此称为。 本文译自 A Complete Guide to Flexbox这里,针对本文介绍的属性列个提纲: 伸缩容器属性: display flex-direction...

    pekonchan 评论0 收藏0
  • CSS及布局

    摘要:经过半年的打磨,正式发布,主要是新增了一些常用组件,并使用命名,为接下来的微信小程序开发做好准备。这两种方式实现的瀑布流式布局均支持首屏和网页窗口大小改变时的列数自适应。主要是对于标准里的布局方式草案中的布局方式进行一些总结。 一劳永逸的搞定 flex 布局 寻根溯源话布局 一切都始于这样一个问题:怎样通过 CSS 简单而优雅的实现水平、垂直同时居中。记得刚开始学习 CSS 的时候,看...

    jaysun 评论0 收藏0
  • HTML-CSS-JS

    摘要:本周于上海闭幕,掘金和知乎上都有对应的实录和问答,但会议的视频目前都还没放出来,有心的同学如果找到了欢迎分享。建议中英文对照阅读。英文原文前端独立技术博客推荐推荐一些现在还在坚持原创的博主,有业界大牛,也有小鲜肉,也有国外美女。 CSS 样式书写规范最佳实践 本文的所列是实践当中得出的一套比较不错的 CSS 书写规范,可以结合自身团队发展出一套适合自己业务的规范。 CSS中的字体与排版...

    mikasa 评论0 收藏0

发表评论

0条评论

Baoyuan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<