Grid 網格布局
網格布局是最強大的CSS布局方案,將網頁划分成一個個網格
可以任意組合不同的網格,做出各種各樣的布局
網格布局與彈性布局有一定的相似性,都可以指定容器內部多個項目的位置,
但是也存在重大區別
1.1 和flex布局的區別:
- grid容器子項是單元格,而非子元素(當然,如果子元素沒有設置寬高,那么他的寬高跟隨單元格,值得一提的是,子元素樣式calc函數的100%也是相對於單元格而非容器元素),而flex容器的子項直接即是子元素
- Flex布局是軸線布局,只能指定"項目"針對軸線的位置,是一維布局
- grid將容器划分成行和列,產生單元格,然后指定項目所在單元格,可以看作是二維布局
1.2 基本概念
容器和項目:即容器結點和子節點
行和列:水平區域/垂直區域
單元格:行和列的交叉區域,n行m列會產生n×m個單元格
網格線:划分網格的線,水平網格線和垂直網格線分別決定了行和列,n行有n+1根網格線
1.3 容器屬性
- Grid項目指子節點,不包含孫子節點,Grid子項(單元格)默認都是塊級元素
- 和flex布局一樣,Grid布局不影響容器之外的元素
- 設置Grid布局以后,容器子項的float、display等屬性失效
- 指定網格布局:display:grid
1.3.1 指定塊級容器和行內容器
display:grid
display:inline-grid
1.3.2 列寬和行高
容器指定了網格布局以后,接着就要划分行和列
grid-template-columns: 每列列寬, 是設置子項(單元格)的屬性,而不是子元素寬高,但是可以用calc函數相對於父元素做子元素計算
grid-template-rows:每行行高
有時候重復的值很多,寫起來很麻煩,這時,可以使用repeat函數,簡化重復的值
簡寫:
grid-template-columns:repeat(3, 33, 33%) 三列均分布局
grid-template-rows:repeat(3, 33.33%) 每行行高為33.33%
<style>
.wrapper {
height: 500px;
width: 600px;
display: grid;
background: lightseagreen;
/* 定義列寬。指的是子項(單元格)的寬度,而非子元素的寬度*/
grid-template-columns: repeat(3, 200px);
/* 定義每行行高 */
grid-template-rows: 100px 100px 100px;
/* repeat(3,200px) equals to 200px 200px 200px */
}
.child {
width: 100px;
height: 100px;
background: lightsalmon;
font-size: 12px;
}
</style>
<body>
<div class="wrapper">
<div class="child"><span>grandchild</span></div>
<div class="child"><span>grandchild</span></div>
<div class="child"><span>grandchild</span></div>
</div>
</body>
1.3.3 自動填充 auto-fill關鍵字
有時候,單元格大小固定,但是容器的大小不固定,可以用這個屬性包含盡可能多的列
即:不指定容器的列數,只指定容器的列寬,具體一行多少列數,由容器寬來做自適應,盡可能容納更多的列數
<style>
.container{
width: 430px;
height: 500px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(auto-fill,100px);
grid-template-rows: repeat(3 200px);
gap: 10px;
}
.item{
width: 100px;
height: 100px;
background: lightsalmon;
}
</style>
<body>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
1.3.4 比例關系 fr關鍵字
有時候為了方便表示比例關系,grid布局提供了fr關鍵字(fraction, 片段)
如果兩列的寬分別為1fr 和 2fr 那么前者是后者的兩倍
如果全是1fr, 表示均分
如果是100px 1fr 2fr, 則表示第一列100px, 剩下均分,但是第二列是第三列的1/2
<style>
.container{
width: 530px;
height: 500px;
background: lightseagreen;
display: grid;
/* 4個單元格均分容器寬 */
/* grid-template-columns: repeat(4,1fr); */
/* 第一列寬200px,剩下3列均分剩余容器寬 */
grid-template-columns: 200px repeat(3,1fr);
grid-template-rows: repeat(3 200px);
gap: 10px;
}
.item{
/* 這個100%是相對於單元格,而非容器 */
width: calc(100% - 10px);
height: 100px;
background: lightsalmon;
}
</style>
<body>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
1.3.5 長度范圍 minmax
minmax指定長度范圍,如指定第一列列寬不小於100px不大於200px
<! DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container{
width: 530px;
height: 500px;
background: lightseagreen;
display: grid;
/* 指定寬度范圍,實際寬度190px,按最大情況處理,剩下fr均分 */
grid-template-columns: minmax(100px,200px) repeat(3,1fr);
grid-template-rows: repeat(3 200px);
gap: 10px;
}
.item{
/* 這個100%是相對於單元格,而非容器 */
width: calc(100% - 10px);
height: 100px;
background: lightsalmon;
}
</style>
<body>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>
1.3.6 Grid實現兩欄布局和三欄自適應布局
三欄布局,中間自適應, 將左右兩欄寫死,中間設置1fr自動分配即可
<style>
body,
html {
width: 100%;
height: 100%;
/* 去掉滾動條 */
margin: 0;
}
.container {
width: 100%;
height: 100%;
background: lightseagreen;
display: grid;
/* 兩欄布局 */
/* grid-template-columns: 70% 30%; */
/* 三欄布局,中間自適應,將左右兩欄寫死,中間設置1fr自適應分配即可 */
grid-template-columns: 100px 1fr 200px;
/*不寫默認是100%,子元素默認撐滿單元格高度 */
/* grid-template-rows: 100px; */
}
.left {
background: skyblue;
}
.right {
background: rebeccapurple;
}
.con {
background: orange;
}
</style>
<body>
<div class="container">
<div class="left"></div>
<div class="con"></div>
<div class="right"></div>
</div>
</body>
1.3.7 grid間隔
grid-row-gap:設置行間隔
grid-column-gap:設置列間隔
grid-gap: 設置行間隔於列間隔
<! DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container{
width: 530px;
height: 500px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 10px 10px;
}
.item{
background: lightsalmon;
}
</style>
<body>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>
1.3.8 grid-auto-flow屬性
通過grid-template-columns和grid-template-rows設置好行列,確定好單元格之后
可以用grid-auto-flow來決定子元素是先填滿行還是先填滿列
<! DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container {
width: 930px;
height: 900px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 10px 10px;
/* 先行后列,默認,即子元素先填滿行 */
/* grid-auto-flow: row; */
/* 先列后行,即子元素先填滿第一列 */
grid-auto-flow: column;
}
.item {
width: 50px;
height: 50px;
background: lightsalmon;
}
</style>
<body>
<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>
</body>
</html>
1.3.9 justify-items align-items justify-content align-content
justify-items align-items
設置的是單元格內容相對於單元格的水平/垂直位置
start:對齊單元格的起始邊緣
end:對齊單元格的結束邊緣
center:單元格內部居中
stretch:拉伸,占滿單元格的整個寬度(默認值)
jusityfy-content align-content
設置的是整個內容區域在Grid容器中的位置
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
<! DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container {
width: 930px;
height: 900px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 10px 10px;
/* justify-items/align-items設置單元格內容的水平/垂直位置 */
justify-items: center;
align-items: center;
}
.item {
width: 50px;
height: 50px;
background: lightsalmon;
}
</style>
<body>
<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>
</body>
</html>
1.4 子項屬性
1.4.1 grid-columns-start/end 指定某個子項起止哪根網格線
<! DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container {
width: 930px;
height: 900px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 10px 10px;
/* 先行后列,默認,即子元素先填滿行 */
/* grid-auto-flow: row; */
/* 先列后行,即子元素先填滿第一列 */
/* grid-auto-flow: column; */
}
.item {
/* width: 100%; */
/* height: 100%; */
width: 50px;
height: 50px;
background: lightsalmon;
}
/* grid-column-start/end 第一個子元素起始於垂直第一根網格線,終止於垂直第三根網格線,共占據兩個單元格 */
.item:nth-child(1){
width: 100%;
background: red;
grid-column-start: 1;
grid-column-end: 3;
}
</style>
<body>
<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>
</body>
</html>
1.4.2 grid-area 指定某個元素位於哪個區域
如以下位於區域e
.container {
width: 930px;
height: 900px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 10px 10px;
/* justify-items/align-items設置單元格內容的水平/垂直位置 */
/* justify-items: center; */
/* align-items: center; */
/* justify-content/align-content設置的是內容區域在整個Grid容器中的位置 */
/* justify-content: space-between ; */
grid-template-areas: 'a b c'
'd e f'
'g h i';
}
.item {
/* width: 50px; */
/* height: 50px; */
background: lightsalmon;
}
.item:nth-child(1) {
grid-area: e;
}
1.4.3 jusity-slef align-self
設置單元格內容的水平/垂直位置,jusity-slef、align-self跟justify-items、align-self的用法效果相同,卻別在於,前者是子項屬性,只作用於某一個單元格,后者是容器屬性,作用於所有單元格
如以下案例只會設置第一個子項水平在單元格內水平垂直居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.container {
width: 930px;
height: 900px;
background: lightseagreen;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 10px 10px;
/* justify-items/align-items設置所有單元格內容的水平/垂直位置 */
/* justify-items: center; */
/* align-items: center; */
/* justify-content/align-content設置的是內容區域在整個Grid容器中的位置 */
/* justify-content: space-between ; */
}
.item {
width: 100px;
height: 100px;
background: lightsalmon;
}
.item:nth-child(1) {
/* 設置的是某個子元素在單元格內容中的水平/垂直位置 */
justify-self: center;
align-self: center;
}
</style>
<body>
<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>
</body>
</html>