有一點需要注意的是,你的小程序要求兼容到iOS8以下版本,需要開啟樣式自動補全。開啟樣式自動補全,在“設置”—“項目設置”—勾選“上傳代碼時樣式自動補全”。
圖4-2 開發者工具開啟樣式自動補全
在小程序開發中,我們需要考慮各種尺寸終端設備上的適配。在傳統網頁開發,我們用的是盒模型,通過display:inline | block | inline-block、 position、float來實現布局,缺乏靈活性且有些適配效果難以實現。比如像下面這種常見的信息列表,要求內容高度不確定下保持垂直居中:
圖4-3 常見的信息列表排版方式
這種情況下,我們更建議用flex布局。
在開始介紹flex之前,為了表述方便,我們約定以下術語:采用flex布局的元素,簡稱為“容器”,在代碼示例中以container表示容器的類名。容器內的元素簡稱為“項目”,在代碼示例中以item表示項目的類名。
圖4-4 container容器和item項目
4.2.1 基本概念
flex的概念最早是在2009年被提出,目的是提供一種更靈活的布局模型,使容器能通過改變里面項目的高寬、順序,來對可用空間實現最佳的填充,方便適配不同大小的內容區域。
在不固定高度信息的例子中,我們只需要在容器中設置以下兩個屬性即可實現內容不確定下的垂直居中。
.container{
display: flex;
flex-direction: column;
justify-content: center;
}
flex不單是一個屬性,它包含了一套新的屬性集。屬性集包括用於設置容器,和用於設置項目兩部分。
設置容器的屬性有:
display:flex;
flex-direction:row(默認值) | row-reverse | column |column-reverse
flex-wrap:nowrap(默認值) | wrap | wrap-reverse
justify-content:flex-start(默認值) | flex-end | center |space-between | space-around | space-evenly
align-items:stretch(默認值) | center | flex-end | baseline | flex-start
align-content:stretch(默認值) | flex-start | center |flex-end | space-between | space-around | space-evenly
設置項目的屬性有:
order:0(默認值) | <integer>
flex-shrink:1(默認值) | <number>
flex-grow:0(默認值) | <number>
flex-basis:auto(默認值) | <length>
flex:none | auto | @flex-grow @flex-shrink @flex-basis
align-self:auto(默認值) | flex-start | flex-end |center | baseline| stretch
在開始介紹各個屬性之前,我們需要先明確一個坐標軸。默認的情況下,水平方向的是主軸(main axis),垂直方向的是交叉軸(cross axis)。
圖4-5 默認情況下的主軸與交叉軸
項目是在主軸上排列,排滿后在交叉軸方向換行。需要注意的是,交叉軸垂直於主軸,它的方向取決於主軸方向。
圖4-6 項目是在主軸上排列,排滿后在交叉軸方向換行
接下來的例子如無特殊聲明,我們都以默認情況下的坐標軸為例。
4.2.2 容器屬性
設置容器,用於統一管理容器內項目布局,也就是管理項目的排列方式和對齊方式。
flex-direction 屬性
通過設置坐標軸,來設置項目排列方向。
.container{
flex-direction: row(默認值) | row-reverse | column | column-reverse
}
row(默認值):主軸橫向,方向為從左指向右。項目沿主軸排列,從左到右排列。
row-reverse:row的反方向。主軸橫向,方向為從右指向左。項目沿主軸排列,從右到左排列。
column:主軸縱向,方向從上指向下。項目沿主軸排列,從上到下排列。
column-reverse:column的反方向。主軸縱向,方向從下指向上。項目沿主軸排列,從下到上排列。
圖4-7 flex-direction
flex-wrap 屬性
設置是否允許項目多行排列,以及多行排列時換行的方向。
.container{
flex-wrap: nowrap(默認值) | wrap | wrap-reverse
}
nowrap(默認值):不換行。如果單行內容過多,則溢出容器。
wrap:容器單行容不下所有項目時,換行排列。
wrap-reverse:容器單行容不下所有項目時,換行排列。換行方向為wrap時的反方向。
圖4-8 flex-wrap
justify-content 屬性
設置項目在主軸方向上對齊方式,以及分配項目之間及其周圍多余的空間。
.container{
justify-content: flex-start(默認值) | flex-end | center | space-between | space-around| space-evenly
}
flex-start(默認值):項目對齊主軸起點,項目間不留空隙。
center:項目在主軸上居中排列,項目間不留空隙。主軸上第一個項目離主軸起點距離等於最后一個項目離主軸終點距離。
flex-end:項目對齊主軸終點,項目間不留空隙。
space-between:項目間間距相等,第一個項目離主軸起點和最后一個項目離主軸終點距離為0。
space-around:與space-between相似。不同點為,第一個項目離主軸起點和最后一個項目離主軸終點距離為中間項目間間距的一半。
space-evenly:項目間間距、第一個項目離主軸起點和最后一個項目離主軸終點距離等於項目間間距。
圖4-9 justify-content
align-items 屬性
設置項目在行中的對齊方式。
.container{
align-items:stretch(默認值) | flex-start | center | flex-end | baseline
}
stretch(默認值):項目拉伸至填滿行高。
flex-start:項目頂部與行起點對齊。
center:項目在行中居中對齊。
flex-end:項目底部與行終點對齊。
baseline:項目的第一行文字的基線對齊。。
圖4-10 align-items
align-content 屬性
多行排列時,設置行在交叉軸方向上的對齊方式,以及分配行之間及其周圍多余的空間。
.container{
align-content: stretch(默認值) | flex-start | center | flex-end | space-between |space-around | space-evenly
}
stretch(默認值):當未設置項目尺寸,將各行中的項目拉伸至填滿交叉軸。當設置了項目尺寸,項目尺寸不變,項目行拉伸至填滿交叉軸。
flex-start:首行在交叉軸起點開始排列,行間不留間距。
center:行在交叉軸中點排列,行間不留間距,首行離交叉軸起點和尾行離交叉軸終點距離相等。
flex-end:尾行在交叉軸終點開始排列,行間不留間距。
space-between:行與行間距相等,首行離交叉軸起點和尾行離交叉軸終點距離為0。
space-around:行與行間距相等,首行離交叉軸起點和尾行離交叉軸終點距離為行與行間間距的一半。
space-evenly:行間間距、以及首行離交叉軸起點和尾行離交叉軸終點距離相等。
圖4-11 align-content
4.2.3 項目屬性
設置項目,用於設置項目的尺寸、位置,以及對項目的對齊方式做特殊設置。
order 屬性
設置項目沿主軸方向上的排列順序,數值越小,排列越靠前。屬性值為整數。
.item{
order: 0(默認值) | <integer>
}
圖4-12 order
flex-shrink 屬性
當項目在主軸方向上溢出時,通過設置項目收縮因子來壓縮項目適應容器。屬性值為項目的收縮因子,屬性值取非負數。
.item{
flex-shrink: 1(默認值) | <number>
}
.item1{
width: 120px;
flex-shrink: 2;
}
.item2{
width: 150px;
flex-shrink: 3;
}
.item3{// 項目3未設置flex-shrink,默認flex-shrink值為1
width: 180px;
}
為了加深理解,我們舉個例子:
一個寬度為400px的容器,里面的三個項目width分別為120px,150px,180px。分別對這項目1和項目2設置flex-shrink值為2和3。
.container{
display: flex;
width: 400px; // 容器寬度為400px
}
在這個例子中,項目溢出 400 - (120 + 150 + 180) = -50px。計算壓縮量時總權重為各個項目的寬度乘以flex-shrink的總和,這個例子壓縮總權重為120 * 2 + 150 * 3+ 180 * 1 = 870。各個項目壓縮空間大小為總溢出空間乘以項目寬度乘以flex-shrink除以總權重:
item1的最終寬度為:120 - 50 * 120 * 2 / 870 ≈ 106px
item2的最終寬度為:150 - 50 * 150 * 3 / 870 ≈ 124px
item3的最終寬度為:180 - 50 * 180 * 1 / 870 ≈ 169px
其中計算時候值如果為小數,則向下取整。
圖4-13 flex-shrink
需要注意一點,當項目的壓縮因子相加小於1時,參與計算的溢出空間不等於完整的溢出空間。在上面例子的基礎上,我們改變各個項目的flex-shrink。
.container{
display: flex;
width: 400px; // 容器寬度為400px
}
.item1{
width: 120px;
flex-shrink: 0.1;
}
.item2{
width: 150px;
flex-shrink: 0.2;
}
.item3{
width: 180px;
flex-shrink: 0.3;
}
總權重為:120 * 0.1 + 150 * 0.2 + 180 * 0.3 = 96。參與計算的溢出空間不再是50px,而是50 * (0.1 + 0.2 + 0.3) / 1 =30:
item1的最終寬度為:120 - 30 * 120 * 0.1 / 96 ≈ 116px
item2的最終寬度為:150 - 30 * 150 * 0.2 / 96 ≈ 140px
item3的最終寬度為:180 - 30 * 180 * 0.3 / 96 ≈ 163px
flex-grow 屬性
當項目在主軸方向上還有剩余空間時,通過設置項目擴張因子進行剩余空間的分配。屬性值為項目的擴張因子,屬性值取非負數。
.item{
flex-grow: 0(默認值) | <number>
}
為了加深理解,我們舉個例子:
一個寬度為400px的容器,里面的三個項目width分別為80px,120px,140px。分別對這項目1和項目2設置flex-grow值為3和1。
.container{
display: flex;
width: 400px; // 容器寬度為400px
}
.item1{
width: 80px;
flex-grow: 3;
}
.item2{
width: 120px;
flex-grow: 1;
}
.item3{// 項目3未設置flex-grow,默認flex-grow值為0
width: 140px;
}
在這個例子中,容器的剩余空間為 400 - (80 + 120 + 140) = 60px。剩余空間按 60 / (3 + 1 + 0) = 15px進行分配:
item1的最終寬度為:80+ (15 * 3) = 125px
item2的最終寬度為:120 + (15 * 1) = 135px
item3的最終寬度為:140 + (15 * 0) =140px
圖4-14 flex-grow
需要注意一點,當項目的擴張因子相加小於1時,剩余空間按除以1進行分配。在上面例子的基礎上,我們改變各個項目的flex-grow。
.container{
display: flex;
width: 400px; // 容器寬度為400px
}
.item1{
width: 50px;
flex-grow: 0.1;
}
.item2{
width: 80px;
flex-grow: 0.3;
}
.item3{
width: 110px;
flex-grow: 0.2;
}
在這個例子中,容器的剩余空間為 400 - (50 + 80 + 110) = 160px。由於項目的flex-grow相加0.1 + 0.3 + 0.2 = 0.6小於1,剩余空間按 160 / 1 = 160px划分。例子中的項目寬度分別為:
item1的最終寬度為:50 + (160 * 0.1) = 66px
item2的最終寬度為:80 + (160 * 0.3) = 128px
item3的最終寬度為:110 + (160 * 0.2) = 142px
flex-basis 屬性
當容器設置flex-direction為row或row-reverse時,flex-basis和width同時存在,flex-basis優先級高於width,也就是此時flex-basis代替項目的width屬性。
當容器設置flex-direction為column或column-reverse時,flex-basis和height同時存在,flex-basis優先級高於height,也就是此時flex-basis代替項目的height屬性。
需要注意的是,當flex-basis和width(或height),其中一個屬性值為auto時,非auto的優先級更高。
.item{
flex-basis: auto(默認值) | <number>px
}
圖4-15 flex-basis
flex 屬性
是flex-grow,flex-shrink,flex-basis的簡寫方式。值設置為none,等價於00 auto。值設置為auto,等價於1 1 auto。
.item{
flex: none | auto | @flex-grow @flex-shrink@flex-basis
}
align-self 屬性
設置項目在行中交叉軸方向上的對齊方式,用於覆蓋容器的align-items,這么做可以對項目的對齊方式做特殊處理。默認屬性值為auto,繼承容器的align-items值,當容器沒有設置align-items時,屬性值為stretch。
.item{
align-self: auto(默認值) | flex-start | center | flex-end | baseline |stretch
}
圖4-16 align-self
.
