# [CSS] Grid ###### tags: `前端筆記` `style` 1. 外層容器畫線,裡面的子元素畫格子(依照格子佔位) 2. Grid 編排的角度 => 一開始就全部排好,像畫圖填格子一樣 3. Flex 編排的角度 => 由上到下一層一層排好 ## 下在外層容器的屬性 - grid-template-columns - grid-template-rows - grid-template-areas ### grid-template-columns - 決定橫向有 n 格 - 決定 寬度 ### grid-template-rows - 決定直向有 m 格 - 決定 高度 ### gap - `grid-row-gap` 及 `grid-column-gap` 的縮寫 #### 外層畫一個 4 X 3 的容器 - 外層容器是畫線。 `grid-template-columns: 1fr 1fr 1fr 1fr;` 一排(橫向)有 4 個格子,每個格子都拿到 1 份外層容器平分後的寬度 - `grid-template-columns: 1fr 1fr 1fr 1fr;` = `grid-template-columns: repeat(4, 1fr);` 會重複寫的可以用 repeat(要重複的次數, 要重複的東西) `grid-template-rows: repeat(3, 1fr)` 一列(直向)有 3 個格子,每個格子都拿到 1 份外層容器平分後的高度 - 同理,`grid-template-rows: repeat(3, 1fr)` = `grid-template-rows: 1fr 1fr 1fr` ```htmlembedded= <body> <div class="wrapper1"> <!-- 畫一個 4 X 3 的格子 --> </div> </body> ``` ```css= .wrapper1 { display: grid; height: 300px; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: repeat(3, 1fr); } ``` ![](https://i.imgur.com/NOq3wqO.png) #### 幫每一格加上間距(gap) `gap: <grid-row-gap> <grid-column-gap>` ```css= .wrapper1 { display: grid; height: 300px; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: repeat(3, 1fr); gap: 10px 15px; } ``` ![](https://i.imgur.com/YwEGrTV.png) - 每個格子橫向會有 15 px 的間距 - 同理,直向就是 10 ## 下在子元素本身的屬性 - grid-column - grid-row - grid-area ### grid-column - `grid-column: <start-line> / <end-line>;` - 決定子元素橫向佔多少線 - 總線數為外層 grid-template-columns 創造出的 n 個格子 + 1 ### grid-row - `grid-row: <start-line> / <end-line>;` - 決定子元素直向佔多少線 - 總線數為外層 grid-template-rows 創造出的 m 個格子 + 1 #### 記得子元素 grid-column 及 gird-row 是數線的 ```css= .wrapper1 { display: grid; height: 300px; grid-template-columns: 1fr 2fr 1fr; grid-template-rows: repeat(3, 1fr); gap: 10px 15px; /*<grid-row-gap> <grid-column-gap>*/ .header { grid-column: 1 / -1; /* 第 1 條到 - 1 條線 = 第 1 條到最後 1 條線*/ background-color: green; } .side-bar { grid-column: 1 / 2; background-color: yellow; } .content { grid-column: 2 / -1; background-color: blue; } footer { grid-column: 1 / -1; background-color: pink; } } ``` ![](https://i.imgur.com/p7yjdXf.png) ## Learn CSS Grid in 20 Minutes 影片範例 ### 1. grid-auto-columns / rows - 為格子的基準寬度 / 高度 - 如果橫向 / 直向的格子數不夠, auto 就會變成沒被設定之格子的寬度 / 高度,如果其他格子使用比例分的大小的,要先扣掉基準才會分比例 - [範例](https://codepen.io/lun0223/pen/vYZqgKe) - [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) (0600-0700) ### 2. minmax(最小範圍, 最大範圍) Q: 如果高度設定固定值,但內文太多造成實際需要的高度會 > 設定值,看起來會怎麼樣呢? A: 如果是用 `grid-auto-rows` 就會炸出來,因為 `grid-auto-rows` 的基準很強大。這時就要用 `minmax(x, autp)` 讓高度最小為 x ,如果內容超過 x ,就隨著內容長大。 ![](https://i.imgur.com/VrOVMfq.png) - [範例](https://codepen.io/lun0223/pen/zYzVZXL) - [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) (0710-0750) ### 3. 為每個格子命名排版 `grid-template-areas` + `grid-area` 直接在外層元素使用這個屬性(`grid-template-areas`),依名字排版,內層元素(`grid-area: 名字`)在個別命名。 - [範例](https://codepen.io/lun0223/pen/BaZgRQW) - [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) (0850-1030) ### 也可以用數線或者數格子(span) > 一開始在排版的時候就要先安排大區塊,思考整體的安排。 這裡先插入一個小觀念,Grid 大致分兩個區塊:explicit(明確的)& implicit(不明確的)。下列的文章有詳細介紹 XDD。 https://nicolakacha.coderbridge.io/2020/09/22/css-flex-grid-2/ #### explicit(明確的)& implicit(不明確的) ##### 1. explicit(明確的) 有明確設定出來的區域(也就是設定中的格式),吃得到外層設定的 `grid-template-columns` & `grid-template-rows` 的比例。 ##### 2.implicit(不明確的) 明確區域之外的就是屬於 implicit(不明確的)的區域。此區域吃不到外層設定的排版。 >為什麼會有這個呢?因為子元素的排列超過外層容器規定的線啦。 ![](https://i.imgur.com/y1iTAlC.png) *因為外層設定垂直向 `grid-template-rows: 150px 200px;` 只有兩格,但是排版的關係 Side-bar 1 跟 Side-bar 2 把垂直的格數佔掉了。所以讓多出來的區域高(height)失靈,但橫向沒超過,所以還是會維持寬(width)。* #### 不想數線嗎?那就用 `span` 數格子吧! 算格子真的比較簡單... `gird-column / row: default span 1` 預設都會佔一格。 `span` 就是「算格子」,而 `grid-column / row` 是算「線」。 - [範例](https://codepen.io/lun0223/pen/abwgVrw) ### Grid 的排序與各種對齊方式 #### 該怎麼對齊? 有兩種屬性決定對齊的方式: ##### 1. `justify-items` `justify-items: start | end | center | stretch (default)` 決定子元素在水平軸上的對齊(橫向)。 ##### 2. `align-items` `Align-items: start | end | center | stretch (default)` 決定子元素在交叉軸上的對齊(直向)。 >道理和 flex-box 差不多,但是不像 flex-box 主線軸的方向(flex-direction)會影響兩個屬性對齊的方向。 #### 如果想要對齊單個子元素呢? ##### 1. `justify-self` ##### 2. `align-self` 範例可以看 [A Complete Guide to Grid](https://css-tricks.com/snippets/css/complete-guide-grid/#top-of-site)。 #### RWD 組合技 ```htmlembedded= <div class="contaier"> <div class="grid-item grid-item-1">grid-item-1</div> <div class="grid-item grid-item-2">grid-item-2</div> <div class="grid-item grid-item-3">grid-item-3</div> <div class="grid-item grid-item-4">grid-item-4</div> <div class="footer">Footer</div> </div> ``` ```scss= body { background-color: rgba(0, 0, 0, 0.2); } .contaier { border: 1px solid white; width: 200px; display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); > * { border: 1px solid white; } .grid-item-1 { background-color: #ffba08; } .grid-item-2 { background-color: #e85d04; } .grid-item-3 { background-color: #d00000; } .grid-item-4 { background-color: #8ecae6; } .footer { background-color: #a68a64; } } ``` ##### `grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));` - repeat(auto-fit, minmax(100px, 1fr)) 盡可能的製造出橫向格,每格最小為 100px,超過 100px 每格最多拿到一份平分後的空間。 ###### 誰決定有幾個格子? - 該容器擁有幾個子元素影響有幾個格子 - (min)假設容器的空間是 600px,有六個子元素,那麼每個元素就會分到 100px 的空間。 - (max)假設容器的空間是 600px,但這次只有兩個子元素,那麼每個元素就會分到 300px 的空間。 ###### 那麼為什麼可以做 RWD? 只要容器縮小到沒辦法滿足最小的需求 minmax(最小, 最大),那麼就會縮排,讓子元素滿足最大的需求(也就是佔 1fr)。 - [範例](https://codepen.io/lun0223/pen/qBjzVGV) - https://nicolakacha.coderbridge.io/2020/09/22/css-flex-grid-2/ - [Grid 切不同大小的格子 + RWD 設置](https://codepen.io/lun0223/pen/abLbbVJ?editors=1100) ## 之後 Grid 可以看這系列文章重新整理 https://ithelp.ithome.com.tw/users/20001433/ironman/3944 ## Grid 容器範例 ### 1. 外容器切分兩個項目,單個項目又成為 Grid 容器 ![](https://hackmd.io/_uploads/BJUwthmvc.png) ![](https://hackmd.io/_uploads/SJ8DFnQw5.png) ### 2. 公司專案:外層容器使用 `grid-template-areas` 定義區塊位置,內層項目使用 `grid-area` 命名位置 ![截圖 2024-08-20 10.44.42](https://hackmd.io/_uploads/HyF7XtWs0.png) 簡略版本的 HTML 結構: ```htmlembedded <!-- 若使用 grid-template-areas 用定義的方式區分區塊,那麼 HTML 的順序沒差,也可以 .content, .menu, .header,但是為了讓結構維持可讀性,還是建議按照順序定義結構 --> <div class="layout"> <div class="header"></div> <div class="menu"></div> <div class="content"></div> </div> ``` ```css /* 外層容器 */ /* 容器定義項目為 2 x 2 */ .layout { display: grid; /* 定義橫向 */ grid-template-columns: min-content auto; /* 定義直向 */ grid-template-rows: 52px 1fr; /* 定義區塊位子 */ /* menu 的區塊會佔兩個直向的區塊 */ grid-template-areas: "menu header" "menu content"; } .header { grid-area: header; } .menu { grid-area: menu; } .content { grid-area: content; } ``` ## 參考資料 1. [CSS Flex & Grid 排版詳解(下):Oh My Grid!](https://nicolakacha.coderbridge.io/2020/09/22/css-flex-grid-2/) -> RWD 組合技 2. [Learn CSS Grid in 20 Minutes](https://www.youtube.com/watch?v=9zBsdzdE4sM) 3. [A Complete Guide to Grid](https://css-tricks.com/snippets/css/complete-guide-grid/#top-of-site) -> 可以看裡面屬性的範例 4. https://grid.malven.co/ -> 屬性範例 5. [CSS Grid 网格布局教程](https://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html) 6. [Less Absolute Positioning With Modern CSS => 其他用 `display: grid` 取代 `position: absolute` 的奇淫技巧](https://ishadeed.com/article/less-absolute-positioning-modern-css/?fbclid=IwAR0Z2NOOvroCvfxEui9RN2eOEAgsGtzxyfEKsVVcyce-gKTUgbPvptpmItQ) 7. [Overlap Elements With CSS Grid Instead Of Position Absolute => masharea 就是用 `display: grid` 讓 UI 能夠重疊](https://pqina.nl/blog/css-grid-position-absolute-alternative/)