【譯】瞭解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

若是你們想要持續關注網格佈局以及本系列翻譯,能夠關注公衆號「前端記事本」,及時得到最新消息推送。

相關文章
相關標籤/搜索