伸縮盒模型
CSS3 引入的布局模式 Flexbox 布局
主要思想: 讓容器有能力讓其子項目能夠改變其寬度,高度,以最佳方式填充可用空間。
特點:
display: flex; 只能控制其子元素
浮動無法影響伸縮容器,但是如果內聯伸縮容器 設置了浮動,元素將會以塊級伸縮容器顯示。
伸縮容器的 margin 與其內容的 margin 不會重疊
項目構建,會將新版語法構建成老板語法
主軸在水平方向時,元素要換行,但是子元素沒有 width,此時,使用換軸(父元素加 flex-direction: column;)
- 面試題: 用 CSS3 屬性實現元素 水平垂直居中,除了 trnasform: translate(-50%, -50%);
-
/**** 新版語法 ****/ #wrap { display: flex; justify-content: center; align-items: center; } /**** 老版語法 ****/ #wrap { display: -webkit-flex; -webkit-box-pack: center; -webkit-box-align: center; }
以上代碼適用於 任何類型子元素 的水平垂直居中(塊元素,行內元素,行內塊元素)。
-
- 概論:
- 主軸:Flex 容器的主軸主要用來配置 Flex 項目。他不一定是水平的,這主要取決於 flex-direction 屬性。
-
- 主軸起點,主軸終點:Flex 項目 的配置從容器的主軸起點邊開始,往主軸終點邊結束。
-
- 主軸長度:Flex 項目 在主軸方向的寬度或高度就是項目的主軸長度,Flex 項目 的主軸長度屬性是 width 或 height 屬性,由哪一個對着主軸方向決定。
- 側軸:與主軸垂直的軸稱作側軸,是側軸方向的延伸。
-
- 側軸起點,側軸終點:伸縮行的配置從容器的側軸起點邊開始,往側軸終點邊結束。
-
- 側軸長度:Flex 項目 在側軸方向的寬度或高度就是項目的側軸長度,Flex 項目 的側軸長度屬性是 widht 或 height 屬性,由哪一個對着主軸方向決定。
- Flex 布局 局限性: 因為語法規范版本眾多,瀏覽器支持不一致,致使 Flexbox 布局使用不多。
- Flexbox 布局 語法規范 主要分成三種:
- 舊版本,2009 年版本,是最早的伸縮布局,各大主流瀏覽器對其支持性略有不同,可惜的是,對 Flexbox 布局的各屬性支持也不完全,在使用時還需添加各瀏覽器的前綴。
-
- 混合版本,2011 年版本,只有 IE10 支持。
-
- 最新版本,2012 年版本,除了 Safari 瀏覽器不支持外,其他最新瀏覽器都支持這個版本。
1. 伸縮容器屬性(父元素屬性)
- 使用伸縮盒模型 的前提:
- 應用於 父元素 子元素
-
display: flex;
-
設置為塊級伸縮容器。
-
/**** 新老版本兼容寫法 ****/ #wrap { display: -webkit-box; display: -webkit-flex; display: flex; }
- 塊級伸縮容器獨占一行
- 有些設計用來控制塊布局的屬性在伸縮布局中不適用
-
-
display: inline-flex; 設置為內聯級伸縮容器。
- 如果內聯伸縮容器設置了浮動,元素將會以塊級伸縮容器顯示。
- flex-direction: row | row-reverse | column | column-reverse;
定義 Flex 項目 在 Flex 容器 中放置的方向。
- 側軸拉伸:子元素 px 與父元素 等 px
- 主軸: 子元素 px 由內容撐開
- row: 默認值,
- 如果書寫方式是 ltr,那么 Flex 項目從左向右排列;
- 如果書寫方式是 rtl,那么 Flex 項目從右向左排列。
- row-reverse:
- 如果書寫方式是 ltr,那么 Flex 項目從右向左排列;
- 如果書寫方式是 rtl,那么 Flex 項目從左向右排列。
- column:
- 和 row 類似,方向從上到下排列。
- column-reverse:
- 和row-reverse類似,方向從下到上排列。
- justify-content: flex-start | flex-end | center | space-between | space-around;
設置 伸縮項目 在主軸上的對齊方式。
指定如何在 伸縮項目 之間分布伸縮容器富裕空間
- flex-start
- 默認值,伸縮項目向一行的起始位置靠齊。
- 伸縮容器沿着布局軸方向的所有額外空間都被置於布局軸的末尾。
- flex-end
- 伸縮項目向一行的結束位置靠齊。
- 伸縮容器沿着布局軸方向的所有額外空間都被置於布局軸的開始。
- center
- 伸縮項目向一行的中間位置靠齊。
- 伸縮容器的所有額外空間平均分布在第一伸縮項目前面和最后一個伸縮項目的后面。
- space-between
- 伸縮項目會平均分布在行里。
- 伸縮容器的所有額外空間平均分布在所有伸縮項目之間,
- 但是在第一個伸縮項目之前和最后一個伸縮項目之后不分配空間,
- 也就是說,第一個伸縮項目靠齊開始位置,最后一個伸縮項目靠齊結束位置。
- space-around
- 伸縮項目會品均分布在行里。
- 伸縮容器的所有額外空間品均分布在所有伸縮項目之間
- 但是第一個伸縮項目之前與最后一個伸縮項目之后只分配其他位置得到額外空間的一半。
- align-items: flex-start | flex-end | center | baseline | stretch;
設置 伸縮項目 在主軸上的對齊方式。
align-items 控制的是每一行的富裕空間
align-items 是用來管理伸縮容器側軸方向的額外空間
- flex-start
- 伸縮項目在側軸起點邊的外邊距緊靠住該行在側軸起始的邊。
- flex-end
- 伸縮項目在側軸終點邊的外邊距靠住該行在側軸終點的邊。
- center
- 伸縮項目的外邊距盒在該行的側軸上居中放置。
- stretch
- 如果側軸 長度屬性 的值為 auto,則此值會使項目的外邊距盒的尺寸在遵照 min/max-width/height 屬性的限制下盡可能接近所在行的尺寸
- baseline
- 如果伸縮項目的行內軸與側軸為同一條,則該值和 flex-start 等效。
- 其它情況下,該值將參與基線對齊。
- 所有參與該對齊方式的伸縮項目將按下列方式排列
- 首先將這些伸縮項目的基線進行對齊,
- 隨后其中基線至側軸起點邊的外邊距距離最長的那個項目將緊靠住該行在側軸起點的邊。
- flex-wrap: nowrap | wrap | wrap-reverse;
flex 項目 實現換行
新版本 flex 容器 特有屬性
換行以后:
- 有多個側軸(wrap-reverse 會替換所有側軸的 start 和 end)
- 整體側軸(align-content 控制整體側軸的富裕空間)
- 單行側軸(align-items 控制的是每一行的富裕空間)
- 幾行就有幾個單行側軸
- 整體側軸與單行側軸 一樣時,整體側軸生效(有打包效果)
- nowrap
- 默認值,父元素寬度不夠,子元素的自身寬度會進行壓縮
- 默認元素始終在一行,無論設置多少 width,height
- wrap
- 父元素寬度不夠,子元素自動進行換行
- 由於側軸默認拉伸 stretch,所以側軸距離被子元素均分
- wrap-reverse
- 子元素換行的同時,側軸的 start 與 end 發生對調
- align-content: stretch | flex-start | flex-end | center | space-between | space-around;
生效條件:
- 伸縮容器 必須有 flex-wrap: wrap;
- 伸縮容器 height 設置足夠的高(因為需要整體打包才能看見效果)
- stretch
- flex-start
- flex-end
- center
- 只要元素捆到一塊兒,在中間,就是側軸 flex 項目 center
- space-between
- space-around
- flex-flow: wrap-reverse colum;
是 flex-wrap 和 flex-direction 的縮寫
等同於 flex-wrap: wrap-reverse; flex-direction: colum;
- 最終元素換行,取決於主軸的位置
- 主軸 在水平方向上,子元素須設置足夠的 width 實現換行
- 主軸 在垂直方向上,子元素須設置足夠的 height 實現換行
waiting
2. 伸縮項目屬性(子元素屬性)
- flex-grow: 1 | 2 | ... ...;
設置 Flex 項目 的擴大比例,或者說,空間分配比例
flex-grow 處理的是 伸縮容器內部 剩下的額外空間
默認值為 0,不能取負值,沒有單位
- 1, 2, 3____分別占 1/5, 2/5, 3/5
-
<style> .box{ width:100%; border-bottom: 1px solid red; display:flex; } .box div{ width:100px; border:1px solid; } .box div:nth-child(1){ flex-grow:1; } .box div:nth-child(2){ flex-grow:2; } .box div:nth-child(3){ flex-grow:3; } </style> </head> <body> <div class="box"> <div>A</div> <div>B</div> <div>C</div> </div> </body>
- flex-shrink: 1 | 2 | ... ...;
收縮率 flex-shrink 處理的是 由於伸縮容器太小, 溢出的額外空間。處理是,按比例分配,不寫比例,默認1份
默認值 1,即如果溢出,每個子元素均分容器主軸空間
- 計算過程:
默認 將溢出部分分成 n 份,每個 伸縮項目 縮放 1/n
- 父盒子300px,剛剛好不溢出,
- 父盒子100px,溢出,則元素縮放,按比例分配
- A 壓縮溢出部分的 1/4
- B 壓縮溢出部分的 2/4
- C 壓縮溢出部分的 1/4
-
<style> .box{ width:100px; border-bottom: 1px solid red; display:flex; } .box div{ width:100px; border:1px solid; } .box div:nth-child(1){ flex-shrink:1; } .box div:nth-child(2){ flex-shrink:2; } .box div:nth-child(3){ flex-shrink:1; } </style> </head> <body> <div class="box"> <div>A</div> <div>B</div> <div>C</div> </div> </body>
- order: 1 | 2 | ... ...;
flex 項目 的排列順序,沿着主軸方向進行排序
未排序元素正常排列再前,將 排序元素 單獨拿出來,再在后面排序
- align-self: stretch | flex-start | flex-end | center;
flex 項目自身的側軸富裕空間
- flex-basis: 0;
flex 項目 的基准值
- 實現 等分布局 的兩種方法:
- 第一種方法
-
/**** 新版語法(面試題) ****/
#inner_box {
flex-basis: 0; /**** 讓 伸縮項目 的 主軸空間(width/height) 始終等於 0 ****/
flex-grow: 1;
}
/**** 老版語法(面試題) ****/
#inner_box {
width: 0;
-webkit-box-flex: 1; /**** 等同於新版的 flex-grow ****/
}- 主軸方向上,伸縮項目 永遠等分 伸縮容器,不會被 內容 打破布局
- 第二種方法
-
/**** 新版本 特有實現 等分布局 ****/ #inner_box { flex: 1; /**** ----等同於 flex-basis: 0; flex-grow: 1; flex-shrink: 1; ****/ }
- flex 是 flex-grow,flex-shrink,flex-basis 的簡寫屬性
- 默認值
- flex-grow: 0;
- flex-shrink: 1;
- flex-basis: auto;
- flex: none; ----等同於 flex: 0, 0, auto; ----等同於 display: flex;
- flex: 1; ----等同於 flex: 1, 1, 0%;
- 默認值
- flex 是 flex-grow,flex-shrink,flex-basis 的簡寫屬性
- 典例:
- 給 ul 設置 display: flex; 使 li 元素在一行
- 給 li 設置 flex-basis: 0; flex-grow: 1; 等分布局
- 給 li 設置 display: flex; justify-content: center; 使文字水平居中
- 使用 ::before 來設置圖片,發現文字不居中了(<a> 元素居中了,但是由於圖片的加入,文字就不居中了)
- 給 a 設置 display: flex; flex-direction: column; align-items: center; 實現文本再水平居中
-
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> * { margin: 0; padding: 0; } /**** Double Line Goods ****/ a { text-decoration: none; } #top_line, #bottom_line { display: flex; list-style: none; } #top_line li, #bottom_line li { /**** 等分布局 ****/ flex-flow: 0; flex-grow: 1; display: flex; justify-content: center; /**** li 中 子元素 水平居中 ****/ } #top_line li a, #bottom_line li a { display: flex; flex-direction: column; /**** a 中 子元素 在一列 ****/ align-items: center; /**** a 中 文字水平居中 ****/ } #top_line li a::before, #bottom_line li a::before { content:""; display: block; width: 86px; height: 86px; } #top_line li:nth-child(1) a::before { background-image: url(./img/01.png); } #top_line li:nth-child(2) a::before { background-image: url(./img/02.png); } #top_line li:nth-child(3) a::before { background-image: url(./img/03.png); } #top_line li:nth-child(4) a::before { background-image: url(./img/04.png); } #top_line li:nth-child(5) a::before { background-image: url(./img/05.png); } #bottom_line li:nth-child(1) a::before { background-image: url(./img/06.png); } #bottom_line li:nth-child(2) a::before { background-image: url(./img/07.png); } #bottom_line li:nth-child(3) a::before { background-image: url(./img/08.png); } #bottom_line li:nth-child(4) a::before { background-image: url(./img/09.png); } #bottom_line li:nth-child(5) a::before { background-image: url(./img/10.png); } </style> </head> <body> <ul id="top_line"> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> </ul> <ul id="bottom_line"> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> <li><a href="javascript:;">天貓</a></li> </ul> </body> </html>
- 骰子
- display: flex;
- align-self: center; // 可以實現自身水平居中
- justify-content: space-around;
- box-sizing: border-box; padding: 4px;
-
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Dice</title> <style type="text/css"> *{ padding: 0; margin: 0; } body { width: 100%; padding-top: 300px; color: #000; background: #96b377; font: 14px Helvetica, Arial, sans-serif; display: flex; justify-content: center; align-items: center; } /**** flex 實現 Dice ****/ /* 白點 */ .dice_point { width: 20px; height: 20px; border-radius: 100%; background-color: #fff; } /* 黑底 */ .diy_dice { width: 140px; height: 140px; background-color: #000; } #dice_1 { display: flex; justify-content: center; align-items: center; } #dice_2 { display: flex; justify-content: space-between; padding: 20px 20px; box-sizing: border-box; } #dice_2>div:nth-child(2){ align-self: flex-end; } #dice_3 { display: flex; justify-content: space-between; padding: 20px 20px; box-sizing: border-box; } #dice_3>div:nth-child(2){ align-self: center; } #dice_3>div:nth-child(3){ align-self: flex-end; } #dice_4, #dice_5, #dice_6 { display: flex; justify-content: space-between; padding: 20px 20px; box-sizing: border-box; } #dice_4>div:nth-child(1), #dice_4>div:nth-child(2), #dice_5>div:nth-child(1), #dice_5>div:nth-child(3), #dice_6>div:nth-child(1), #dice_6>div:nth-child(2) { display: flex; flex-direction: column; justify-content: space-between; } #dice_5>div:nth-child(2){ align-self: center; } /**** 3D 盒子 + 旋轉****/ #dice_box { position: relative; width: 140px; height: 140px; perspective: 2800px; transform-style: preserve-3d; transform-origin: 50% 50% -70px; transform: rotateX(-20deg) rotateY(20deg); animation: turnaround 5s infinite alternate; } @keyframes turnaround { from{ transform: rotateX(0deg) rotateY(0deg); } to{ transform: rotateX(-360deg) rotateY(360deg); } } .diy_dice { position: absolute; } #dice_2 { top: -100%; transform-origin: bottom; transform: rotateX(90deg); } #dice_3 { left: 100%; transform-origin: left; transform: rotateY(90deg); } #dice_4 { left: -100%; transform-origin: right; transform: rotateY(-90deg); } #dice_5 { top: 100%; transform-origin: top; transform: rotateX(-90deg); } #dice_6 { transform: rotateY(180deg) translateZ(140px) ; } </style> </head> <body> <div id="dice_box"> <div id="dice_1" class="diy_dice"> <div class="dice_point"></div> </div> <div id="dice_2" class="diy_dice"> <div class="dice_point"></div> <div class="dice_point"></div> </div> <div id="dice_3" class="diy_dice"> <div class="dice_point"></div> <div class="dice_point"></div> <div class="dice_point"></div> </div> <div id="dice_4" class="diy_dice"> <div> <div class="dice_point"></div> <div class="dice_point"></div> </div> <div> <div class="dice_point"></div> <div class="dice_point"></div> </div> </div> <div id="dice_5" class="diy_dice"> <div> <div class="dice_point"></div> <div class="dice_point"></div> </div> <div class="dice_point"></div> <div> <div class="dice_point"></div> <div class="dice_point"></div> </div> </div> <div id="dice_6" class="diy_dice"> <div> <div class="dice_point"></div> <div class="dice_point"></div> <div class="dice_point"></div> </div> <div> <div class="dice_point"></div> <div class="dice_point"></div> <div class="dice_point"></div> </div> </div> </div> </body> </html>