# Grid 格線佈局 透過設定欄(column)列(row)來達成像表格那樣的排版。 可分為外層的容器(container)與內層的項目(item),有各自的屬性可設置。 > 如果在一個方向上排列內容項目,應該使用Flexbox 會比Grid更加靈活,且程式碼少易維護;但是,如果要在兩個維度(包括欄和列)中建立整個佈局,則可使用 Grid ## 外容器 Grid container 在父層設置display:grid ```css! .container { display: grid; } ``` --- ## 使用 grid-template-columns/rows 設定格線欄/列 利用 <span class='red'>`grid-template-columns`</span> 來設定格線上的 **column**;用 <span class='red'>`grid-template-row`</span> 來設定格線的 **row**,在絕對意義上來說就是 height。 > grid-template-rows 是縱軸,grid-template-columns 則是橫軸 ![image](https://hackmd.io/_uploads/rklKmcZrp.png) ```htmlmixed! <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 class="item">10</div> <div class="item">11</div> <div class="item">12</div> </div> ``` ```css! .container { display: grid; width: 600px; height: 400px; grid-template-columns: 120px 80px auto 1fr 2fr; grid-template-rows: 100px 1fr 2fr; gap: 10px; } ``` <iframe height="410.8642578125" style="width: 100%;" scrolling="no" title="Untitled" src="https://codepen.io/mileyho/embed/QWYBbmz?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/QWYBbmz"> Untitled</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### grid-template 結合 grid-template-column 和 grid-template-row ```css! .container { display: grid; gap: 10px; grid-template: 120px 80px auto 1fr 2fr / 100px 1fr 2fr; /* 列(row)每格的寬度 / 欄(column)每格的寬度 */ } ``` --- ## 調整容器內欄列大小的單位 grid屬性可用的單位,px、%、em、auto、fr…皆可。 ### fr (fractional) * 只有在 Grid 出現的格線單位,是佔比(幾分之幾)的意思。1fr 是一等分的意思,2fr 就是兩等分,以此類推。 ``` grid-template-rows: 2fr 1fr 1fr; grid-template-columns: 2fr 1fr 1fr; ``` * 也可以和自定義的數值混用,這樣的話就會扣掉固定數值,剩下的寬(高)再平分。 ``` grid-template-rows: 30% 100px 1fr 1fr; grid-template-columns: 200px 1fr 1fr; ``` 範例: 當我們把第四個 column 設為 2fr,而前三個設為 1fr 的時候,代表把自由空間各分配 1 份給前三個 column,分配兩份給第四個 column (grid-template-rows: 1fr 1fr 1fr 2fr) <iframe height="200" style="width: 100%;" scrolling="no" title="Grid-1" src="https://codepen.io/mileyho/embed/xxMJObq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/xxMJObq"> Grid-1</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### auto * 使用 auto 代表依內容決定寬度,要注意和 fr 是不同的概念。 --- ## 利用 repeat() 來簡化欄列的寫法 **repeat(格數, 格寬/高)** **範例 1:** ``` grid-template-columns: 1fr 1fr 1fr 1fr; ``` 使用 repeat() 簡化成 ``` grid-template-columns: repeat(4, 1fr); ``` **範例 2:** ``` grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr 1fr 2fr; ``` 使用 repeat() 簡化成 ``` grid-template-columns: repeat(4, 1fr 2fr); ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid-1" src="https://codepen.io/mileyho/embed/JjxBBQv?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/JjxBBQv"> Grid-1</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> **問:** 那麼這樣有幾欄呢? ``` grid-template-columns: 200px repeat(4, 1fr 2fr) auto; ``` --- ## auto-fill / auto-fit 當我們使用 <span class='red'>`repeat()`</span> 時,可以在第一個參數設定第要重複的次數是 <span class='red'>`auto-fill`</span> 或 <span class='red'>`auto-fit`</span>。 若是不知道數量的情況下,這時就可以使用 <span class='red'>`auto-fit`</span> 或 <span class='red'>`auto-fill`</span> 自動填滿。 * ### auto-fill 會根據 grid 子層寬度自動計算需要填充的數量,若父層寬度大於子層許多的話,就會產生隱藏的欄位 * ### auto-fit 和 auto-fill 類似,視覺上的效果是會將原本欄位內的子層寬度都平均拉長,但實際上還是有新增欄位數,只是被摺疊起來了 <iframe height="360" style="width: 100%;" scrolling="no" title="Grid minmax" src="https://codepen.io/mileyho/embed/JjxBeJy?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/JjxBeJy"> Grid minmax</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> --- ## minmax **minmax(最小值, 最大值)** 可以利用<span class='red'>`grid-template-columns`</span>搭配<span class='red'>`minmax`</span>做出**RWD**效果。 例如設定成 `minmax(100px,1fr)` ,意思就是最小寬度是 100px,而最大寬度則是自動1等分。 範例: ``` grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid minmax" src="https://codepen.io/mileyho/embed/MWLBPQR?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/MWLBPQR"> Grid minmax</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> --- ## grid-auto-rows / grid-auto-columns <span class='red'>`grid-auto-rows`</span> 或 <span class='red'>`grid-auto-columns`</span>可以用來簡單設定 rows 或 columns的長度。 ### grid-auto-rows ```css! .container { display: grid; width: 50vw; grid-template-columns: 1fr 1fr 1fr; grid-auto-rows: 100px; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow column" src="https://codepen.io/mileyho/embed/yLZxwGY?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/yLZxwGY"> Grid grid-auto-flow column</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### grid-auto-columns ```css! .contaner { display: grid; grid-auto-columns: 200px; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-columns" src="https://codepen.io/mileyho/embed/JjxaWJa?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/JjxaWJa"> Grid grid-auto-columns</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 或是利用 <span class='red'>`grid-auto-rows`</span>來設定自動產生的 rows 的長度 ```css! .container { display: grid; grid-gap: 20px; grid-template-rows: 50px 200px; grid-auto-rows: 100px; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-rows 3" src="https://codepen.io/mileyho/embed/LYqJWJa?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/LYqJWJa"> Grid grid-auto-rows 3</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 當定義出 columns 的數量時,多出來的子元素會「換行」到下一個 row ```css! .container { display: grid; grid-gap: 20px; grid-template-columns: 100px 200px; grid-template-rows: 50px 100px; grid-auto-rows: 150px; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-columns" src="https://codepen.io/mileyho/embed/XWOPMqq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/XWOPMqq"> Grid grid-auto-columns</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> --- ## grid-auto-flow 像 <span class='red'>`flex-direction`</span> 這個屬性,用來控制排序要水平的還是垂直 ``` grid-auto-flow: row; grid-auto-flow: column; grid-auto-flow: dense; grid-auto-flow: row dense; grid-auto-flow: column dense; ``` grid 的預設值是垂直排列 <span class='red'>`row`</span>,當設定的 template 排完後,接著就會往下一列排列,所以如果是水平排列的話(先從上往下排列好後,往旁邊繼續排列)就要改成 <span class='red'>`grid-auto-flow: column;`</span> ### grid-auto-flow: row; ```css! .container{ display: grid; grid-template-columns: 1fr 1fr; grid-auto-flow: row; } ``` 使用grid-template屬性指定Grid的欄數為2欄 <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow column" src="https://codepen.io/mileyho/embed/eYxLyoK?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/eYxLyoK"> Grid grid-auto-flow column</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### grid-auto-flow: column; ```css! .container{ display: grid; grid-auto-flow: column; } ``` <iframe height="200" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow column" src="https://codepen.io/mileyho/embed/BaMOWRN?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/BaMOWRN"> Grid grid-auto-flow column</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 使用grid-template屬性指定Grid的列數為2列 ```css! .container{ display: grid; grid-template-rows: 1fr 1fr; grid-auto-flow: column; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-auto-flow row" src="https://codepen.io/mileyho/embed/gOqdoNr?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/gOqdoNr"> Grid grid-auto-flow row</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### grid-auto-flow: dense; 假如欄寬列高超過 template 的設定,grid 就會自動往下一行,這樣就會產生空白欄位,這邊我們就可以使用 <span class='red'>`dense`</span> ,利用其他合的欄寬補足空白 <iframe height="400" style="width: 100%;" scrolling="no" title="Grid minmax" src="https://codepen.io/mileyho/embed/MWLBLaP?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/MWLBLaP"> Grid minmax</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> <iframe height="300" style="width: 100%;" scrolling="no" title="CSS Grid Responsive Image Gallery" src="https://codepen.io/ramenhog/embed/MpORPa?default-tab=result&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/ramenhog/pen/MpORPa"> CSS Grid Responsive Image Gallery</a> by Stephanie (<a href="https://codepen.io/ramenhog">@ramenhog</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> <iframe height="300" style="width: 100%;" scrolling="no" title="Guided" src="https://codepen.io/ycw/embed/LgJEor?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/ycw/pen/LgJEor"> Guided</a> by ycw (<a href="https://codepen.io/ycw">@ycw</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> --- ## 項目 grid Item ### grid-[row/column]-start / grid-[row/column]-end 物件所佔的空間位置,column 及 row 所到的起始點及終點 ``` .item { grid-column-start: <number> | <name> | span <number> | span <name> | auto grid-column-end: <number> | <name> | span <number> | span <name> | auto grid-row-start: <number> | <name> | span <number> | span <name> | auto grid-row-end: <number> | <name> | span <number> | span <name> | auto } ``` * `<line>` - 用數字表示 物件 所在的線 * `span <number>` - 物件所佔用的欄位數 * `span <name>` - 物件所在的 grid 名稱 * `auto` - 自動,設定 auto 通常為 start 值 +1 ![image](https://hackmd.io/_uploads/HJW11INHp.png) ```css! .itemA{ grid-row-start: span 2; /* 起始為跨兩格*/ grid-row-end: -1; /* 終點為倒數第一條線 */ /* 負值為倒數數過來 */ grid-column-start: 2; /* 起始欄位第2條線 */ grid-column-end: span 2; /* 結束欄位線,從第二條線跨兩格 */ } ``` > **span**:跨越幾個區塊 > ### 合併: grid-[row/column]: start / end ```css! .itemA{ grid-row: span 3 / -1 ; /* startline / endline */ grid-column: 2 / span 2 ; /* startline / endline */ } ``` 如果只寫2,代表2-3的單位 ```css! .itemA{ grid-row: 2; /* == grid-row: 2 / 3; */ } ``` ### 大合併: grid-area ```css! .itemA{ grid-area: span 3 / 2 / -1 / span 2 ; /* row-start / column-start / row-end / column-end */ } ``` <iframe height="500" style="width: 100%;" scrolling="no" title="Grid grid-auto-rows 2" src="https://codepen.io/mileyho/embed/LYqJyPw?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/LYqJyPw"> Grid grid-auto-rows 2</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> --- ## 自訂格子和線的名字 使用 <span class='red'>`grid-template-columns` </span>和<span class='red'> `grid-template-rows`</span>畫好格子之後,也可以使用 <span class='red'>`grid-template-area`</span> 為特定的格子命名,並指定要將什麼元素放在此格子裡。 ### grid-template-areas * 區塊如果要合併,必須要連續,像ㄇ形或L型是不行的 * 定義完後,子元素必須加入 `grid-area` 指定區塊 * 使用<span class='red'>` . `</span>可以留空區塊 ```css! .container { display: grid; grid-template-rows: 60px 300px 300px; grid-template-columns: 200px 1fr 1fr; grid-template-areas: "nav nav nav" "sidebar content-01 content-02" "sidebar content-03 content-04"; /* (x) 倒L型 nav * grid-template-areas: * "nav nav nav" * "nav content-01 content-02" * "nav content-03 content-04"; */ } .nav { grid-area: nav; } .sidebar { grid-area: sidebar; } .content-01 { grid-area: content-01; } .content-02 { grid-area: content-02; } .content-03 { grid-area: content-03; } .content-04 { grid-area: content-04; } ``` <iframe height="500" style="width: 100%;" scrolling="no" title="grid-template-areas" src="https://codepen.io/mileyho/embed/eYxLVaq?default-tab=result&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/eYxLVaq"> grid-template-areas</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ```css! .container{ display: grid; grid-template-rows: 1fr 2fr 2fr; grid-template-columns: 2fr 1fr 1fr; grid-template-areas: "a a ." "a a ." ". b c"; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="grid-template-areas" src="https://codepen.io/mileyho/embed/BaMOEQB?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/BaMOEQB"> grid-template-areas</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 命名之後的區域,也可以搭配 <span class='red'>`grid-row`</span> 和 <span class='red'>`grid-column`</span>,直接定義要從哪個命名區塊開始或結束 ### 為格線命名 可以使用 <span class='red'>`[]`</span> 為格線命名,以便之後指定元素在格線上的位置時使用,一條格線可以不只一個命名,有點類似 CSS 的 class,可以有多重命名。 ```css! .container { display: grid; grid-gap: 20px; grid-template-columns: [sidebar-start site-left] 1fr [sidebar-end content-start] 500px [content-end] 1fr [site-right]; grid-template-rows: [content-top] repeat(10, auto) [content-bottom]; } .item3 { background: slateblue; grid-column: content-start; grid-row: content-top / content-bottom; /* grid-row: 1 / span 10; */ } ``` --- ## gap 各區塊之間的間距,可以一起設定,也可以用 `row-gap` 和 `column-gap` 分開設定。 --- ## 對齊方式 ### justify-content * 作用範圍: Grid容器。 * 作用對象: 用於設定Grid容器內所有子項目在主軸上的對齊方式。 ``` justify-content: start | end | center | stretch | space-between | space-around | space-evenly ``` <iframe height="300" style="width: 100%;" scrolling="no" title="grid-auto-flow span" src="https://codepen.io/mileyho/embed/ExrBZLw?default-tab=css%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/ExrBZLw"> grid-auto-flow span</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### justify-items * 作用範圍: Grid容器。 * 作用對象: 於設定Grid容器內所有子項目的默認對齊方式,可以被單個網格項目的justify-self屬性覆蓋。。 ``` justify-items: start | end | center | stretch | ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid justify-content" src="https://codepen.io/mileyho/embed/JjxQJwv?default-tab=css%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/JjxQJwv"> Grid justify-content</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ### justify-self ### align-items ``` align-items: start | end | center | stretch ``` ### align-self * 在 grid 容器上設定 <span class='red'>`justify-items`</span> 可以決定所有的 grid 子元素在水平線(主軸)上怎麼對齊,設定 <span class='red'>`align-items`</span> 可以設定所有的 grid 子元素在垂直線(交叉軸)上要怎麼對齊。 * 若只想要改變某個 grid 元素的對齊方式,可在子元素上設定 <span class='red'>`justify-self`</span> 即 <span class='red'>`align-self`</span>。 * 大致用法都和 flex 排版的原理相通。 --- ## 排序:order 利用order來改變排列順序,所有子元素的預設 order 是 0,但是順序可以被任意設置為正數或者負數。 ```css! .container { display: grid; grid-gap: 20px; grid-template-columns: repeat(10, 1fr); } .logo { grid-column: span 2; order: 2; } .nav { grid-column: span 8; order: 1; } .content { grid-column: 1 / -1; order: 3; } ``` <iframe height="300" style="width: 100%;" scrolling="no" title="Grid grid-area" src="https://codepen.io/mileyho/embed/LYqJyJN?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/mileyho/pen/LYqJyJN"> Grid grid-area</a> by Miley (<a href="https://codepen.io/mileyho">@mileyho</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> ## justify-self, align-self --- [**Grid by Example 🌐**](https://gridbyexample.com/) --提供大量關於 CSS Grid 的範例和資源,從基礎到進階的都有 [**Grid 小遊戲 🌐**](https://cssgridgarden.com/#zh-tw) [**Amos 影片教學 🌐**](https://www.youtube.com/watch?v=fYcz3FUqv7M) <style> .red{ color: crimson; } </style>