基本的布局方法——Flex布局

4.2 基本的布局方法——Flex布局

如果之前你接觸過網(wǎng)頁開發(fā)中的flexbox布局,基本上你可以略過這節(jié)。但有一點需要注意的是,你的小程序要求兼容到iOS8以下版本,需要開啟樣式自動補全。開啟樣式自動補全,在“設(shè)置”—“項目設(shè)置”—勾選“上傳代碼時樣式自動補全”。

image.png

? 圖4-2 開發(fā)者工具開啟樣式自動補全

在小程序開發(fā)中,我們需要考慮各種尺寸終端設(shè)備上的適配。在傳統(tǒng)網(wǎng)頁開發(fā),我們用的是盒模型,通過display:inline | block | inline-block、 position、float來實現(xiàn)布局,缺乏靈活性且有些適配效果難以實現(xiàn)。比如像下面這種常見的信息列表,要求內(nèi)容高度不確定下保持垂直居中:

圖4-3 常見的信息列表排版方式

? 圖4-3 常見的信息列表排版方式

這種情況下,我們更建議用flex布局。

在開始介紹flex之前,為了表述方便,我們約定以下術(shù)語:采用flex布局的元素,簡稱為“容器”,在代碼示例中以container表示容器的類名。容器內(nèi)的元素簡稱為“項目”,在代碼示例中以item表示項目的類名。

圖4-4 container容器和item項目

4.2.1 基本概念

flex的概念最早是在2009年被提出,目的是提供一種更靈活的布局模型,使容器能通過改變里面項目的高寬、順序,來對可用空間實現(xiàn)最佳的填充,方便適配不同大小的內(nèi)容區(qū)域。

在不固定高度信息的例子中,我們只需要在容器中設(shè)置以下兩個屬性即可實現(xiàn)內(nèi)容不確定下的垂直居中。

.container{

  display: flex;

  flex-direction: column;

  justify-content: center;

}

flex不單是一個屬性,它包含了一套新的屬性集。屬性集包括用于設(shè)置容器,和用于設(shè)置項目兩部分。

設(shè)置容器的屬性有:

display:flex;

flex-direction:row(默認(rèn)值) | row-reverse | column |column-reverse

flex-wrap:nowrap(默認(rèn)值) | wrap | wrap-reverse

justify-content:flex-start(默認(rèn)值) | flex-end | center |space-between | space-around | space-evenly

align-items:stretch(默認(rèn)值) | center  | flex-end | baseline | flex-start

align-content:stretch(默認(rèn)值) | flex-start | center |flex-end | space-between | space-around | space-evenly

設(shè)置項目的屬性有:

order:0(默認(rèn)值) | <integer>

flex-shrink:1(默認(rèn)值) | <number>

flex-grow:0(默認(rèn)值) | <number>

flex-basis:auto(默認(rèn)值) | <length>

flex:none | auto | @flex-grow @flex-shrink @flex-basis

align-self:auto(默認(rèn)值) | flex-start | flex-end |center | baseline| stretch

在開始介紹各個屬性之前,我們需要先明確一個坐標(biāo)軸。默認(rèn)的情況下,水平方向的是主軸(main axis),垂直方向的是交叉軸(cross axis)。

圖4-5 默認(rèn)情況下的主軸與交叉軸

項目是在主軸上排列,排滿后在交叉軸方向換行。需要注意的是,交叉軸垂直于主軸,它的方向取決于主軸方向。

?圖4-6 項目是在主軸上排列,排滿后在交叉軸方向換行

接下來的例子如無特殊聲明,我們都以默認(rèn)情況下的坐標(biāo)軸為例。

4.2.2 容器屬性

設(shè)置容器,用于統(tǒng)一管理容器內(nèi)項目布局,也就是管理項目的排列方式和對齊方式。

flex-direction 屬性

通過設(shè)置坐標(biāo)軸,來設(shè)置項目排列方向。

.container{
  flex-direction: row(默認(rèn)值) | row-reverse | column | column-reverse
}

row(默認(rèn)值):主軸橫向,方向為從左指向右。項目沿主軸排列,從左到右排列。

row-reverse:row的反方向。主軸橫向,方向為從右指向左。項目沿主軸排列,從右到左排列。

column:主軸縱向,方向從上指向下。項目沿主軸排列,從上到下排列。

column-reverse:column的反方向。主軸縱向,方向從下指向上。項目沿主軸排列,從下到上排列。

圖4-7 flex-direction

flex-wrap 屬性

設(shè)置是否允許項目多行排列,以及多行排列時換行的方向。

.container{
  flex-wrap: nowrap(默認(rèn)值) | wrap | wrap-reverse
}

nowrap(默認(rèn)值):不換行。如果單行內(nèi)容過多,則溢出容器。
wrap:容器單行容不下所有項目時,換行排列。
wrap-reverse:容器單行容不下所有項目時,換行排列。換行方向為wrap時的反方向。

?
圖4-8 flex-wrap

justify-content 屬性

設(shè)置項目在主軸方向上對齊方式,以及分配項目之間及其周圍多余的空間。

.container{

  justify-content: flex-start(默認(rèn)值) | flex-end | center | space-between | space-around| space-evenly

}

flex-start(默認(rèn)值):項目對齊主軸起點,項目間不留空隙。

center:項目在主軸上居中排列,項目間不留空隙。主軸上第一個項目離主軸起點距離等于最后一個項目離主軸終點距離。

flex-end:項目對齊主軸終點,項目間不留空隙。
space-between:項目間間距相等,第一個項目離主軸起點和最后一個項目離主軸終點距離為0。
space-around:與space-between相似。不同點為,第一個項目離主軸起點和最后一個項目離主軸終點距離為中間項目間間距的一半。

space-evenly:項目間間距、第一個項目離主軸起點和最后一個項目離主軸終點距離等于項目間間距。

圖4-9 justify-content

align-items 屬性

設(shè)置項目在行中的對齊方式。

.container{

  align-items:stretch(默認(rèn)值) | flex-start | center | flex-end | baseline

}

stretch(默認(rèn)值):項目拉伸至填滿行高。
flex-start:項目頂部與行起點對齊。
center:項目在行中居中對齊。
flex-end:項目底部與行終點對齊。
baseline:項目的第一行文字的基線對齊。。

圖4-10 align-items

align-content 屬性

多行排列時,設(shè)置行在交叉軸方向上的對齊方式,以及分配行之間及其周圍多余的空間。

.container{

  align-content: stretch(默認(rèn)值) | flex-start | center | flex-end | space-between |space-around | space-evenly

}

stretch(默認(rèn)值):當(dāng)未設(shè)置項目尺寸,將各行中的項目拉伸至填滿交叉軸。當(dāng)設(shè)置了項目尺寸,項目尺寸不變,項目行拉伸至填滿交叉軸。

flex-start:首行在交叉軸起點開始排列,行間不留間距。

center:行在交叉軸中點排列,行間不留間距,首行離交叉軸起點和尾行離交叉軸終點距離相等。

flex-end:尾行在交叉軸終點開始排列,行間不留間距。
space-between:行與行間距相等,首行離交叉軸起點和尾行離交叉軸終點距離為0。
space-around:行與行間距相等,首行離交叉軸起點和尾行離交叉軸終點距離為行與行間間距的一半。

space-evenly:行間間距、以及首行離交叉軸起點和尾行離交叉軸終點距離相等。



圖4-11 align-content

4.2.3 項目屬性

設(shè)置項目,用于設(shè)置項目的尺寸、位置,以及對項目的對齊方式做特殊設(shè)置。

order 屬性

設(shè)置項目沿主軸方向上的排列順序,數(shù)值越小,排列越靠前。屬性值為整數(shù)。

.item{

  order: 0(默認(rèn)值) | <integer>

}

圖4-12 order

?

flex-shrink 屬性

當(dāng)項目在主軸方向上溢出時,通過設(shè)置項目收縮因子來壓縮項目適應(yīng)容器。屬性值為項目的收縮因子,屬性值取非負(fù)數(shù)。

.item{

  flex-shrink: 1(默認(rèn)值) | <number>

}

.item1{

  width: 120px;

  flex-shrink: 2;

}

.item2{

  width: 150px;

  flex-shrink: 3;

}

.item3{// 項目3未設(shè)置flex-shrink,默認(rèn)flex-shrink值為1

  width: 180px;

}

為了加深理解,我們舉個例子:

一個寬度為400px的容器,里面的三個項目width分別為120px,150px,180px。分別對這項目1和項目2設(shè)置flex-shrink值為2和3。

.container{

  display: flex;

  width: 400px; // 容器寬度為400px

}

在這個例子中,項目溢出 400 - (120 + 150 + 180) = -50px。計算壓縮量時總權(quán)重為各個項目的寬度乘以flex-shrink的總和,這個例子壓縮總權(quán)重為120 * 2 + 150 * 3+ 180 * 1 = 870。各個項目壓縮空間大小為總溢出空間乘以項目寬度乘以flex-shrink除以總權(quán)重:

item1的最終寬度為:120 - 50 * 120 * 2 / 870 ≈ 106px

item2的最終寬度為:150 - 50 * 150 * 3 / 870 ≈ 124px

item3的最終寬度為:180 - 50 * 180 * 1 / 870 ≈ 169px

其中計算時候值如果為小數(shù),則向下取整。

圖4-13 flex-shrink

?

需要注意一點,當(dāng)項目的壓縮因子相加小于1時,參與計算的溢出空間不等于完整的溢出空間。在上面例子的基礎(chǔ)上,我們改變各個項目的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;

}

總權(quán)重為: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 屬性

當(dāng)項目在主軸方向上還有剩余空間時,通過設(shè)置項目擴張因子進(jìn)行剩余空間的分配。屬性值為項目的擴張因子,屬性值取非負(fù)數(shù)。

.item{

  flex-grow: 0(默認(rèn)值) | <number>

}

為了加深理解,我們舉個例子:

一個寬度為400px的容器,里面的三個項目width分別為80px,120px,140px。分別對這項目1和項目2設(shè)置flex-grow值為3和1。

.container{

  display: flex;

  width: 400px; // 容器寬度為400px

}

.item1{

  width: 80px;

  flex-grow: 3;

}

.item2{

  width: 120px;

  flex-grow: 1;

}

.item3{// 項目3未設(shè)置flex-grow,默認(rèn)flex-grow值為0

  width: 140px;

}

在這個例子中,容器的剩余空間為 400 - (80 + 120 + 140) = 60px。剩余空間按 60 / (3 + 1 + 0) = 15px進(jìn)行分配:

item1的最終寬度為:80+ (15 * 3) = 125px

item2的最終寬度為:120 + (15 * 1) = 135px

item3的最終寬度為:140 + (15 * 0) =140px

圖4-14 flex-grow

?

需要注意一點,當(dāng)項目的擴張因子相加小于1時,剩余空間按除以1進(jìn)行分配。在上面例子的基礎(chǔ)上,我們改變各個項目的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 屬性

當(dāng)容器設(shè)置flex-direction為row或row-reverse時,flex-basis和width同時存在,flex-basis優(yōu)先級高于width,也就是此時flex-basis代替項目的width屬性。

當(dāng)容器設(shè)置flex-direction為column或column-reverse時,flex-basis和height同時存在,flex-basis優(yōu)先級高于height,也就是此時flex-basis代替項目的height屬性。

需要注意的是,當(dāng)flex-basis和width(或height),其中一個屬性值為auto時,非auto的優(yōu)先級更高。

.item{

  flex-basis: auto(默認(rèn)值) | <number>px

}

圖4-15 flex-basis

flex 屬性

是flex-grow,flex-shrink,flex-basis的簡寫方式。值設(shè)置為none,等價于00 auto。值設(shè)置為auto,等價于1 1 auto。

.item{

  flex: none | auto | @flex-grow @flex-shrink@flex-basis

}

align-self 屬性

設(shè)置項目在行中交叉軸方向上的對齊方式,用于覆蓋容器的align-items,這么做可以對項目的對齊方式做特殊處理。默認(rèn)屬性值為auto,繼承容器的align-items值,當(dāng)容器沒有設(shè)置align-items時,屬性值為stretch。

.item{

  align-self: auto(默認(rèn)值) | flex-start | center | flex-end | baseline |stretch

}

圖4-16 align-self

?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容