起源
2009年,W3C 提出了一種新的方案----Flex 布局,F(xiàn)lex 是 Flexible Box 的縮寫(xiě),意為"彈性布局",用來(lái)為盒狀模型提供最大的靈活性。目前,它已經(jīng)得到了所有瀏覽器的支持,這意味著,現(xiàn)在就能很安全地使用這項(xiàng)功能。
基本概念
采用 Flex 布局的元素,稱(chēng)為 Flex 容器(flex container)。它的所有子元素自動(dòng)成為容器成員,稱(chēng)為 Flex 項(xiàng)目(flex item)。容器默認(rèn)存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開(kāi)始位置(與邊框的交叉點(diǎn))叫做 main start,結(jié)束位置叫做 main end;交叉軸的開(kāi)始位置叫做 cross start,結(jié)束位置叫做 cross end。項(xiàng)目默認(rèn)沿主軸排列。單個(gè)項(xiàng)目占據(jù)的主軸空間叫做 main size,占據(jù)的交叉軸空間叫做 cross size
命名方式
屬性命名為駝峰式的。正確:flexDirection。錯(cuò)誤:flex-direction。
容器的屬性(flexDirection,flexWrap,justifyContent,alignItems)
- flexDirection 屬性決定主軸的方向(即項(xiàng)目的排列方向)。
- row:從左向右依次排列。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
},
red: {
backgroundColor: 'red',
height: 60,
width: 60,
margin: 5,
},
yellow: {
backgroundColor: 'yellow',
height: 60,
width: 60,
margin: 5,
},
blue: {
backgroundColor: 'blue',
height: 60,
width: 60,
margin: 5,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
- row-reverse:從右向左依次排列。
- column:默認(rèn)的排列方式,從上向下排列。
- column-reverse:從下向上排列。
- flexWrap 屬性定義了如果一條軸線排不下,如何換行。
- nowrap(默認(rèn)):元素只排列在一行上,可能導(dǎo)致溢出。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
},
red: {
backgroundColor: 'red',
height: 60,
width: 60,
margin: 5,
},
yellow: {
backgroundColor: 'yellow',
height: 60,
width: 60,
margin: 5,
},
blue: {
backgroundColor: 'blue',
height: 60,
width: 60,
margin: 5,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
- wrap:元素在一行排列不下時(shí),就進(jìn)行多行排列。
- wrap-reverse:多行排列,對(duì) wrap 做一個(gè)反轉(zhuǎn)。
RN 0.56 版本之后支持,目前 0.45.1 版本不支持此布局方式。
- justifyContent 屬性定義了項(xiàng)目在主軸上的對(duì)齊方式。
- flex-start(默認(rèn)值):與主軸起點(diǎn)對(duì)齊。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start'
},
red: {
backgroundColor: 'red',
height: 60,
width: 100,
},
yellow: {
backgroundColor: 'yellow',
height: 60,
width: 60,
},
blue: {
backgroundColor: 'blue',
height: 60,
width: 150,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
- flex-end:與主軸終點(diǎn)對(duì)齊。
- center: 主軸居中對(duì)齊。
- space-between:兩端對(duì)齊,項(xiàng)目之間的間隔都相等。
- space-around:每個(gè)項(xiàng)目?jī)蓚?cè)的間隔相等。項(xiàng)目之間的間隔比項(xiàng)目與邊框的間隔大一倍。
- alignItems 屬性定義項(xiàng)目在交叉軸上如何對(duì)齊。
- stretch(默認(rèn)值):如果項(xiàng)目未設(shè)置高度或設(shè)為 auto,將占滿整個(gè)容器的高度。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'stretch',
},
red: {
backgroundColor: 'red',
height: 'auto',
width: 60,
},
yellow: {
backgroundColor: 'yellow',
height: 'auto',
width: 60,
},
blue: {
backgroundColor: 'blue',
height: 'auto',
width: 60,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
height 給了高度之后,更改 alignItems 屬性值的效果。
- flex-start:元素向交叉軸起點(diǎn)對(duì)齊。
- flex-end:元素向交叉軸終點(diǎn)對(duì)齊。
- center:元素在交叉軸居中。如果元素在交叉軸上的高度高于其容器,那么在兩個(gè)方向上溢出距離相同。
- baseline: 項(xiàng)目的第一行文字的基線對(duì)齊。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
},
red: {
backgroundColor: 'red',
height: 150,
width: 60,
},
yellow: {
backgroundColor: 'yellow',
height: 100,
width: 60,
},
blue: {
backgroundColor: 'blue',
height: 60,
width: 60,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}>
<Text style={{ color: 'black', fontSize: 20 }}>里奧</Text>
</View>
<View style={ScreenStyle.yellow}>
<Text style={{ color: 'black', fontSize: 16 }}>梅西</Text>
</View>
<View style={ScreenStyle.blue}>
<Text style={{ color: 'black', fontSize: 25 }}>涼涼</Text>
</View>
</View>
);
}
- flex 屬性決定其占據(jù)父容器的比例。React Native 中 flex 只能是數(shù)字。如果是正整數(shù),就是與數(shù)字的大小成比例。如果為 0 就是自生的大小,并且不能擴(kuò)展。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
},
red: {
backgroundColor: 'red',
flex: 1,
},
yellow: {
backgroundColor: 'yellow',
flex: 2,
},
blue: {
backgroundColor: 'blue',
flex: 3,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
CSS 中 Flex 布局的內(nèi)容在 React Native 中簡(jiǎn)化了一些,flex-flow(屬性是 flexDirection 屬性和 flexWrap 屬性的簡(jiǎn)寫(xiě)形式,默認(rèn)值為 row nowrap)和 align-content(屬性定義了多根軸線的對(duì)齊方式。如果項(xiàng)目只有一根軸線,該屬性不起作用)屬性在 React Native 中沒(méi)有。
項(xiàng)目屬性(flexGrow,flexShrink,flexBasis,alignSelf)
- flexGrow 屬性定義項(xiàng)目的放大比例,默認(rèn)為 0,即如果存在剩余空間,也不放大。
如果所有項(xiàng)目的 flexGrow 屬性都為 1,則它們將等分剩余空間(如果有的話)。如果一個(gè)項(xiàng)目的 flexGrow 屬性為 2,其他項(xiàng)目都為 1,則前者占據(jù)的剩余空間將比其他項(xiàng)多一倍。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
},
red: {
backgroundColor: 'red',
width: 80,
height: 80,
flexGrow: 5,
},
yellow: {
backgroundColor: 'yellow',
width: 100,
height: 100,
flexGrow: 2,
},
blue: {
backgroundColor: 'blue',
width: 60,
height: 60,
flexGrow: 3,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
將 flexDirection 改成 column
- flexShrink 屬性定義了項(xiàng)目的縮小比例,默認(rèn)為 1,即如果空間不足,該項(xiàng)目將縮小。
如果所有項(xiàng)目的 flexShrink 屬性都為 1,當(dāng)空間不足時(shí),都將等比例縮小。如果一個(gè)項(xiàng)目的 flexShrink 屬性為 0,其他項(xiàng)目都為 1,則空間不足時(shí),前者不縮小。
負(fù)值對(duì)該屬性無(wú)效。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
},
red: {
backgroundColor: 'red',
height: 150,
width: 500,
flexShrink: 1,
},
yellow: {
backgroundColor: 'yellow',
height: 100,
width: 200,
flexShrink: 1,
},
blue: {
backgroundColor: 'blue',
height: 60,
width: 300,
flexShrink: 0,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
- flexBasis 屬性定義了在分配多余空間之前,項(xiàng)目占據(jù)的主軸空間(main size)。瀏覽器根據(jù)這個(gè)屬性,計(jì)算主軸是否有多余空間。它的默認(rèn)值為 auto,即項(xiàng)目的本來(lái)大小。
它可以設(shè)為跟 width 或 height 屬性一樣的值(比如350px),則項(xiàng)目將占據(jù)固定空間。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
},
red: {
backgroundColor: 'red',
height: 150,
width: 500,
flexBasis: 50,
},
yellow: {
backgroundColor: 'yellow',
height: 100,
width: 200,
flexBasis: 100,
},
blue: {
backgroundColor: 'blue',
height: 60,
width: 300,
flexBasis: 30,
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
- alignSelf 屬性允許單個(gè)項(xiàng)目有與其他項(xiàng)目不一樣的對(duì)齊方式,可覆蓋 alignItems 屬性。
- auto: 按照自身設(shè)置的寬高來(lái)顯示,如果沒(méi)設(shè)置,效果跟 stretch 一樣。
- flex-start: 與父容器頂部對(duì)齊。
- flex-end: 與父容器底部對(duì)齊。
- center: 位于中間位置。
- stretch: 交叉軸拉伸,不設(shè)置具體的 width/height 的時(shí)候 stretch 才有效果。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'flex-start',
},
red: {
backgroundColor: 'red',
// height: 100,
width: 100,
alignSelf: 'stretch',
},
yellow: {
backgroundColor: 'yellow',
// height: 100,
width: 100,
alignSelf: 'stretch',
},
blue: {
backgroundColor: 'blue',
// height: 100,
width: 100,
alignSelf: 'stretch',
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}></View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
- baseline: 項(xiàng)目的第一行文字的基線對(duì)齊。
const styles = {
container: {
backgroundColor: '#f0f0f0',
flex: 1,
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'flex-start',
alignItems: 'flex-start',
},
red: {
backgroundColor: 'red',
height: 50,
width: 100,
alignSelf: 'baseline',
},
yellow: {
backgroundColor: 'yellow',
height: 100,
width: 100,
alignSelf: 'baseline',
},
blue: {
backgroundColor: 'blue',
height: 180,
width: 100,
alignSelf: 'baseline',
},
};
render() {
return (
<View style={ScreenStyle.container}>
<View style={ScreenStyle.red}>
<Text style={{ color: 'black', fontSize: 25 }}>世界杯</Text>
</View>
<View style={ScreenStyle.yellow}></View>
<View style={ScreenStyle.blue}></View>
</View>
);
}
Web CSS 不同之處
- flexDirection: React Native 中默認(rèn)為 flexDirection:'column',在 Web CSS 中默認(rèn)為 flex-direction:'row'
- alignItems: React Native 中默認(rèn)為 alignItems:'stretch',在 Web CSS 中默認(rèn) align-items:'flex-start'
- flex: 相比 Web CSS 的 flex 接受多參數(shù),如:flex: 2 2 10%;,但在 React Native 中 flex 只接受一個(gè)參數(shù)
- 不支持屬性:align-content,order,flex-flow
其他布局屬性
- 視圖邊框
- borderBottomWidth number 底部邊框?qū)挾?/li>
- borderLeftWidth number 左邊框?qū)挾?/li>
- borderRightWidth number 右邊框?qū)挾?/li>
- borderTopWidth number 頂部邊框?qū)挾?/li>
- borderWidth number 邊框?qū)挾?/li>
- border<Bottom|Left|Right|Top>Color 個(gè)方向邊框的顏色
- borderColor 邊框顏色
- 尺寸
- width number
- height number
- 外邊距
- margin number 外邊距
- marginBottom number 下外邊距
- marginHorizontal number 左右外邊距
- marginLeft number 左外邊距
- marginRight number 右外邊距
- marginTop number 上外邊距
- marginVertical number 上下外邊距
- 內(nèi)邊距
- padding number 內(nèi)邊距
- paddingBottom number 下內(nèi)邊距
- paddingHorizontal number 左右內(nèi)邊距
- paddingLeft number 做內(nèi)邊距
- paddingRight number 右內(nèi)邊距
- paddingTop number 上內(nèi)邊距
- paddingVertical number 上下內(nèi)邊距
- 邊緣
- left number 屬性規(guī)定元素的左邊緣。該屬性定義了定位元素左外邊距邊界與其包含塊左邊界之間的偏移。
- right number 屬性規(guī)定元素的右邊緣。該屬性定義了定位元素右外邊距邊界與其包含塊右邊界之間的偏移
- top number 屬性規(guī)定元素的頂部邊緣。該屬性定義了一個(gè)定位元素的上外邊距邊界與其包含塊上邊界之間的偏移。
- bottom number 屬性規(guī)定元素的底部邊緣。該屬性定義了一個(gè)定位元素的下外邊距邊界與其包含塊下邊界之間的偏移。
-
定位(position)
position enum('absolute', 'relative')屬性設(shè)置元素的定位方式,為將要定位的元素定義定位規(guī)則。
- absolute:生成絕對(duì)定位的元素,元素的位置通過(guò) "left", "top", "right" 以及 "bottom" 屬性進(jìn)行規(guī)定。
- relative:生成相對(duì)定位的元素,相對(duì)于其正常位置進(jìn)行定位。因此,"left:20" 會(huì)向元素的 LEFT 位置添加 20 像素。