Grid 布局系统

CSS Grid Layout Level 1

我们一直用传统的 CSS 布局我们的网页,但是这种布局并不是很方便,我们用 table,用 float,用 inline-block,等等方法,但是这些方法其实都算是无奈的 hack 方法,无法直接达到目的,而且还常常会产生一些别的问题。

Grid 布局系统是一种新的 CSS 布局系统,有强大的控制块及其内容的尺寸和位置的能力,跟 Flexible Box 布局系统不一样的是,Flexible Box 布局是以单条坐标轴方向进行布局的,但是 Grid 布局优化为二维布局,就是说内容可以在两个维度上进行对齐。Grid 是第一个专门为解决布局问题而开发 CSS 模块。

​ Flex 布局

Exemplary Flex Layout Example

​ Grid 布局

Exemplary Grid Layout Example

在 Grid 布局中,容器内的内容将通过定位并对准网格来布置的,网格就是一系列水平和垂直线的相交集合,它将网格容器的空间划分为网格区域,使网格元素(网格容器里的内容)可以为放置在该区域中。

这里有两组网格线,一组沿着 block 轴(column轴)延伸,一组沿着 line 轴(row轴)延伸。

Grid Lines 网格线

grid line 就是网格的水平和垂直分界线。网格线可以是 column 轴 或者是 row 轴

它们可以通过数字来指定,或者指定的名称来指定,网格元素就是根据参考着网格线的位置属性来决定位置的。

#grid {
  display: grid;
  grid-template-columns: 150px 1fr;
  grid-template-rows: 50px 1fr 50px;
}

#item1 {
  grid-column: 2;
  grid-row-start: 1;
  grid-row-end: 4;
}
/* equivalent layout to the prior example, but using named lines */
#grid {
  display: grid;
  grid-template-columns: 150px [item1-start] 1fr [item1-end];
  grid-template-rows: [item1-start] 50px 1fr 50px [item1-end];
}

#item1 {
  grid-column: item1-start / item1-end;
  grid-row: item1-start / item1-end;
}

Grid Tracks 网格轨道

grid Track,就是指两条相邻网格线之间的那部分空间,换句话说就是 grid columngrid row 的一个通用术语,每个网格轨道都被分配了一个尺寸设置,用来控制网格轨道的宽度或可以增长到多宽。相邻的网格轨道可以用grid-gap 属性分隔,也可以紧密相连。

Grid Cells 网格单元格

grid cellsgrid rowgrid column 的交集,它是定位网格元素的最小可参考单位。

#grid {
  display: grid;
  grid-template-columns: 150px 1fr;  /* two columns */
  grid-template-rows: 50px 1fr 50px; /* three rows  */
}

Grid Areas 网格区域

grid areas 是用于布置一个或多个网格项目的逻辑空间,一个 grid area 由一个或多个 grid cell 组成, 并且必须由 4 条边界线包围。grid area 可以通过 grid-template-areas 属性被显式命名,也可以由其边界网格线隐式引用。使用 grid-placement 属性可以将 grid item 分配到某个 grid area

/* using the template syntax */
#grid  {
  display: grid;
  grid-template-areas: ". a"
                       "b a"
                       ". a";
  grid-template-columns: 150px 1fr;
  grid-template-rows: 50px 1fr 50px;
}

#item1 { grid-area: a }
#item2 { grid-area: b }
#item3 { grid-area: b }

/* Align items 2 and 3 at different points in the grid area "b".  */
/* By default, grid items are stretched to fit their grid area    */
/* and these items would layer one over the other. */
#item2 { align-self: start; }
#item3 { justify-self: end; align-self: end; }

https://codepen.io/bubupu/pen/vJbNqg

在同一个 grid area 里的 grid item 互相之间不会直接影响彼此的布局,然而间接地,具有固定尺寸的 grid item 会影响到 grid track 的大小(并且因此影响到 grid track 的位置),这又可以影响到另一个 grid item 的位置或大小。

Grid Container 属性

Name: 'display'
New Values: grid \ inline-grid

这个属性将元素定义为 grid container,并为其内容建立新的网格化上下文。

grid : 元素生成块级 grid container

inline-grid : 元素生成行内块级 grid container

column,float,clear 和 vertical-align 在 grid container 中都是无效的。

Name: 'grid-template-columns', 'grid-template-rows'
Value: none \ \

这个属性指定了分隔的 grid track 列表的尺寸和 grid line 的名称。

none : 表示没有明确指定的 grid track

| : 为轨道列表指定一系列的尺寸大小和分割线名称


= [ ? [ | ] ] + ?

= [ ? [ | ] ] * ?

​ [ ? [ | ] ] * ?

= | minmax( , ) | fit-content(

)

= | minmax( , ) | minmax( <inflexible-

​ breadth> , )

= | | min-content | max-content | auto

= | min-content | max-content | auto

=

= '[' * ']'


: or 是相对于网格列轨道中网格容器的 inline 尺寸,以及行轨道中的网格容器的 block 大小。如果网格容器的大小依赖于它的轨道大小,那么 就会被视为 auto。

: 单位为 'fr' 的非负尺寸,表示轨道的弹性因子。每个 尺寸会按照弹性因子的比例占据剩余的空间份额,具体参考之前介绍 flex 弹性盒子。

如果 flex 尺寸被 minmax() 包围,那么就会应用一个最小值 ,例如: minmax(auto, )

max-content : 表示占据网格轨道的最大内容网格元素的尺寸

min-content : 表示占据网格轨道的最小内容网格元素的尺寸

minmax(min, max) : 定义大于或等于 min 且小于或等于 max 的大小范围,如果 max < min, 那么 max 的值会被忽略,minmax(min, max) 就等于 min,如果 max 值被设置为 ,那 max 就会是无效的。

auto : 最大值和 max-content 相同,最小值代表占用网格轨道的网格物体的最小尺寸(由最小宽度/最小高度指定)。

Example:

grid-template-columns: 100px 1fr max-content minmax(min-content, 1fr);

5条网格线被创建:

1.位于网格容器的开始边界

2.距离开始边界 100px

3.距离前一条线的距离等于剩下可用空间(网格容器的宽度减去非弹性轨迹的宽度)的一半

4.距离前一条线的距离等于这两条线之间的列里的最大内容网格元素大小。

5.距离前一条线的距离不小于两条线之间的列里的最小内容网格元素大小,且不大于可用空间的一半

如果非弹性的尺寸(100px, max-content , min-content )的总和超过了网格容器的宽度,那么最后一条线的距离边界的距离就会这个总和值相等(相当于 1fr 大小被解析为 0),如果总和小于网格容器的宽度,最后一条网格线将会正好落在网格容器的末端。

给网格线命名

虽然网格线可以通过数字索引来引用,但是给网格线命名可以使网格属性更容易理解和维护。可以在 grid-template-rows 和 grid-template-columns 属性中显示命名,或者通过 grid-template-areas 属性创建命名的网络区域来隐式命名网格线。

Example:
#grid {
  display: grid;
  grid-template-columns: [first nav-start] 150px [main-start] 1fr [last];
  grid-template-rows: [first header-start] 50px [main-start] 1fr [footer-start] 50px [last];
}

重复行和列:repeat() 符号

repeat() 表示轨道列表的片段重复,让我们能以更紧凑的形式写重复的大量行或列

Example:
grid-template-columns: 10px [col-start] 250px [col-end]
                       10px [col-start] 250px [col-end]
                       10px [col-start] 250px [col-end]
                       10px [col-start] 250px [col-end] 10px;
/* 与上面等价,更简便的书写方式*/
grid-template-columns: repeat(4, 10px [col-start] 250px [col-end]) 10px;
repeat() 语法

repeat( [ | auto-fill | auto-fit ] , )

第一个参数表示重复次数,第二个参数表示重复内容,另外 repeat 还有几个限制:

  • repeat() 符号不能嵌套
  • 自动重复 ( auto-fillauto-fit ) 不能与内在或者弹性尺寸组合。
auto-fill 和 auto-fit

当重复次数被设置为 auto-fill , 如果网格容器在对应轴线上定义了尺寸或最大尺寸,那么重复次数就是不会导致溢出网格容器的最大正整数。如果网格容器在对应轴线上定义了最小尺寸,那么重复次数就是满足最小尺寸的最小正整数。

Example

以下代码将创建尽可能多的25个字符的列,以适应窗口宽度。如果有剩余的空间,它将分布在25个字符的列之间。

body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(25ch, 1fr));
}

auto-fit 的行为与 auto-fill 一致,除了在网格部署好后,任何空白的重复网格轨道都会被折叠,一个空白的网格轨道就是不含任何网格元素的轨道(这会导致所有的轨道都被折叠,如果它们都是空的话)。

弹性尺寸:单位 fr

弹性长度 是以 fr 为单位的维度,其代表了网格容器剩余空间的一部分。

剩余空间的分布发生在所有非弹性轨迹的尺寸值达到最大值以后。从可用空间中减去这些行或列的尺寸,剩下的才是剩余空间,然后再将它按与弹性系数成正比分成弹性大小的行和列。

Name: 'grid-template-areas'
Value: none \ +

这个属性用于指定命名网格区域,这个命名可以在 grid-placement 属性中被引用。grid-template-areas 还提供了网格的可视化,使网格容器的整体布局更容易理解。

none : 表示没有指定的网格区域,也没有指定的网格轨道( 但是网格轨道还是可以由 grid-template-columns 或 grid-template-rows 创建命名)。

+ : 为每个单独的字符串创建一行,为字符串中的每个单元格创建一个列

grid-template-areas: 
  "<grid-area-name> | . | none | ..."
  "...";

为网格单元格的名称

. 表示一个空的单元格

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

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

上面的代码创建了四列宽三行高的网格。整个顶行由标题去组成,中间行由两个区域组成,一个空单元格和一个侧边区域组成,最后一行全部是页脚

声明中的每行都需要具有相同数量的单元格

我们注意到这里没有显式命名网格线,但当你使用这个语法的时候,实际上这个区域的两端的行会自动命名。

如果我们给一个网格区域命名为 foo,则该区域行和列的起始线名称会被命名为 foo-start,最后一行和最后一列的结束线会被命名为 foo-end。这意味着有些线条可能有会多个名字,比如最左边的这条网格线,就有三个名字:header-start,main-start 和 footer-start。

Name: 'grid-template'
Value: none \ [ <'grid-template-rows'> / <'grid-template-columns'> ] \ [ ? ? ? ] + [/ ]?

grid-template 属性是单个声明 grid-template-columnsgrid-template-rowsgrid-template-areas 这三个属性的简写。

none : 将所有三个属性设置为其初始值('none')

<'grid-template-rows'> / <'grid-template-columns'> : 将 grid-template-rows 和 grid-template-columns 分别设置为指定的值,并将 grid-template-areas 设置为 'none'。

grid-template: auto 1fr / auto 1fr auto;
/* is equivalent to */
grid-template-rows: auto 1fr;
grid-template-columns: auto 1fr auto;
grid-template-areas: none;

[ ? ? ? ] + [/ ] :

  • 将 grid-template-areas 设置为列出的 string 列表
  • 将 grid-template-rows 设置为跟随在 string 之后的 (如果缺少尺寸自动填充为 'auto'),并在每个尺寸的前后用命名的网格线拼接。
  • 将 grid-template-columns 设置在斜杠之后的 track-list,或不指定。
grid-template: [header-top] "a a a"     [header-bottom]
                 [main-top] "b b b" 1fr [main-bottom]
                          / auto 1fr auto;
/* is equivalent to */
grid-template-areas: "a a a"
                     "b b b";
grid-template-rows:  [header-top] auto [header-bottom main-top] 1fr [main-bottom];
grid-template-columns: auto 1fr auto;

Names: 'grid-auto-columns', 'grid-auto-rows'
Values: +

如果一个网格项被放在没有用 grid-template-rowsgrid-template-columns 显式指定指定尺寸的行或列中,那么隐式的网格轨道会被创建来保存它。grid-auto-columnsgrid-auto-rows 属性用于指定这种隐式创建的轨道的大小。

#grid {
  display: grid;
  grid-template-columns: 20px;
  grid-auto-columns: 40px;
  grid-template-rows: 20px;
  grid-auto-rows: 40px;
}
#A { grid-column: 1; grid-row: 1; }
#B { grid-column: 2; grid-row: 2; }
#C { grid-column: 1; grid-row: 2; }
#D { grid-column: 2; grid-row: 2; }
<div id="grid">
  <div id="A">A</div>
  <div id="B">B</div>
  <div id="C">C</div>
  <div id="D">D</div>
</div>

Name: 'grid-auto-flow'
Value: [ row \ column ] \ \ dense
Initial: row

没有显示指定放置位置的 grid item 会通过 grid 自动布局算法,被放置到 grid container 中的空闲空间。'grid-auto-flow' 属性控制了自动布局算法的工作原理,指定了被自动放置的项目在网格容器中如何流动。

  • row : 告诉自动布局算法依次填充每行,根据需要添加新行
  • column : 告诉自动布局算法依次填充每列,根据需要添加新列
  • dense : 告诉自动布局算法尝试在网格尽早用更大 grid item 填充空洞,这个可能导致 grid item 出现乱序
<section class="container">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</section>
.container {
  display: grid;
  grid-template-columns: repeat(5, 60px);
  grid-template-rows: repeat(2, 30px);
  grid-auto-flow: row;
}
.item-a {
  grid-column: 1;
  grid-row: 1 / 3;
}
.item-e {
  grid-column: 5;
  grid-row: 1 / 3;
}

.container {
  display: grid;
  grid-template-columns: repeat(5, 60px);
  grid-template-rows: repeat(2, 30px);
  grid-auto-flow: column;
}

Name: 'grid'
Value: <'grid-template'> \ <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-column'>? \ [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>

在单个声明中设置所有以下属性的简写:grid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns 和 grid-auto-flow,它也将 grid-column-gap 和 grid-row-gap 设置为其初始值,即使它们不能由此属性显式设置。

grid: auto-flow 1fr / 100px;
/* is equivalent to */
grid-template: none / 100px;
grid-auto-flow: row;
grid-auto-rows: 1fr;
grid-auto-columns: auto;
grid: none / auto-flow 1fr;
/* is equivalent to */
grid-template: none;
grid-auto-flow: column;
grid-auto-rows: auto;
grid-auto-columns: 1fr;

网格项属性

每个网格项都与一个网格区域(网格项所占据的相邻的网格单元的矩形集合)相关联。

网格项在网格区域中的位置由 grid postiongrid span 组成。

  • grid position : 网格项在网格中的位置,可以是明确指定的,也可以是自动放置确定的。
  • grid span :网格项占用的轨道数,网格项占据的轨道范围始终是确定的,如果无法确定,默认设为 1。

网格放置属性有以下几项:

grid-row-start, grid-row-end, grid-column-start, grid-column-end

它们的简写属性:

grid-row, grid-column, grid-area

这些属性让用户通过提供以下六条信息的任何信息来指定网格项位置:

Row Column
Start row-start line column-start
End row-end line column-end line
Span row span column span

指定一个维度上的 start,end 和 span 中的任意两个,就意味着第三个值的确定。

grid-area grid-column grid-column-start
grid-column-end
grid-row grid-row-start
grid-row-end
.item {
  grid-column-start: <line> | span <number> | span <name> | auto;
  grid-column-end: <line> | span <number> | span <name> | auto;
  grid-row-start: <line> | span <number> | span <name> | auto;
  grid-row-end: <line> | span <number> | span <name> | auto;
}
  • : 网格线,可以是一个数字编号来引用或一个名称来引用
  • span : 网格项目跨越的轨道数量
  • span : 该项目将跨越轨道,直到遇到提供名称的网格线
  • auto : 表示自动放置,自动跨度或默认跨度为1

Example

.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 来控制它们的堆叠顺序。


grid-column 和 grid-row

grid-columngrid-column-start + grid-column-end 的简写

grid-rowgrid-row-start + grid-row-end 的简写

.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}

Example

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

如果没有声明 end line,默认情况下该项目将跨越1个轨道。


grid-area

grid-area 属性用于给网格项指定一个名称,引用 grid-template-areas 属性里创建的区域名称。

另外,这个属性也可以写成 grid-column-start + grid-column-end + grid-row-start + grid-row-end 的缩写

.item {
  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
  • : 指定放置的网格区域名
  • / / / : 网格线,可以是一个数字编号来引用或一个名称来引用

Example

#grid {
  grid-template-areas: ". . . a a"
                       ". . . a a"
                       ". . . a a";    
}

.item-d {
  grid-area: a;
}

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

results matching ""

    No results matching ""