翻译 | CSS网格(CSS Grid)布局入门

翻译 | CSS网格(CSS Grid)布局入门

banner

CSS网格布局是浏览器Flexbox布局以后最重要的布局方式。咱们能够忘记过去15年常用的的各类“神奇数字”,hacks和一系列变通布局方案。网格布局提供了很是简单的声明布局方式,以后不再须要借助一些常见的主流css框架,也能减小不少手动实现的布局方式github

若是你之前不熟悉CSS网格布局,那么你能够开始了解它了。它是一种适用于容器元素,并能指定子元素的间距、大小和对齐方式的布局工具。浏览器

CSS网格布局赋予咱们更强大的能力——你们熟悉的水平垂直居中布局,不须要增长标签就能作到。一样,这也能让咱们不须要媒体查询就能根据可用空间自动适应。app

学习的最低要求

首先网格布局有很多新语法须要学习,可是你只须要稍微看下就能上手。本文将会用示例带你学习CSS网格布局各类各样重要的入门概念。框架

浏览器兼容性

CSS网格布局从Safari 10.1, Firefox 52, Opera 44, Chrome 57开始收到支持,微软Edge在Edge 15会更新对网格布局的支持。模块化

微软的浏览器(IE10–11和Edge 13-14)有一种比较旧的实现,因此有很多限制,咱们会简单介绍新的实现方式和老的实现方式之间的区别,这样你能知道如何规避他们。工具

对于大多数布局,咱们会使用下面的query特性来让老的浏览器对他们理解的特性也能工做:

@supports (display: grid) {
    .grid {
        display: grid;
    }
}

不支持浏览器@supports或网格的浏览器将不会生效。

为了能正确展现文中的示例,你须要使用支持网格布局的浏览器

建立带有间距(gutter)的两列(column)网格

为了演示CSS网格布局如何定义列,咱们从下面的布局开始:
grid-template-columns 和 grid-gap
[使用grid-template-columns 和 grid-gap建立带间距的两列布局]

为了建立上述网格布局,咱们须要使用grid-template-columnsgrid-gap
grid-template-columns表示网格中的列是如何布局的,它的值是一连串以空格分割的的值,这些值标识每列的大小,值的个数表示列的数目。

例如,四列250px宽度的网格布局能够这样表示:

grid-template-columns: 250px 250px 250px 250px;

也可使用repeat关键字表示:

grid-template-columns: repeat(4, 250px);

定义间距

grid-gap定义了网格布局的间距大小,接收一个或两个值,若是定义两个值则表示列(column)和行(row)的间距大小。

在两列布局示例中,咱们能够以下使用:

.grid {
  display: grid;
  grid-template-columns: 50vw 50vw;
  grid-gap: 1rem;
}

不幸的是,这个间距将会占用容器元素的总体宽度,计算出来就是100vw + 1rem,最终这个布局会致使出现水平滚动条。
viewport致使的水平滚动条
[经过viewport单位建立带间距网格致使的水平滚动条]

为了解决这个空间溢出问题,咱们须要些不一样的方法来处理,须要用分数单位或者说是FR

分数单位

分数单位标识占用可用空间的份额,若是900px是可用空间,其中的一个元素占有1份,另外的元素占有2份——那么第一个元素的宽度会是900px的1/3,另外的元素是900px的2/3。
修改后用分数代替view-port单位的新代码以下:

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 1rem;
}

内容对齐

为了对齐示例中的内容,咱们在子元素上使用grid布局,并加上对齐属性来定位他们到指定轨道(track),轨道就是一个网格的列或行的某个位置的常见的名称。网格跟Flex布局同样,有一系列对齐的属性——共有四种值——start, center, end, 和stretch,分别对应其子元素所在的轨道。stretch跟其余不太同样,它会将元素从所在轨道的头拉伸到尾。

align-items 和 justify-content

[align-items 和 justify-content]

例子中咱们要将内容水平和垂直居中,能够经过在容器上设置下面这些属性:

.center-content {
    display: grid;
    align-items: center;
    justify-content: center;
}

示例地址

使用旧的网格布局实现两栏布局

若是使用旧的网格布局方式建立,咱们须要考虑实现中的诸多限制。旧的布局方式不只没有grid-gap,并且你须要在每个网格元素上声明网格元素的起始位置,不然默认会设置为1,这样全部的网格都会堆在第一列。

旧版本的布局方式须要经过增长间距做为网格轨道的一部分,也须要设置每一个网格从哪里开始:

.grid-legacy {
   display: -ms-grid;
   -ms-grid-columns: 1fr 1rem 1fr; // 取代 gap 间距
}
.grid-legacy:first-child {
   -ms-grid-column: 1;
}
.grid-legacy:last-child {
    -ms-grid-column: 3;
}

旧的布局方式实现对齐和全高度

旧的布局方式跟IE 11中Flexbox有同样的问题,在容器上设置最小高度(min-height)不必定会生效。这个问题经过网格布局来解决更方便。

为了实现这个效果咱们在父容器的行属性上使用minmax方法,minmax指定了行或列的最大和最小值。

-ms-grid-rows: minmax(100vh, 1fr);

在子元素上咱们声明一个单位为1fr的单列单行的网格:

.ms-cell {
   -ms-grid-columns: 1fr;
   -ms-grid-rows: 1fr;
}

最后,由于咱们不能像Flexbox或最新网格布局那样根据父元素对齐,咱们必须使用元素自身的对齐方式来对齐:

.ms-align-center {
    -ms-grid-column: 1;
    -ms-grid-column-align: center; // 新型grid布局中的 align-self
    -ms-grid-row-align: center; // 新型grid布局中的 justify-self
}

旧的两列布局示例

到此咱们实现了如何建立列、实现间距、内容对齐及对旧的网格布局的支持。接下来让咱们实验下如何经过grid实现内边距。

经过CSS网格实现内边距(Negative Space)

网格布局容许你经过grid-column-start属性指定列开始的位置,因此就有了能够在网格内建立内边距的可能性。

使用grid-template-columns和grid-column-start建立内边距
[使用grid-template-columns和grid-column-start建立内边距]

建立内边距的一种方式是在列的实际位置上设置一个数字,空出网格元素的原始空间, 网格元素也会被push到新的网格列。

grid-column-start push
[随着grid-column-start push 第一项]

在上面的内边距示例中,html结构中用一个div包裹另一个div:

<div class="grid">
    <div class="child"><!-- 内容 --></div>
</div

网格像这样设置:

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

为了让子元素从右侧开始,咱们设置子元素从第2列开始:

.child {
    grid-column-start: 2;
}

注意:在Firefox 52中的一个差别致使一个垂直对齐问题——基于FR单位的行不会拉伸得跟整个窗口同样高。为了解决(address)这个问题咱们设置子元素为网格项,并给每一行设置一个想要的高度:

.l-grid--full-height {
    grid-template-rows: minmax(100vh, 1fr);
}

设置内边距示例

用内容死区(content dead-zones)建立空白

在四列布局中,给原本在第三列的网格项上设置grid-column-start:2;,那么会找到下一个可用的第二列来填充空间。

网格轨道会跳过某些列,直到找到下一列。咱们能够利用这个方法在网格内建立空白,没有内容的网格也会被分配。
[建立空白示例]


[使用grid-template-columns 和 grid-column-start建立空白]

建立行

若是咱们想分割布局为四份,咱们目前所了解的关于列的布局方式对行一样有效:

.grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 250px 250px;
}


[同时使用grid-template-columns 和 grid-template-rows建立网格布局]

理想状况下这个示例是没问题的。由于此时每一个网格项的内容足够少而不会撑开每行。但随着内容的变化,一切都不同了。当示例中的内容超出指定行的大小后,看下会发生什么:


[内容超出声明的行高]

咱们建立了250px高的两行,若是内容超过每行的高度,将会打破布局并和后面的行的内容重叠。并非一个咱们想要的结果。

灵活的设置最小值

咱们在该场景下须要的是设置最小尺寸的能力,但又要容许尺寸能够根据内容弹性变化。这里咱们经过上面旧浏览器示例中的minmax关键字实现。

.grid {
    grid-template-rows: minmax(250px, auto) minmax(250px, auto);
}

建立有最小值的弹性行

如今咱们已经了解了建立带有内容的行的基础方法,咱们开始来建立水平和垂直交错的更复杂网格布局。


[使用grid-column-start和span关键字建立复杂网格布局Unsplash]

建立更复杂的网格

咱们开始建立更复杂的网格布局。将网格中的每一个网格项设置成占据多条轨道,在一列内,咱们能经过grid-column-startgrid-column-end实现,或者经过以下所示更简单的写法:

grid-column: 1 / 3;

用这种实现方式的弊端是难以“模块化”,为了定位每块内容须要写不少代码。span关键字更符合模块化的思路,由于咱们能放在任何地方,让网格来控制他。咱们能够定义网格项的开始位置,及其占据的轨道数:

.span-column-3 {
    grid-column-start: span 3;
}

任何添加该class的网格将会从其开始位置,占据三个轨道。

[经过span实现的复杂网格]

使用span设计一个布局

咱们能设计一个多轨道布局,经过将布局分解为grid布局中的最小单元。本示例中的最小单位是图中高亮的部分。


[经过最小网格单位结合span建立更大的网格]

围绕最小单位,咱们能灵活的使用span来建立一些有意思的布局,由于span是能够叠加的——你能够结合列和行的轨道在网格中建立多层级。

不须要媒体查询(media queries)的弹性网格

虽然上面说到的例子能在可用空间内适应变化,可是没有一个是专门为空间变化设计的。网格有两个很是有用的特性来适应可用空间的变化。这两个属性叫‘auto-fit’和‘auto-fill’,像下面这样结合repeat functionminmax function使用:

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

这些值代替了repeat中的数字,并计算在每条轨道上会填充多少行或列。两者之间最大不一样是当一条轨道上空白的溢出时的他们的处理方式不一样。

auto-fit尝试在不致使列溢出的状况下,放置该列能处理的最大数量的重复元素。当没有足够的空间来放置更多的元素时,以后的元素将会放到下一行,不能填满的空间将会被保留。

auto-fill
[示例:auto-fill. auto-fill会保留后面空间,反之auto-fit会让空白收缩为0px]

auto-fill的表现跟auto-fit相似,可是任何的空白空间都会自动收缩,同时这一行的元素也会被拉升——相似flexbox的效果,列会随着可用空间变小发生折叠。

grid-auto-fit示例

[grid-auto-fit示例]

依赖媒体查询的布局跟窗口大小关系很大,这不够模块化——系统内的组件应该能根据可用空间自适应。那么在实践中会是什么样的呢?

auto-fit
[grid auto-fit的真实示例]

[网格auto-fit示例]

这只是冰山一角

咱们已经经历了快十五年的CSS浮动为主的布局方式,咱们上面学习了几乎全部你能用float实现的布局——CSS网格布局是这个领域的新表明,仍然还有许多东西须要去尝试和学习。

如今最重要的步骤是开始使用它。在构建、建立更多高级布局的时候会很方便。网格布局还有很多未知领域,一旦咱们更好地理解其能力并开始与其余特性结合,咱们便能用更少代码创造更多有趣、灵活的布局,并能减小些框架抽象的麻烦。

若是你感兴趣并想进一步探究CSS网格,能够试下Rachel Andrew的例子,这里面经过带解释说明的实例探讨了CSS网格布局的每个特性。


图片描述

iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。

相关文章
相关标签/搜索