基本概念
<template><div class="parent"><div class="box">p1-1</div><div class="box">p1-2</div><div class="box">p1-3</div></div><div class="parent"><div class="box">p2-1</div><div class="box">p2-2</div><div class="box">p2-3</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid; // 塊級容器,寬度撐滿整行/* display: inline-grid; */ // 行內容器,寬度隨內容自適應
}.box {border: 1px solid #000;
}
</style>
最外層的 <div class="parent">
稱為容器,內層的三個 <div class="children">
稱為項目(或網格項)。
使用網格布局后,項目的 float、display: inline-block、display: table-cell、vertical-align、column-*
等設置都將失效。
指定行列
grid-template-columns 指定劃分列數
grid-template-rows 指定劃分行數
固定寬高 px
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box box5">5</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;/* 3 列 */grid-template-columns: 100px 100px 100px;/* 2 行 */grid-template-rows: 50px 40px;
}.box {border: 1px solid #000;margin: 10px;
}
</style>
可以看到 grid-template-columns 和 grid-template-rows 設置的值是包含 margin 在內的。
使用了 grid-template-columns 和 grid-template-rows 后還可以單獨給項目設置寬高嗎?答案是可以的。
.box5 {height: 80px;
}
單獨設置寬高是不包含 margin 的,且容器的寬高不會受它影響。
百分比 %
-
如果
.parent
沒有顯式設置 width 和 height ,則 100% 將等于 .parent 自然展開后的寬高。 -
如果
.parent
有顯式的 width 和 height 值,那么 100% 就等于該指定的寬高值。
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box"><div style="height: 30px;">7</div></div></div></template><style scoped>
.parent {background-color: skyblue;display: grid;/* 3 列 */grid-template-columns: 40% 30% 20%;/* 2 行 */grid-template-rows: 100% 50%;
}.box {border: 1px solid #000;margin: 10px;
}
</style>
第 7 個 項目的高度沒有被 grid-template-rows
設置到,則第 7 個 div 的高度是他實際內容的高度。
重復設置 repeat
使用 repeat 統一設置值,第一個參數為重復數量,第二個參數是重復值
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box">7</div></div></template><style scoped>
.parent {background-color: skyblue;display: grid;/* 3 列 */grid-template-columns: repeat(3, 40%);/* 2 行 */grid-template-rows: repeat(2, 50%);
}.box {border: 1px solid #000;margin: 10px;
}
</style>
項目總寬度超過 100% 時會產生滾動條。
repeat 還可以設置多個值:
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box">7</div></div></template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: repeat(2, 200px 100px);grid-template-rows: repeat(2, 50px);
}.box {border: 1px solid #000;margin: 10px;
}
</style>
自動填充 auto
用于填充滿所有剩余空間
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box">7</div></div></template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: 100px 20% auto;
}.box {border: 1px solid #000;margin: 10px;
}
</style>
比例劃分 fr
fr 是 fraction 的縮寫,意為"片段"。
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box">7</div></div></template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: 100px 1fr 2fr;grid-template-rows: 3fr 1fr 2fr;
}.box {border: 1px solid #000;margin: 10px;
}
</style>
假設容器總寬度是 800px,grid-template-columns: 100px 1fr 2fr
則表示第一列占據 100px 寬度,第二列占據剩余 700px 的三分之一的寬度,第三列占據剩余 700px 的三分之二的寬度。
所以 grid-template-columns: 100px 20% 1fr
中最后一列的 1fr 其實也是鋪滿剩余空間的意思。
repeat 中也能用 fr。
最大最小值 minmax
minmax() 函數產生一個長度范圍,表示長度就在這個范圍之中。它接受兩個參數,分別為最小值和最大值。
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box">7</div></div></template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: 100px 100px minmax(100px, 1fr);grid-template-rows: 3fr 1fr 2fr;
}.box {border: 1px solid #000;margin: 10px;
}
</style>
最后一列表示寬度最小 100px,最大鋪滿剩余空間。
自動調整 auto-fit 和 auto-fill
<template><div class="parent auto-fit"><div class="box">1</div><div class="box">2</div><div class="box">3</div></div><div class="parent auto-fill"><div class="box">1</div><div class="box">2</div><div class="box">3</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;width: 600px;margin-bottom: 20px;
}.auto-fit {grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}.auto-fill {grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}.box {border: 1px solid #000;margin: 10px;
}
</style>
容器寬度為 600px,我們希望在其中放置一些最小寬度為 100px 的項目,每個項目的最大寬度為 1fr(即剩余空間的等分部分)。
理論上可以創建 6 個 100px 寬的列,但只有 3 個項目,所以會有 3 個空的列。
auto-fit 會合并多余的空列,使現有列擴展以填滿所有可用空間。
auto-fill 仍然會創建 6 個列,但其中 3 個列將是空的。
auto-fill 和 auto-fit 關鍵需要與 repeat() 函數和 minmax() 函數一起使用,才能發揮它們的作用。
在上例中我們看到,使用 auto-fill 時,項目的寬度始終時 minmax(100px, 1fr)
中的最小值 100px,那么 1fr 的作用是什么呢?
直接說結論:
-
當容器的寬度小于等于項目的寬度時,1fr 不會起作用
-
當容器的寬度是項目的寬度的整數倍時,1fr 不會起作用
-
當容器的寬度是項目的寬度的大于 1 的小數倍時,1fr 才會起作用
例如把上面的例子中改成:
.parent {width: 460px
}
每個項目寬度是 115px,被擴充了。
總結:
auto-fit 和 auto-fill 都會嘗試創建盡可能多的項目,例如 460px 的容器最多可以創建 4 個最小寬度為 100px 的項目,但是 html 中只有 3 個項目,對多出的這 1 個空白項目和剩余的額外 60px 空間的處理方式就是 auto-fit 和 auto-fill 的區別
-
auto-fit 會吞并多出的空白項目,使現有項目擴展以填滿所有剩余空間
-
auto-fill 會保留多出的空白項目,空白項目會占據空間,如果有剩余的額外,則所有項目會擴展以填滿剩余額外空間
指定區域
grid-template-areas
可以將網格布局中的某個單元格或多個單元格定義為一個區域。
網格區域一定要形成規整的矩形區域,無論是 L 形,還是凹的或凸的形狀都會認為是無效的屬性值。
按固定數值劃分
<template><div class="parent"><div class="box top">top</div><div class="box left">left</div><div class="box right">right</div><div class="box bottom">bottom</div></div>
</template><style scoped>
.parent {background-color: skyblue;height: 100%;display: grid;grid-template-columns: 50px auto;grid-template-rows: 70px auto 70px;grid-template-areas:"top top""left right""bottom bottom";
}.box {border: 1px solid #000;
}.top {grid-area: top;
}.left {grid-area: left;
}.right {grid-area: right;
}.bottom {grid-area: bottom;
}
</style>
按比例劃分
<template><div class="parent"><div class="box top">top</div><div class="box left">left</div><div class="box right">right</div><div class="box bottom">bottom</div></div>
</template><style scoped>
.parent {background-color: skyblue;height: 100%;display: grid;grid-template-columns: 1fr 1fr 1fr;grid-template-rows: 1fr 1fr 1fr 1fr;grid-template-areas:"top top top""left right right""left right right""bottom bottom bottom";
}.box {border: 1px solid #000;
}.top {grid-area: top;
}.left {grid-area: left;
}.right {grid-area: right;
}.bottom {grid-area: bottom;
}
</style>
grid-tempalte
是 grid-template-rows、grid-template-columns、grid-template-areas 的三個屬性的簡寫。
按固定數值劃分
上面的按固定數值劃分可以改造為:
.parent {background-color: skyblue;height: 100%;display: grid;grid-template:"top top" 70px"left right" auto"bottom bottom" 70px/ 50px auto;
}
第一行 "top top" 70px
定義了一個名為 top 的區域占據前兩列,并且該區域所在行的高度為 70px。
第二行 "left right" auto
定義了一個名為 left 的區域占據第一列和一個名為 right 的區域占據第二列,并且該區域所在行的高度為 auto。
第三行 "bottom bottom" 70px
定義了一個名為 bottom 的區域占據前兩列,并且該區域所在行的高度為 70px。
最后的 / 50px auto
定義了列的大小:第一列的寬度為 50px,第二列的寬度為 auto。
按比例劃分
上面的按比例劃分可以改造為:
.parent {background-color: skyblue;height: 100%;display: grid;grid-template:"top top top" 1fr"left right right" 1fr"left right right" 1fr"bottom bottom bottom" 1fr/ 1fr 1fr 1fr;
}
一行可以有多個不同的高度嗎?例如把第一行改成 "top top top" 1fr 50px
。答案是不行,會導致錯亂。
點代表占位符
.parent {background-color: skyblue;height: 100%;display: grid;grid-template:"top top ." 1fr"left . ." 1fr"right . ." 1fr"bottom bottom bottom" 1fr/ 1fr 1fr 1fr;
}
注意:
一個元素不能同時占據多個不連續的網格區域。
也就是說 "top top ."
和 ". top . "
、". . top"
等等都是允許的,但是 "top . top"
是不允許的。
其實 top
對應的是一個 html 元素,它要么占據連續的區域,要么占據一個單獨的單元格,它不能分裂成不連續的部分。
定義間距
行間距 row-gap
列間距 column-gap
<template><div class="parent"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div><div class="box">5</div><div class="box">6</div><div class="box">7</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: repeat(3, 1fr);grid-template-rows: repeat(3, 1fr);column-gap: 30px;row-gap: 20px;
}.box {border: 1px solid #000;
}
</style>
組合定義 gap
組合寫法 gap: 20px 30px;
先行(row)后列(column)
元素定位
grid-row/column-start/end
樣式屬性 | 說明 |
---|---|
grid-row-start | 行開始網格線 |
grid-row-end | 行結束網格線 |
grid-column-start | 列開始網格線 |
grid-column-end | 列結束網格線 |
屬性值 | 說明 |
---|---|
Line | 網格絡 |
span 數值 | 網格包含的網格數量 |
span 區域名稱 | 網格包含到指定的區域名稱 |
auto | 自動設置,默認為一個網格寬度和高度 |
用于指定一個網格項目的開始行(列)和結束行(列)的位置。
例如:
.grid-item1 {grid-row-start: 1; /* 從第 1 行開始 */grid-row-end: 3; /* 到第 3 行結束(不包括第 3 行,即跨越兩行) */
}.grid-item2 {grid-row-start: 1;grid-row-end: span 2; /* 從第 1 行開始,跨越 2 行 */
}
行線 1 對應第一行的上邊緣
行線 2 對應第二行的上邊緣
行線 3 對應第三行的上邊緣
…
grid-row-start 通常要比 grid-row-end 小,否則會導致一些意想不到的結果。
<template><div class="parent"><div class="box box1">1</div><div class="box box2">2</div><div class="box box3">3</div><div class="box box4">4</div><div class="box box5">5</div><div class="box box6">6</div><div class="box box7">7</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: repeat(3, 1fr);grid-template-rows: repeat(3, 1fr);gap: 20px 30px;
}.box {border: 1px solid #000;
}.box1 {grid-row-start: 1;
}
</style>
.box1 {grid-row-start: 2;
}
.box1 {grid-row-start: 3;
}
.box1 {grid-row-start: 4;
}
.box1 {grid-row-start: 1;grid-row-end: 3; /* 當該值是 1 和 2 時表現形式和默認圖相同,直接從 3 開始 */
}
.box1 {grid-row-start: 1;grid-row-end: 4;
}
.box1 {grid-row-start: 1;grid-row-end: 5;
}
.box1 {grid-row-start: 1;grid-row-end: 6;
}
簡寫模式 grid-row、grid-column
grid-row 和 grid-column
語法:
grid-row: grid-row-start / grid-row-end;
grid-column: grid-row-column / grid-row-column;
例如:
.box1 {grid-row-start: 1;grid-row-end: 6;
}
就可以簡寫成
.box1 {grid-row: 1/6;
}
超級簡寫模式 grid-area
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
網格流動 grid-auto-flow
在容器中設置 grid-auto-flow 屬性可以改變單元格排列方式。
選項 | 說明 |
---|---|
row | 按行排列,默認值 |
column | 按列排序 |
row dense | 網格將嘗試在行方向上盡可能緊密地放置項目,盡量不出現空格 |
column dense | 網格將嘗試在列方向上緊密放置項目,盡量不出現空格 |
<template><div class="parent"><div class="box box1">1</div><div class="box box2">2</div><div class="box box3">3</div><div class="box box4">4</div><div class="box box5">5</div><div class="box box6">6</div><div class="box box7">7</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: repeat(3, 1fr);grid-template-rows: repeat(3, 1fr);gap: 20px 30px;grid-auto-flow: row;
}.box {border: 1px solid #000;
}
</style>
grid-auto-flow: column
設置單元格對齊方式
justify-items
指定單元格內容的水平對齊方式
屬性 | 描述 |
---|---|
stretch | 默認值,占滿單元格的整個寬度 |
start | 對齊單元格的起始邊緣 |
end | 對齊單元格的結束邊緣 |
center | 單元格內部居中 |
<template><div class="parent"><div class="box box1">1</div><div class="box box2">2</div><div class="box box3">3</div><div class="box box4">4</div><div class="box box5">5</div><div class="box box6">6</div><div class="box box7">7</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: 1fr 1fr 1fr;grid-template-rows: repeat(3, 50px);gap: 20px;
}.box {border: 1px solid #000;
}
</style>
.parent {justify-items: start
}
.parent {justify-items: center
}
.parent {justify-items: end
}
align-items
指定單元格內容的垂直對齊方式
normal | 默認值,會根據使用場景的不同表現為 stretch 或者 start |
stretch | 拉伸,占滿單元格的整個寬度 |
start | 對齊單元格的起始邊緣 |
end | 對齊單元格的結束邊緣 |
center | 單元格內部居中 |
baseline | 基線對齊 |
.parent {align-items: normal; // 或 stretch
}
.parent {align-items: start;
}
.parent {align-items: center;
}
.parent {align-items: end;
}
place-items
是 align-items 屬性和 justify-items 屬性的合并簡寫形式。
.parent {// 先垂直方向,再水平方向place-items: start end;
}
IE 瀏覽器和 Edge 瀏覽器都不支持 place-items 屬性。如果不考慮瀏覽器的兼容性,在 CSS 中實現垂直居中對齊效果的最佳方法就是使用 grid 布局的 place-items 屬性:
.parent {// 如果省略第二個值,則瀏覽器認為與第一個值相等place-items: center;
}
justify-self
跟 justify-items 屬性的用法完全一致,但只作用于單個項目。
.box1 {justify-self: center
}
align-self
跟 align-items 屬性的用法完全一致,也是只作用于單個項目。
.box1 {align-self: center
}
place-self
是 align-self 屬性和 justify-self 屬性的合并簡寫形式,跟 place-items 屬性的用法完全一致。
.box1 {place-self: center
}
設置容器內的對齊方式
justify-content
項目在水平方向對齊方式
align-content
項目在垂直方向對齊方式
與 flex 布局中的類似。
注意:要想 justify-content 屬性和 align-content 屬性起作用,就需要讓項目的總尺寸小于 grid 容器的尺寸。
<template><div class="parent"><div class="box box1">1</div><div class="box box2">2</div><div class="box box3">3</div><div class="box box4">4</div><div class="box box5">5</div><div class="box box6">6</div><div class="box box7">7</div></div>
</template><style scoped>
.parent {background-color: skyblue;display: grid;grid-template-columns: repeat(3, 50px);grid-template-rows: repeat(3, 50px);gap: 20px;width: 100%;height: 300px;
}.box {border: 1px solid #000;
}
</style>
.parent {justify-content: space-between;
}
place-content
是 align-content 屬性和 justify-content 屬性的合并簡寫形式。如果省略第二個值,瀏覽器就會假定第二個值等于第一個值。
.parent {// 先垂直方向,再水平方向place-content: center space-between;
}
xxx-item 和 xxx-content 的區別
xxx-item 用于控制容器內每個項目的對齊方式。它影響的是每個單獨的項目在其所在單元格內的對齊方式。
xxx-content 用于控制容器內的所有項目的對齊方式。它影響的是所有項作為一個整體如何在容器內分配空間。
參考鏈接:
CSS3最強布局-Grid布局
css【詳解】grid布局—— 網格布局(柵格布局)