4.2 基本的布局方法——Flex布局
如果之前你接觸過(guò)網(wǎng)頁(yè)開(kāi)發(fā)中的flexbox布局悄晃,基本上你可以略過(guò)這節(jié)。但有一點(diǎn)需要注意的是,你的小程序要求兼容到iOS8以下版本饶火,需要開(kāi)啟樣式自動(dòng)補(bǔ)全。開(kāi)啟樣式自動(dòng)補(bǔ)全致扯,在“設(shè)置”—“項(xiàng)目設(shè)置”—勾選“上傳代碼時(shí)樣式自動(dòng)補(bǔ)全”肤寝。
? 圖4-2 開(kāi)發(fā)者工具開(kāi)啟樣式自動(dòng)補(bǔ)全
在小程序開(kāi)發(fā)中,我們需要考慮各種尺寸終端設(shè)備上的適配抖僵。在傳統(tǒng)網(wǎng)頁(yè)開(kāi)發(fā)鲤看,我們用的是盒模型,通過(guò)display:inline | block | inline-block裆针、 position刨摩、float來(lái)實(shí)現(xiàn)布局,缺乏靈活性且有些適配效果難以實(shí)現(xiàn)世吨。比如像下面這種常見(jiàn)的信息列表澡刹,要求內(nèi)容高度不確定下保持垂直居中:
? 圖4-3 常見(jiàn)的信息列表排版方式
這種情況下,我們更建議用flex布局耘婚。
在開(kāi)始介紹flex之前罢浇,為了表述方便,我們約定以下術(shù)語(yǔ):采用flex布局的元素,簡(jiǎn)稱(chēng)為“容器”嚷闭,在代碼示例中以container表示容器的類(lèi)名攒岛。容器內(nèi)的元素簡(jiǎn)稱(chēng)為“項(xiàng)目”,在代碼示例中以item表示項(xiàng)目的類(lèi)名胞锰。
4.2.1 基本概念
flex的概念最早是在2009年被提出灾锯,目的是提供一種更靈活的布局模型,使容器能通過(guò)改變里面項(xiàng)目的高寬嗅榕、順序顺饮,來(lái)對(duì)可用空間實(shí)現(xiàn)最佳的填充,方便適配不同大小的內(nèi)容區(qū)域凌那。
在不固定高度信息的例子中兼雄,我們只需要在容器中設(shè)置以下兩個(gè)屬性即可實(shí)現(xiàn)內(nèi)容不確定下的垂直居中。
.container{
display: flex;
flex-direction: column;
justify-content: center;
}
flex不單是一個(gè)屬性帽蝶,它包含了一套新的屬性集赦肋。屬性集包括用于設(shè)置容器,和用于設(shè)置項(xiàng)目?jī)刹糠帧?/p>
設(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è)置項(xiàng)目的屬性有:
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
在開(kāi)始介紹各個(gè)屬性之前励稳,我們需要先明確一個(gè)坐標(biāo)軸佃乘。默認(rèn)的情況下,水平方向的是主軸(main axis)麦锯,垂直方向的是交叉軸(cross axis)恕稠。
項(xiàng)目是在主軸上排列,排滿后在交叉軸方向換行扶欣。需要注意的是鹅巍,交叉軸垂直于主軸,它的方向取決于主軸方向料祠。
接下來(lái)的例子如無(wú)特殊聲明柑土,我們都以默認(rèn)情況下的坐標(biāo)軸為例振亮。
4.2.2 容器屬性
設(shè)置容器芒珠,用于統(tǒng)一管理容器內(nèi)項(xiàng)目布局沧烈,也就是管理項(xiàng)目的排列方式和對(duì)齊方式。
flex-direction 屬性
通過(guò)設(shè)置坐標(biāo)軸伍掀,來(lái)設(shè)置項(xiàng)目排列方向偎快。
.container{
flex-direction: row(默認(rèn)值) | row-reverse | column | column-reverse
}
row(默認(rèn)值):主軸橫向囊咏,方向?yàn)閺淖笾赶蛴抑瓴琛m?xiàng)目沿主軸排列来涨,從左到右排列。
row-reverse:row的反方向启盛。主軸橫向蹦掐,方向?yàn)閺挠抑赶蜃蠹几帷m?xiàng)目沿主軸排列,從右到左排列卧抗。
column:主軸縱向藤滥,方向從上指向下。項(xiàng)目沿主軸排列社裆,從上到下排列拙绊。
column-reverse:column的反方向。主軸縱向浦马,方向從下指向上时呀。項(xiàng)目沿主軸排列,從下到上排列晶默。
flex-wrap 屬性
設(shè)置是否允許項(xiàng)目多行排列,以及多行排列時(shí)換行的方向航攒。
.container{
flex-wrap: nowrap(默認(rèn)值) | wrap | wrap-reverse
}
nowrap(默認(rèn)值):不換行磺陡。如果單行內(nèi)容過(guò)多,則溢出容器漠畜。
wrap:容器單行容不下所有項(xiàng)目時(shí)币他,換行排列。
wrap-reverse:容器單行容不下所有項(xiàng)目時(shí)憔狞,換行排列蝴悉。換行方向?yàn)閣rap時(shí)的反方向。
justify-content 屬性
設(shè)置項(xiàng)目在主軸方向上對(duì)齊方式瘾敢,以及分配項(xiàng)目之間及其周?chē)嘤嗟目臻g拍冠。
.container{
justify-content: flex-start(默認(rèn)值) | flex-end | center | space-between | space-around| space-evenly
}
flex-start(默認(rèn)值):項(xiàng)目對(duì)齊主軸起點(diǎn),項(xiàng)目間不留空隙簇抵。
center:項(xiàng)目在主軸上居中排列庆杜,項(xiàng)目間不留空隙。主軸上第一個(gè)項(xiàng)目離主軸起點(diǎn)距離等于最后一個(gè)項(xiàng)目離主軸終點(diǎn)距離碟摆。
flex-end:項(xiàng)目對(duì)齊主軸終點(diǎn)晃财,項(xiàng)目間不留空隙。
space-between:項(xiàng)目間間距相等典蜕,第一個(gè)項(xiàng)目離主軸起點(diǎn)和最后一個(gè)項(xiàng)目離主軸終點(diǎn)距離為0断盛。
space-around:與space-between相似。不同點(diǎn)為愉舔,第一個(gè)項(xiàng)目離主軸起點(diǎn)和最后一個(gè)項(xiàng)目離主軸終點(diǎn)距離為中間項(xiàng)目間間距的一半钢猛。
space-evenly:項(xiàng)目間間距、第一個(gè)項(xiàng)目離主軸起點(diǎn)和最后一個(gè)項(xiàng)目離主軸終點(diǎn)距離等于項(xiàng)目間間距屑宠。
align-items 屬性
設(shè)置項(xiàng)目在行中的對(duì)齊方式厢洞。
.container{
align-items:stretch(默認(rèn)值) | flex-start | center | flex-end | baseline
}
stretch(默認(rèn)值):項(xiàng)目拉伸至填滿行高。
flex-start:項(xiàng)目頂部與行起點(diǎn)對(duì)齊。
center:項(xiàng)目在行中居中對(duì)齊躺翻。
flex-end:項(xiàng)目底部與行終點(diǎn)對(duì)齊丧叽。
baseline:項(xiàng)目的第一行文字的基線對(duì)齊。公你。
align-content 屬性
多行排列時(shí)踊淳,設(shè)置行在交叉軸方向上的對(duì)齊方式,以及分配行之間及其周?chē)嘤嗟目臻g陕靠。
.container{
align-content: stretch(默認(rèn)值) | flex-start | center | flex-end | space-between |space-around | space-evenly
}
stretch(默認(rèn)值):當(dāng)未設(shè)置項(xiàng)目尺寸迂尝,將各行中的項(xiàng)目拉伸至填滿交叉軸。當(dāng)設(shè)置了項(xiàng)目尺寸剪芥,項(xiàng)目尺寸不變垄开,項(xiàng)目行拉伸至填滿交叉軸。
flex-start:首行在交叉軸起點(diǎn)開(kāi)始排列税肪,行間不留間距溉躲。
center:行在交叉軸中點(diǎn)排列,行間不留間距益兄,首行離交叉軸起點(diǎn)和尾行離交叉軸終點(diǎn)距離相等锻梳。
flex-end:尾行在交叉軸終點(diǎn)開(kāi)始排列,行間不留間距净捅。
space-between:行與行間距相等疑枯,首行離交叉軸起點(diǎn)和尾行離交叉軸終點(diǎn)距離為0。
space-around:行與行間距相等蛔六,首行離交叉軸起點(diǎn)和尾行離交叉軸終點(diǎn)距離為行與行間間距的一半荆永。
space-evenly:行間間距、以及首行離交叉軸起點(diǎn)和尾行離交叉軸終點(diǎn)距離相等古今。
4.2.3 項(xiàng)目屬性
設(shè)置項(xiàng)目屁魏,用于設(shè)置項(xiàng)目的尺寸、位置捉腥,以及對(duì)項(xiàng)目的對(duì)齊方式做特殊設(shè)置氓拼。
order 屬性
設(shè)置項(xiàng)目沿主軸方向上的排列順序,數(shù)值越小抵碟,排列越靠前桃漾。屬性值為整數(shù)。
.item{
order: 0(默認(rèn)值) | <integer>
}
?
flex-shrink 屬性
當(dāng)項(xiàng)目在主軸方向上溢出時(shí)拟逮,通過(guò)設(shè)置項(xiàng)目收縮因子來(lái)壓縮項(xiàng)目適應(yīng)容器撬统。屬性值為項(xiàng)目的收縮因子,屬性值取非負(fù)數(shù)敦迄。
.item{
flex-shrink: 1(默認(rèn)值) | <number>
}
.item1{
width: 120px;
flex-shrink: 2;
}
.item2{
width: 150px;
flex-shrink: 3;
}
.item3{// 項(xiàng)目3未設(shè)置flex-shrink恋追,默認(rèn)flex-shrink值為1
width: 180px;
}
為了加深理解凭迹,我們舉個(gè)例子:
一個(gè)寬度為400px的容器,里面的三個(gè)項(xiàng)目width分別為120px苦囱,150px嗅绸,180px。分別對(duì)這項(xiàng)目1和項(xiàng)目2設(shè)置flex-shrink值為2和3撕彤。
.container{
display: flex;
width: 400px; // 容器寬度為400px
}
在這個(gè)例子中鱼鸠,項(xiàng)目溢出 400 - (120 + 150 + 180) = -50px。計(jì)算壓縮量時(shí)總權(quán)重為各個(gè)項(xiàng)目的寬度乘以flex-shrink的總和羹铅,這個(gè)例子壓縮總權(quán)重為120 * 2 + 150 * 3+ 180 * 1 = 870蚀狰。各個(gè)項(xiàng)目壓縮空間大小為總溢出空間乘以項(xiàng)目寬度乘以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
其中計(jì)算時(shí)候值如果為小數(shù),則向下取整职员。
?
需要注意一點(diǎn)麻蹋,當(dāng)項(xiàng)目的壓縮因子相加小于1時(shí),參與計(jì)算的溢出空間不等于完整的溢出空間焊切。在上面例子的基礎(chǔ)上哥蔚,我們改變各個(gè)項(xiàng)目的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蛛蒙。參與計(jì)算的溢出空間不再是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)項(xiàng)目在主軸方向上還有剩余空間時(shí)渤愁,通過(guò)設(shè)置項(xiàng)目擴(kuò)張因子進(jìn)行剩余空間的分配牵祟。屬性值為項(xiàng)目的擴(kuò)張因子,屬性值取非負(fù)數(shù)抖格。
.item{
flex-grow: 0(默認(rèn)值) | <number>
}
為了加深理解诺苹,我們舉個(gè)例子:
一個(gè)寬度為400px的容器,里面的三個(gè)項(xiàng)目width分別為80px雹拄,120px收奔,140px。分別對(duì)這項(xiàng)目1和項(xiàng)目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{// 項(xiàng)目3未設(shè)置flex-grow坪哄,默認(rèn)flex-grow值為0
width: 140px;
}
在這個(gè)例子中,容器的剩余空間為 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
?
需要注意一點(diǎn)翩肌,當(dāng)項(xiàng)目的擴(kuò)張因子相加小于1時(shí),剩余空間按除以1進(jìn)行分配禁悠。在上面例子的基礎(chǔ)上念祭,我們改變各個(gè)項(xiàng)目的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;
}
在這個(gè)例子中碍侦,容器的剩余空間為 400 - (50 + 80 + 110) = 160px粱坤。由于項(xiàng)目的flex-grow相加0.1 + 0.3 + 0.2 = 0.6小于1隶糕,剩余空間按 160 / 1 = 160px劃分。例子中的項(xiàng)目寬度分別為:
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時(shí)站玄,flex-basis和width同時(shí)存在枚驻,flex-basis優(yōu)先級(jí)高于width,也就是此時(shí)flex-basis代替項(xiàng)目的width屬性蜒什。
當(dāng)容器設(shè)置flex-direction為column或column-reverse時(shí)测秸,flex-basis和height同時(shí)存在,flex-basis優(yōu)先級(jí)高于height灾常,也就是此時(shí)flex-basis代替項(xiàng)目的height屬性霎冯。
需要注意的是,當(dāng)flex-basis和width(或height)钞瀑,其中一個(gè)屬性值為auto時(shí)沈撞,非auto的優(yōu)先級(jí)更高。
.item{
flex-basis: auto(默認(rèn)值) | <number>px
}
flex 屬性
是flex-grow雕什,flex-shrink缠俺,flex-basis的簡(jiǎn)寫(xiě)方式。值設(shè)置為none贷岸,等價(jià)于00 auto壹士。值設(shè)置為auto,等價(jià)于1 1 auto偿警。
.item{
flex: none | auto | @flex-grow @flex-shrink@flex-basis
}
align-self 屬性
設(shè)置項(xiàng)目在行中交叉軸方向上的對(duì)齊方式躏救,用于覆蓋容器的align-items,這么做可以對(duì)項(xiàng)目的對(duì)齊方式做特殊處理螟蒸。默認(rèn)屬性值為auto盒使,繼承容器的align-items值,當(dāng)容器沒(méi)有設(shè)置align-items時(shí)七嫌,屬性值為stretch少办。
.item{
align-self: auto(默認(rèn)值) | flex-start | center | flex-end | baseline |stretch
}
?