grid佈局

我是格鲁特發表於2024-11-05

一、核心術語

  • 容器

設定了 "display: gird / inline-grid" 的元素,就稱之為網格容器(grid container)

  • 專案(Item

grid 容器中的直接子元素就為網格專案(grid item)

下面的 .container 元素就為網格容器(grid container),所有的直接子元素 .item 就為該網格容器的一個個專案(grid item)

<div class="container">
  <div class="item"></div>
  <div class="item">
    <p class="sub-item"></p>
  </div>
  <div class="item"></div>
</div>
  • 行和列

容器裡面的水平區域稱為 "行"(row),垂直區域稱為 "列"(column)

  • 單元格(cell)

行和列的交叉區域

  • 網格線(grid line)

劃分網格的線段,水平線劃分出行,垂直線劃分出列

二、網格容器相關屬性

2.1 大小及名稱

grid-template-rowsgrid-template-columns 用於定義將網格劃分為多少行、多少列;每行/每列的名稱,每行的高度、每列的寬度.

.container {
    display: grid; /* 定義網格佈局 */
    grid-template-rows: 100px 100px 100px; /* 定義三行,每行的高度為100 */
    grid-template-columns: 100px 100px 100px; /* 定義三列,每列寬度為100 */
}


.item {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid white;
    background-color: orange;
    color: white;
}
<body>
    <span>H</span>
    <div class="container">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
    </div>
    <span>H</span>
</body>

2.1.1 行或列的大小

px|repeat()|fr|minmax()|fit-content()|min-content|max-content|auto|%

2.1.1.1 repeat()

當有重複值時,可以使用repeat()函式進行書寫簡化

repeat(數量|auto-fill|auto-fit,px|fr|min-content|max-content|auto|minmax|fit-content):

/*透過 repeat 函式來簡化上面的寫法*/
.container {
    display: grid;
    grid-template-rows: repeat(3, 100px);
    grid-template-columns: repeat(3, 100px);
}
  •  repeat:auto-fll

當大小是固定的,但是容器的大小不確定,希望由瀏覽器自動劃分行數或列數時,可使用該屬性

.container {
    display: grid;
    grid-template-columns: repeat(auto-fill, 100px); /* 具體多少列根據容器大小自動劃分(每列列寬 100px) */
    grid-template-rows: repeat(3, 100px);
}

  • repeat:auto-fit

該關鍵字與上面的 auto-fill 的行為基本是相同的,都會盡可能的生成更多的行或列,但是單元格中沒有元素時,會將對應的列寬收縮為 0

  • auto-fill vs auto-fit

auto-fill 不管單元格是否中是否有元素,都會生產對應單元格的空間

auto-fit 則是如果單元格中沒有元素,會將對應的列寬收縮為 0

2.1.1.2 fr

fr是fraction 的縮寫,意為"片段",該單位可以更方便的定義單元格之間的比例關係

2.1.1.2 minax()

minmax() : 該函式可以生成一個長度範圍,表示長度在這個範圍之中

minmax(px|fr|%|min-content|max-content|auto,px|fr|%|min-content|max-content|auto)

2.1.1.3 auto

該關鍵字表示長度由瀏覽器進行決定(也可以理解為預設會自動吸收對應容器的剩餘長度,當然如果對應單元格元素設定了 min-width/max-width 當達到對應的最值時,對應的效果可能就會有些出入)

2.1.1.4 自動計算值的優先順序

優先順序: - minmax > fr > auto
tip: - 為了保證最小空間,網格可能會超出容器元素的範圍(auto 的最小寬度為 fit-content,即內容寬度)

2.1.2 為隱式建立的行、列指定大小

grid-auto-rows / grid-auto-columns: 用於指定一些自動生成的行和列,對應的行高與列寬。不指定這兩個屬性時對應的行高或列寬是 fit-content(適應內容的)

什麼時候會隱式建立行、列?

如: 當一個網格是三行三列的,但裡面某一個網格專案指定在第 5 行等等,此時網格就會自動生成一些行或列 或在一個三行三列的網格中只有 9 個單元格,但網格中的元素卻超出了九個時,此時也會自動生成一行或列

如下示例: 在一個三行三列的網格容器中,有十個子元素 → 因為網格單元格不夠,就會自動生成一行,我們可以透過 grid-auto-row 屬性來指定對應自動生成行的行高(列同理)

.container {
    gap: 6px;
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(3, 100px);
    grid-auto-rows: 100px; /* 指定自動生成的行的行高大小 */
}

 

2.1.3 網格線名稱

grid-template-columns 屬性和 grid-template-rows 屬性裡面,還可以使用方括號,指定每一根網格線的名字,後面網格專案(item)中的grid-row / grid-column屬性可以使用對應的網格線名稱,可以更加方便將專案元素佈局到對應想要的位置上。

網格佈局允許同一根線有多個名字,比如[fifth-line row-5]

.container {
    display: grid;
    grid-template-columns: [col-1] 100px [col-2] auto [col-3] 100px [col-4];
    grid-template-rows: [row-1] 100px [row-2] 100px [row-3] 100px [row-4];
}

2.2 網格之間的間隙

row-gap設定行之間的間隔(行間距),column-gap設定列間距,gap是行間距和列間距的縮寫

/*普通寫法*/
	{
        row-gap: 設定行與行之間的間隔(行間距); 
        column-gap: 設定列與列之間的間隔(列間距); 
    }
/*我們也可以上面兩個屬性的簡寫屬性 gap 來快速設定對應的間隔*/
    {
        gap: 行間距 列間距;
    }
/*當行間距與列間距相同時,我們也可以只需寫一個值*/
    {
		gap: 行列間距;
    }

  

2.3 網格專案的放置順序

grid-auto-flow用於設定專案的放置順序。預設的放置順序是"先行後列",即先填滿第一行,再開始放入第二行。值通常為 row(先行後列) 或 column(先列後行),預設為 row 即先行後列 → 基本效果如下示例圖

屬性除了可以設定成 rowcolumn,還可以設定成 row densecolumn dense,第二個值主要用於某些專案在指定完位置後,剩下的專案怎麼放置(如: 先行後列,並且儘可能緊密填滿) 文字描述可能會比較抽象,我們可以透過下面幾張圖來進行理解

2.4 對網格進行分割槽

網格佈局允許指定"區域"(area),一個區域由單個或多個單元格組成。grid-template-areas屬性用於定義區域。該屬性定義的分割槽名,在專案中使用grid-area屬性進行引用

.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  grid-template-areas: 'a b c'
                       'd e f'
                       'g h i';
}

上面程式碼先劃分出9個單元格,然後將其定名為ai的九個區域,分別對應這九個單元格。

多個單元格合併成一個區域的寫法如下。

grid-template-areas: 'a a a'
                     'b b b'
                     'c c c';

如果某些區域不需要利用或不屬於任何區域,則使用"點"(.)表示。

grid-template-areas: 'a . c'
                     'd . f'
                     'g . i';
  • 注意,區域的命名會影響到網格線。每個區域的起始網格線,會自動命名為區域名-start,終止網格線自動命名為區域名-end
  • 比如,區域名為header,則起始位置的水平網格線和垂直網格線叫做header-start,終止位置的水平網格線和垂直網格線叫做header-end

2.5 設定容器內整個網格的對齊

justify-content屬性是整個內容區域在容器裡面的水平位置

align-content 屬性是整個內容區域的垂直位置(上中下)

place-content: 上面兩者合併的簡寫

justify-content: start | end | center | stretch | space-around | space-between | space-evenly;

align-content: start | end | center | stretch | space-around | space-between | space-evenly;

place-content: <align-content> <justify-content> /*如果省略第二個值,瀏覽器就會假定第二個值等於第一個值。*/

+ 對應屬性值的作用(及對應 justify-content 示例圖):
- start - 對齊容器的起始邊框(預設)
- end - 對齊容器的結束邊框
- center - 容器內部居中
- stretch - 專案大小沒有指定時,拉伸佔據整個網格容器(即沒有透過 grid-template-columns / grid-template-rows 指定對應列寬或行高時)
- space-around - 每個專案兩側的間隔相等。所以,專案之間的間隔比專案與容器邊框的間隔大一倍
- space-between - 專案與專案的間隔相等,專案與容器邊框之間沒有間隔(兩端對齊)
- space-evenly - 專案與專案的間隔相等,專案與容器邊框之間也是同樣長度的間隔

2.6 設定單元格內的元素對齊方式

justify-items屬性設定單元格內容的水平位置(左中右)

align-items屬性設定單元格內容的垂直位置(上中下)。

place-items 屬性是兩個屬性合併的簡寫

justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
place-items: <align-items> [justify-items]; /* 簡寫: 如果只寫一個值時,將會認為這兩個值相等 */

對應屬性值的作用(及對應 justify-items 示例圖):
- start - 對齊單元格的起始邊緣
- end - 對齊單元格的結束邊緣
- center - 單元格內部居中
- stretch - 拉伸,佔滿單元格的整個寬度(預設值) → 當元素沒有指定具體的大小時

.container {
  justify-items: start; /*水平方向,內容左對齊*/
}

.container {
  align-items: start; /*垂直方向頂對齊*/
}

 

三、網格專案(item)相關屬性

3.1設定專案的起始位置

grid-column-start屬性:左邊框所在的垂直網格線

grid-column-end屬性:右邊框所在的垂直網格線

grid-row-start屬性:上邊框所在的水平網格線

grid-row-end屬性:下邊框所在的水平網格線

grid-column: <grid-column-start> / <grid-column-end>

grid-row: <grid-row-start> / <grid-row-end>

.item-1 {
  grid-column-start: 2;
  grid-column-end: 4;
}

上面程式碼指定,1號專案的左邊框是第二根垂直網格線,右邊框是第四根垂直網格線。由於沒有指定上下邊框,所以會採用預設位置,即上邊框是第一根水平網格線,下邊框是第二根水平網格線。除了1號專案以外,其他專案都沒有指定位置,由瀏覽器自動佈局,這時它們的位置由容器的grid-auto-flow屬性決定,這個屬性的預設值是row,因此會"先行後列"進行排列。

下面的例子是指定四個邊框位置的效果。

.item-1 {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 2;
  grid-row-end: 4;
}

這四個屬性的值,除了指定為第幾個網格線,還可以指定為網格線的名字。

.item-1 {
  grid-column-start: header-start;
  grid-column-end: header-end;
}

 這四個屬性的值還可以使用span關鍵字,表示"跨越",即左右邊框(上下邊框)之間跨越多少個網格。

.item-1 {
  grid-column-start: span 2; /*與grid-column-end: span 2效果是一樣的*/
}

 上面程式碼表示,1號專案的左邊框距離右邊框跨越2個網格。

3.2 為專案設定區域

grid-area屬性指定專案放在哪一個區域。

grid-area: 使用grid-template-areas定義的區域名稱 | <row-start> / <column-start> / <row-end> / <column-end>

.item-1 {
  grid-area: e;
}

上面程式碼中,1號專案位於e區域,效果如下圖。

grid-area屬性還可用作grid-row-startgrid-column-startgrid-row-endgrid-column-end的合併簡寫形式,直接指定專案的位置。

下面是一個例子

.item-1 {
  grid-area: 1 / 1 / 3 / 3;
}

3.3 專案內容重疊處理

因為元素的大小可以跟單元格的大小無關,即元素可以指定比單元格更大的大小,所以就有可能會超出到其它的單元格上,導致與其它單元格元素產生了層疊。

z-index: 該屬性來指定對應的層疊順序

order: 屬性規定了專案的順序,值越小越佈局順序越靠前,未指定則相當於為0(因此總是顯示在有order值的項前面,例如下圖中的3-6).

3.4設定某個單元格內容的對齊

當需要統一設定所有單元格內容對齊時可以使用 2.6 中的justify-items、aligin-items兩個屬性。如果想單獨設定某個單元格內容的對齊,需要使用下面的屬性

justify-self屬性設定單元格內容的水平位置(左中右),跟justify-items屬性的用法完全一致,但只作用於單個專案。

align-self屬性設定單元格內容的垂直位置(上中下),跟align-items屬性的用法完全一致,也是隻作用於單個專案。

place-self屬性是align-self屬性和justify-self屬性的合併簡寫形式。

justify-self: start | end | center | stretch

align-self: start | end | center | stretch

place-self: <align-self> [justify-self]; 如果省略第2個值,則認為與第1個值相等

- start - 對齊單元格的起始邊緣
- end - 對齊單元格的結束邊緣
- center - 單元格內部居中
- stretch - 拉伸,佔滿單元格的整個寬度(預設值) → 當元素沒有指定具體的大小時

下面是justify-self: start的例子。

.item-a  {
  justify-self: start;
}

四、參考及整理

現今 CSS3 最強二維佈局系統 Grid 網格佈局_css3 grid-CSDN部落格

CSS Grid 網格佈局教程 - 阮一峰的網路日誌 (ruanyifeng.com)

grid - CSS:層疊樣式表 | MDN (mozilla.org)

相關文章