【译】了解css网格布局-网格线

原做者:Rachel Andrew 原文地址:www.smashingmagazine.com/2020/01/und…css

在第一篇文章中,咱们讲解了如何建立一个网格容器,而且介绍了一些用于构造网格的属性。只要建立了网格,你就有了不少的网格线。在这篇文章中,咱们将介绍如何经过设置一些属性来对网格的子元素进行布局。 咱们将包括:html

  • 布局属性grid-column-start, grid-column-end, grid-row-start, grid-row-end以及它们的简写方式grid-columngrid-row
  • 如何使用grid-area属性
  • 如何经过行的名字布局
  • 显式网格和隐式网格布局的区别
  • 使用span关键字
  • 当使用属性进行布局以及自动布局混用时应该注意什么

基于网格线进行布局

若是咱们想在网格中放置一个元素,就须要定义它从哪一条网格线开始,到哪一条线结束。 因此,在一个5行5列的网格中,要让元素占据第2列第3列,以及前3行的位置,我可使用下面的css。前端

.item {
  grid-column-start: 2;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 4;
}
复制代码

你也可使用简写方式,前面表明开始的网格线,后面表明结束网格线。函数

.item {
  grid-column: 2 / 4;
  grid-row: 1 / 4;
}
复制代码

能够看下这个例子:布局

<div class="grid">
  <div class="item">Item</div>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.grid {
  border: 5px solid rgb(111,41,97);
  display: grid;
  grid-template-columns: repeat(5, 100px);
  grid-template-rows: repeat(5, 50px);
  inline-size: 500px;
}

.item {
  grid-column: 2 / 4;
  grid-row: 1 / 4;
}

.grid > * {
  background-color: rgba(111,41,97,.4);
  border-radius: 5px;
  padding: 10px;
}
复制代码

注意:咱们的长方体背景延伸到整个区域的缘由是对齐特性的默认初始值align-selfjustify-selfstretch(拉伸,占满单元格的整个宽度)。 若是但愿元素只占据一条轨道,你能够省略结束网格线的值。元素会默认占据一条轨道。像上一篇文章中,最后一个例子,自动放置的元素,每一项值占据一个网格单元。因此若是想要占据第2条和第3条网格线之间的区域能够这么设置。ui

.item {
  grid-column: 2 / 3;
}
复制代码

也能够省略后面的值。spa

.item {
  grid-column: 2;
}
复制代码

简写形式grid-area

你也可使用grid-area设置。在后面的文章中咱们会常常遇到。使用这个属性能够同时设置上面的四个值。翻译

.item {
  grid-area: 1 / 2 / 4 / 4;
}
复制代码

四个值分别表明grid-row-start, grid-column-start, grid-row-end, grid-column-end它们分别表明top, left, bottom, right。这和咱们平时写css属性时有点区别。3d

这是由于不管使用哪一种书写模式或方向,网格都以相同的方式工做,在后面咱们会详细解释。并且先设置两个开始值,再设置两个结束值比描述屏幕的物理映射更加有意义。但我并不推荐使用这种方式。由于在阅读时,使用grid-columngrid-row这两个属性可读性更加好。code

显式网格中的线

在上篇文章中我提到了显式和隐式网格。显式网格是你使用 grid-template-columnsgrid-template-rows明肯定义的网格。经过定义行列轨道,同时也定义了轨道之间的网格线以及网格的边框。 这些线都是有编号的。内联元素和块级元素的编号都是从1开始的。若是你使用水平的书写方式,那么上下方向来讲,上面从1开始数,左右方向上,左边从1开始数。

若是将第二个值设为-1,表明一直跨越到最后一条线。若是设为-2,就是到最后一条网格线以前的那条线。这意味着,若是要跨越显式网格的全部轨迹来跨越某个项,可使用:

.item {
  grid-column: 1 / -1;
}
复制代码

隐式网格中的线

隐式网格中的网格线,它们也是从1开始计数的。在下面的例子中,我为列轨道建立了显式网格,但当我使用grid-auto-rows属性将元素的高设为5em时,就建立了隐式的行轨道。 能够看到带有文字placed的网格项被放在了行线1到行线-1的位置。若是咱们是在显式网格中使用这两个值,网格项应该占据两行的位置。但在隐式网格中,值-1会被处理为网格线2而不是网格线3。

<div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div class="placed">Placed</div>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.grid {
  border: 5px solid rgb(111,41,97);
  display: grid;
  grid-template-columns: repeat(5, 100px);
  grid-auto-rows: 5em;
  inline-size: 500px;
}

.grid > * {
  background-color: rgba(111,41,97,.4);
  border-radius: 5px;
  padding: 10px;
}

.grid > .placed {
  background-color: orange;
  grid-row: 1 / -1; /* the end line is in the implicit grid so -1 does not resolve to it*/
}
复制代码

当前在隐式网格中没有什么方法将元素定位到最后一条网格线前,由于对于隐式网格,咱们并不知道一共有多少条线。

根据命名的线放置项

在上一篇文章中,我提到了,除了使用网格线编号,也可使用网格线的名字。能够将线的名字放在方括号中给对应的线命名。

.grid {
  display: grid;
  grid-template-columns: [full-start] 1fr [main-start] 2fr 2fr [main-end full-end];
}
复制代码

只要你有了一些命名以后的网格线,在布局中就能够再也不使用网格线编号,改成使用线的名字。

.item {
  grid-column: main-start / main-end;
}
复制代码
<div class="grid">
  <div class="item">Item</div>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.grid {
  border: 5px solid rgb(111,41,97);
  display: grid;
  grid-template-columns: [full-start] 1fr [main-start] 2fr 2fr [main-end full-end];
  grid-template-rows: repeat(5, 50px);
  inline-size: 500px;
}

.item {
  grid-column: main-start / main-end;
  grid-row: 1 / 4;
}

.grid > * {
  background-color: rgba(111,41,97,.4);
  border-radius: 5px;
  padding: 10px;
}
复制代码

当同一条线有多个名字时,能够随意使用任何一个,它们的处理效果是同样的。

当多条线有同一个名字时会发生什么

你可能会疑惑,当我给多条线定义同一个名字时会怎么样。一般在使用repeat方法定义名字时会出现这种状况。好比,在下面的例子中,我使用函数重复设定1fr 2fr模式,建立了8个列。我已经给两种网格线分别命名为smlg。那么每种网格线各有四条拥有同一名字的网格线。 在这种状况下,咱们须要将名字和线编号一块儿使用。好比,我想把元素放在第二条叫sm以及第三条lg线之间,就须要使用grid-column: sm 2 / lg 3。若是不带编号,直接使用名字,默认采用第一条线。

<div class="grid">
  <div class="item">Item</div>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.grid {
  border: 5px solid rgb(111,41,97);
  display: grid;
  grid-template-columns: repeat(4, [sm] 1fr [lg] 2fr);
  grid-template-rows: repeat(5, 50px);
  inline-size: 500px;
}

.item {
  grid-column: sm 2 / lg 3;
  grid-row: 1 / 4;
}

.grid > * {
  background-color: rgba(111,41,97,.4);
  border-radius: 5px;
  padding: 10px;
}
复制代码

使用span关键字

有时候,咱们知道某个网格项须要占据的轨道数,但你不知道它会被放在网格中的哪一个位置,这样就没法经过网格线布局了。在下面的例子中,网格项是被默认放置在网格中的,但你须要修改它们占据的轨道数,而不是使用默认的占据一条轨道。你可使用span关键字。在这个例子中,开始的网格线用auto赋值,表示它会被放在网格中的任何位置,并占据3列轨道。

.item {
  grid-column: auto / span 3;
}
复制代码

由于咱们有次级网格概念的支持,因此这种技术会有很是普遍的应用。例如,在卡片布局中,卡片有一个标题和主内容区域,你但愿它们在卡片中彼此对齐,那么可使每张卡片跨越两条行轨道,同时仍然容许默认的自动放置行为。每一个卡片都对于它们所在的行至关于一个次级网格(包括两条行轨道)。能够看到下面这个例子。

<div class="grid">
  <article class="card">
    <h2>This is the heading</h2>
    <p>This is the body of the card.</p>
  </article>
  <article class="card">
    <h2>This is the heading and some headings are bigger</h2>
    <p>This is the body of the card.</p>
  </article>
  <article class="card">
    <h2>This is the heading</h2>
    <p>This is the body of the card.</p>
  </article>
  <article class="card">
    <h2>This is the heading</h2>
    <p>This is the body of the card.</p>
  </article>
  <article class="card">
    <h2>This is the heading</h2>
    <p>This is the body of the card.</p>
  </article>
  <article class="card">
    <h2>This is the heading</h2>
    <p>This is the body of the card.</p>
  </article>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

.card {
  border: 5px solid rgb(111,41,97);
  grid-row: auto / span 2;
  display: grid;
  gap: 0;
  grid-template-rows: subgrid;
}

.card h2 {
  background-color: rgba(111,41,97,.4);
  padding: 10px;
  margin: 0;
}

.card p {
  padding: 10px;
  margin: 0;
}
复制代码

基于线布局的分层

网格会自动将内容放置在空的网格单元中,并不会把多个内容放在同一个网格单元里。 可是使用基于网格线的布局方法能够将元素放在一块儿。在下面的例子中,有一张占据两条行轨道的图片,以及带走caption文本的元素放置在第二条行轨道中,并给了一个半透明的背景。

<div class="grid">
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>This is the caption</figcaption>
  </figure>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

img {
  max-width: 100%;
}

.grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

figure {
  margin: 0;
  display: grid;
  grid-template-rows: 300px min-content;
}

figure img {
  object-fit: cover;
  width: 100%;
  height: 100%;
  grid-row: 1 / 3;
  grid-column: 1;
}

figcaption {
  grid-row: 2;
  grid-column: 1;
  background-color: rgba(0,0,0,.5);
  color: #fff;
  padding: 10px;
}
复制代码

元素会按照代码中的顺序进行堆积。因此在上面的例子中,由于代码中文本元素是放在图片后面的,因此它会堆叠在图片上面。若是它是写在图片代码前面的,咱们就看不到就。你可使用 z-index试试。若是文本元素必须放在前面,那么就只能使用 z-index设置更大的值,强制文本堆叠在图片上面。

网格线的布局和自动布局混用

当基于网格线的布局和自动布局混用时,你须要当心一点。当项目中元素都是自动放置在网格中时,它们将按顺序放置在网格上,每一个项目都会找到下一个可用的空白空间来放置它们本身。

<div class="grid">
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>1. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>2. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>3. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>4. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>5. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>6. This is the caption</figcaption>
  </figure>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

img {
  max-width: 100%;
}

.grid {
  display: grid;
  inline-size: 800px;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}

.grid figure:nth-child(odd) {
  grid-column: auto / span 2;
}

.grid figure:nth-child(2) {
  grid-column: auto / span 3;
}

figure {
  margin: 0;
  display: grid;
  grid-template-rows: 200px min-content;
}

figure img {
  object-fit: cover;
  width: 100%;
  height: 100%;
  grid-row: 1 / 3;
  grid-column: 1;
}

figcaption {
  grid-row: 2;
  grid-column: 1;
  background-color: rgba(0,0,0,.5);
  color: #fff;
  padding: 10px;
}
复制代码

这种默认行为老是向前排列,因此若是元素不能充满网格就会留下空隙。你可使用grid-auto-flow属性进行控制。这种状况下,若是有一个元素能够填满留下的间隙,它将会脱离代码中的顺序,被移过来填补空隙。在下面的例子中,第三个元素被移到第二个元素以前来填补空隙。

<div class="grid">
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>1. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>2. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>3. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>4. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>5. This is the caption</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>6. This is the caption</figcaption>
  </figure>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

img {
  max-width: 100%;
}

.grid {
  display: grid;
  inline-size: 800px;
  grid-auto-flow: dense;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}

.grid figure:nth-child(odd) {
  grid-column: auto / span 2;
}

.grid figure:nth-child(2) {
  grid-column: auto / span 3;
}

figure {
  margin: 0;
  display: grid;
  grid-template-rows: 200px min-content;
}

figure img {
  object-fit: cover;
  width: 100%;
  height: 100%;
  grid-row: 1 / 3;
  grid-column: 1;
}

figcaption {
  grid-row: 2;
  grid-column: 1;
  background-color: rgba(0,0,0,.5);
  color: #fff;
  padding: 10px;
}
复制代码

注意,对于须要在文档中切换tab的状况会存在一些问题,由于它们所遵循的布局和代码中的顺序并不一样步。 若是你已经在网格中放置了一些元素,那么它自动布局会有不同的效果。已经布局的元素会优先处理,其它自动布局的元素会寻找空白单元进行放置。若是您在布局的顶部以空网格行的方式留下了一些空白,而后引入一些自动放置的项,它们最终将位于该轨迹中。 在最后一个例子中,使用基于网格线的布局放置了两个元素item1和item2,而且遗留了行的空白。后面的元素会移动到空白地方并填充。

<div class="grid">
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>1. Positioned</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>2. Positioned</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>3. Auto-placed</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1576451930877-c838b861e9b6?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="lights">
    <figcaption>4. Auto-placed</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482003297000-b7663a1673f1?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="tree">
    <figcaption>5. Auto-placed</figcaption>
  </figure>
  <figure>
    <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b44be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="bauble">
    <figcaption>6. Auto-placed</figcaption>
  </figure>
</div>
复制代码
body {
  padding: 50px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

img {
  max-width: 100%;
}

.grid {
  display: grid;
  inline-size: 800px;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}

.grid figure:nth-child(odd) {
  grid-column: auto / span 2;
}

.grid figure:nth-child(1) {
  grid-row: 2;
  grid-column: 1;
}

.grid figure:nth-child(2) {
  grid-row: 2;
  grid-column: 2 / -1;
}

figure {
  margin: 0;
  display: grid;
  grid-template-rows: 200px min-content;
}

figure img {
  object-fit: cover;
  width: 100%;
  height: 100%;
  grid-row: 1 / 3;
  grid-column: 1;
}

figcaption {
  grid-row: 2;
  grid-column: 1;
  background-color: rgba(0,0,0,.5);
  color: #fff;
  padding: 10px;
}
复制代码

明白这种布局原理是很是重要的,不然当你将一些未设定布局方式的元素放入网格中时会有很奇怪的效果。

收尾

这就是你须要知道的关于网格线的知识。记住,您老是有编号的网格线,不管您如何使用网格,您老是能够将一个项目从一个网格线放置到另外一个网格线。咱们将在之后的文章中介绍的其余方法是指定布局的替代方法,但它们是基于由编号的网格线建立的网格。

END

若是你们想要持续关注网格布局以及本系列翻译,能够关注公众号“前端记事本”,及时得到最新消息推送。

相关文章
相关标签/搜索