正确使用CSS grid(网格)

admin 前端 2019年2月24日 17:56 查看467次

CSS Grid功能强大灵活,与其他CSS布局系统相比是一种全新的方式。功能强大,也伴随着学习变难度加大。

“学习”CSS网格需要开发许多新属性的工作知识,这些属性不只是描述外观或行为的一个方面,而是将其输入到一个全新的布局系统中。这个系统包含大约18个属性,这些属性使用的范例和语法在CSS规范中很少或从未看到。

这意味着CSS Grid有一个相当高的技能基础——开发人员需要学习和消化大量的新信息,以便有效地使用它。一旦你掌握了那个技能,布局创建上的利器。相比这个技能,网格系统是一个累赘。建立一套网格系统,需要很多额外的工作,有些时候利用率却不是很高。

以下内部是CSS Grid 部份功能的介绍:

使用名字,而不是数字

网格的列和行,在它们最基本的情况下,是通过数字来引用的。例如,这个CSS设置了一个有两列的网格,并将页面的主要内容放在第二列:

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

.content {
    grid-column: 2;
}

 

这是可行的,但是它忽略了Grid的一个惊人特性:您可以为行和列指定特定的名称。你应该尽可能地利用这一点。

这里是相同的CSS,调整使用名称:

.container {
    display: grid;
    grid-template-columns: [sidebar] 1fr [content] 2fr;
}

.content {
    grid-column: content;
}

 

即使在这样的轻量级情况下,命名网格区域也对您有好处。


好处

向网格中添加名称会带来几个主要好处。

可读性——您的代码很容易理解。第3行现在描述了网格容器内部发生的一切。你不只是列出列;您正在概述每个列的意图。

第7行也变得更具描述性。以前,我们只知道。content位于第二列,如果没有更多的上下文,这就没有什么意义了——第三列中的第2列?2 200年?然而,如果指定一个列名,则表示这个元素已经在较大的系统中被特别考虑。如果需要的话,命名还可以更容易地找到原始列声明。

防将来—添加名称使CSS更加灵活。具体来说,您可以在.container上迭代,而不必编辑.content。

比如切换序顺,是轻而易举的事。

.container {
    display: grid;
    grid-template-columns: [content] 2fr [sidebar] 1fr;
}

.content {
    grid-column: content;
}

 

比如:新增另一列,也没有任何问题。

.container {
    display: grid;
    grid-template-columns: [related-posts] 1fr [sidebar] 1fr [content] 2fr;
}

.content {
    grid-column: content;
}

 

如果不使用命名列,则必须更新第7行中的列号,以反映第3行所做的更改。命名列提供与列计数或顺序无关的.content一致的行为。

使用fr作为灵活的单元

CSS Grid引入fr单元,它告诉一个区域占用总可用空间的一部分。fr似乎是网格规范中的一个旁注,但实际上它是不可缺少的。

fr单位不同于%或vw,因为后者描述的是100个单元整体的一部分,而fr是由尚未被其他东西使用的空间定义的。frs相对地分割了这个空间。

在这里,内容列的宽度是边栏列的两倍。

.container {
    display: grid;
    grid-template-columns: [sidebar] 1fr [content] 2fr;
}

.content {
    grid-column: content;
}

 

由于没有非fr单元,总共有3个frs,所以1fr = ~33%的网格宽度。


好处

fr单元提供了其他灵活单元所缺乏的一些功能。

可读性和更清晰的意图——使用frs,不像使用百分数,让我们坚持使用相对大小的整数,而不是相对于一个整体。这可以使预期的行为保持清晰。例如,第3行很容易翻译成英语:“内容是侧边栏的两倍宽”。

frs还允许您以使用百分比难以计算(和读取)的方式对空间进行划分。

 

.container {
    display: grid;
    grid-template-columns: [sidebar] 3fr [content] 4fr;
}

更少的数学计算——fr最大的好处是,它将精确计算的责任从开发人员手中转移到浏览器的布局引擎上。例如,下面的代码页展示了使用CSS网格创建相同布局的两种方法。

这些行是演示的关键:

.percents, .frs {
    display: grid;
    grid-column-gap: 20px;
}

.percents {
    grid-template-columns: repeat(3, calc((100% - 40px)/3))
}

.frs {
    grid-template-columns: repeat(3, 1fr);
}

 

第7行代码很难编写,很难读取,而且很脆弱。对grid-column-gap或列计数的任何更改都将破坏布局,除非手动更新列宽度以匹配。


第11行可以忽略空白大小,如果更新列计数,则不需要新的数学运算。这本书很容易读,而且经得起时间的考验。


不要使用网格系统

这个听起来自相矛盾的建议超越了CSS网格规范,深入到web设计的工作方式以及开发人员如何与设计人员及其工作进行交互。

布局通常被理解为沿着网格系统排列的元素。

grid-1.png (55 KB)

通常,开发力求与设计完全一致。如果设计基于14列网格,开发人员将在代码中设置某种14列网格,并编写助手类使项跨越1、2、3、6等列。大多数前端框架,比如Bootstrap,都是这样工作的。


在上面的例子中,我们有一个14列的网格,其中有这些元素的位置和大小:

  1. 标题,从列2开始,跨越12列
  2. 侧边栏从列2开始,跨越4列
  3. 主内容,从第6列开始,跨越8列

在CSS网格中,很容易建立一个模仿设计的系统:

.main {
    display: grid;
    grid-column-gap: 2rem;
    grid-row-gap: 1rem;
    grid-template-rows: [header] 100px [body] auto;
    grid-template-columns: repeat(14, 1fr);
}

.header {
    grid-row: header;
    grid-column: 2 / span 12;
}

.sidebar {
    grid-row: body;
    grid-column: 2 / span 4;
}

.content {
    grid-row: body;
    grid-column: 6 / span 8;
}

 

但这真的是一个好计划吗?我们尝试1:1复制有两个缺点。

首先,它破坏了我们命名列的计划。此外,在我们的14列中,我们只“使用”了第2、5、6和13列。这在技术上是可行的,但这意味着信号噪声比很低。

这两个问题都解决了,如果我们可以采取一些步骤,从原来的设计:

.main {
    display: grid;
    grid-column-gap: 2rem;
    grid-row-gap: 1rem;
    grid-template-rows: [header] 100px [body] auto;
    grid-template-columns: [left-gutter] 1fr [sidebar] 4fr [content] 8fr [right-gutter] 1fr;
}

.header {
    grid-row: header;
    grid-column: sidebar / right-gutter;
}

.sidebar {
    grid-row: body;
    grid-column: sidebar;
}

.content {
    grid-row: body;
    grid-column: content;
}

 

现在不是有14列,我们只有4列,但是它们仍然把横向空间分成14部分。我们拥有与第一次迭代完全相同的视觉效果,但是我们的代码没有那么嘈杂,并且直接反映了它的使用方式。

我们可以在整个布局中继续这个范例。在.content元素中,我们需要在主文章旁边添加辅助信息(作者简介、简介等)。

grid-2.png (54 KB)

如果我们紧紧地贴在14列网格上,看起来我们需要这样的东西:

.content {
    grid-row: body;
    grid-column: 6 / span 8;
}

.article {
    grid-column: 7 / span 4;
}

.info {
    grid-column: 11 / span 12;
}

 

这将是一个棘手的问题,因为CSS网格没有继承的概念。info不知道在.main(它的祖父元素)上设置的网格。

但是,如果我们放弃了文本的14列网格,我们可能会注意到.article和.info不需要知道关于顶级网格的任何信息——它们是.content内部新网格的一部分。

.content {
    grid-row: body;
    grid-column: content;
    display: grid;
    grid-template-columns: [left-gutter] 1fr [article] 4fr [info] 2fr [right-gutter] 1fr;
    grid-column-gap: 2rem;
}

.article {
    grid-column: article;
}

.info {
    grid-column: info;
}

使用此设置,.content简单且内部一致,但也与在.main上设置的外部列完全一致。


好处

除了我已经概述过的,对原始设计系统的更松散的坚持使我们作为开发人员能够更有效地利用我们的专业知识和工具——浏览器。像素和列没有关系和比例空间突出。

文章从第7列开始,而.info从第11列开始,这并不重要。重要的是.article的宽度是.info的两倍。按比例思考元素,并询问它们如何相互作用,有助于我们将布局视为动态系统。


旁注:嵌套标记

关于本节中的代码示例,您可能已经注意到左gutter和右gutter列的使用。这个CSS假定了最简单的HTML。

<div class="main">
    <div class="header"></div>
    <div class="sidebar"></div>
    <div class="content"></div>
</div>
.main {
    display: grid;
    grid-template-columns: [left-gutter] 1fr [sidebar] 4fr [content] 8fr [right-gutter] 1fr;
}

如果我们愿意在标记中放入一个包装器div,我们可以用每个元素更少的列编写更直接的CSS。

<div class="main">
    <div class="wrapper">
    <div class="header"></div>
    <div class="sidebar"></div>
    <div class="content"></div>
    </div>
</div>
.main {
    display: grid;
    grid-template-columns: [left-gutter] 1fr [wrapper] 12fr [right-gutter] 1fr;
}

.wrapper {
    grid-column: wrapper;
    display: grid;
    grid-template-columns: [sidebar] 1fr [content] 2fr;
}

 

第二种方法本质上感觉更好,因为数学更简单——你可以尽快停止担心那些加起来等于14的数字,只考虑1:2的比例。这感觉很符合CSS网格的精神。

但是,CSS Grid感觉不太真实的地方是添加了.wrapper div。,我们不需要添加额外的元素使样式工作或“表现良好”。因此,至少在今天,我鼓励您不要仅仅为了更整洁的CSS网格样式而添加或更改标记。


Coda

感谢您和我一起踏上这趟CSS网格之旅!I’ve使用和爱它在过去的几months,,我希望这可以帮助你理解和使用它💐结束

在简介中重申我的观点,CSS网格很容易使用,但是很难学习。它比任何其他CSS布局技术都更直观,但它完全不同于它的前辈。

所有这些都说明:尽可能慢地使用网格。不要仅仅通过阅读规范就试图理解所有内容,建立简单的示例,打开web inspector(特别是在Firefox中),并善待自己。

这是值得的。

 

源文地址:https://vgpena.github.io/using-css-grid-the-right-way/