前言
上回说到,移动端适配,推荐了,使用px为主,vw,百分比为辅助,再搭配flex的布局方式,于是有人就开始问我了,这个flex搭配布局应该怎么用,梳理一遍,巩固一下
flex前世今生
在前端刚刚兴起html,css,js,还停留在初级阶段是的时候,前端工程化还不存在的时候,jqery还在统治江湖的时候,以及这张图还在大火的时候,额!我又盗图了
我么们想要实现两个div一排显示除了行内块元素以外,只能用这让人又爱又恨的float
float
float 属性定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。
其实float的设计初衷仅仅是为了实现:文字环绕效果,只不过后来在前端的迅速发展中,float被尝试用来了布局,于是,后来flaot就约定熟成的变成一种布局属性,虽然很好用,但是,既然设计初衷不是为了布局,那么强行安上一个布局的帽子,当然会有好多副作用!
副作用
1、当子元素都设置了浮动时,就会导致父元素的塌陷,即父元素撑不开,如下图所示:
2、无法实现动态实现自适应布局,
举个例子,如果想要实现二等分一排布局,width要为50%,但是如果突然来个三等分呢,width设置50%显然是已经不行了
3、margin padding设置值不能正确显示
由于浮动导致父级子级之间设置了css padding、css margin属性的值不能正确表达。特别是上下边的padding和margin不能正确显示。
4、如果前面的元素设置了浮动,那后面的元素就有可能产生异位的现象。
如图所示,由于元素1浮动了,脱离文档流,导致元素2上去了
这些问题让众多开发这相当苦恼,尤其是在相对复杂的项目,各种float会搞得页面相当复杂(特别是移动端),出现不好解决的诡异bug,稍微欠点火候的web开发者,有可能被搞得晕头转向。
而后随着移动互联网兴起,移动端的h5页面铺天盖地,布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对移动端布局非常不方便(引用阮老师),于是flex横空出世,终于,这个万能的float终于要退出历史舞台了!
flex初探
2009年,W3C 提出了一种新的方案----Flex(弹性盒模型) 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。
flex到底是个什么东西
引用老罗名言,少废话先看东西,其实就是给容器指定一个display属性为flex
//比如这样以后div就具有弹性了
div{
display:flex;
}
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。
flex有什么属性
flex 的属性,容器上有,项目上同样也有,且听慢慢道来!
flex容器属性
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
1、flex-direction属性
flex-direction属性决定主轴的方向(即项目的排列方向)。
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
//依次表示主轴为水平方向,起点在左端。(默认)
//主轴为水平方向,起点在右端。
//主轴为垂直方向,起点在上沿。
//主轴为垂直方向,起点在下沿。
2、flex-wrap属性
默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
//依次是不换行
//换行,第一行在上方。
//换行,第一行在下方。
}
3、flex-flow属性
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
4、justify-content属性(这个很重要,经常用)
justify-content属性定义了项目在主轴上的对齐方式。
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
//依次是左对齐(默认值)
//右对齐
//居中
//两端对齐,项目之间的间隔都相等。
//每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
}
5、align-items属性(这个也很重要。也常用)
align-items属性定义项目在交叉轴上如何对齐。
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
//依次是交叉轴的起点对齐。
//交叉轴的终点对齐。
//交叉轴的中点对齐。
//项目的第一行文字的基线对齐。
//如果项目未设置高度或设为auto,将占满整个容器的高度(默认值)
}
6、align-content属性
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
//依次是与交叉轴的起点对齐。
//与交叉轴的终点对齐。
//与交叉轴的中点对齐。
//与交叉轴两端对齐,轴线之间的间隔平均分布。
//每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
//轴线占满整个交叉轴。(默认值)
}
项目的属性
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
1、order属性
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
.item {
order: <integer>;
}
2、flex-grow属性(很重要)
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
.item {
flex-grow: <number>; /* default 0 */
}
3、flex-shrink属性
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
注意:负值对该属性无效。
.item {
flex-shrink: <number>; /* default 1 */
}
4、flex-basis属性(这个是重点,常用)
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
5、flex属性(这个最重要)
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
.item {
//该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
//建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
align-self属性
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
//这个其实就是在项目里用align-items 注:auto为默认值
}
ok,阮大佬的文章算是抄完了(阮大佬的文章实在太好了,一激动就没有自己写,感谢大佬)
实战
基础的东西咱是抄完了,怎么也得有点自己的东西啊,废话少说,实战开始
1、常用的flex 1到底是啥意思?
上文说到。flex 是 flex-grow、flex-shrink、flex-basis的缩写,那咋晕的忽的由来个1呢,其实他又如下规则(mdn上的相当难记请看这里大佬们整理好的):
1、当 flex 取值为 none,则计算值为 0 0 auto
//此处为预处理语法
div{
diaplay:flex
.div {
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
}
2、当 flex 取值为 auto,则计算值为 1 1 auto
//此处为预处理语法
div{
diaplay:flex
.div {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
}
3、当 flex 取值为一个非负数字,则 flex-grow 数字,flex-shrink 取 1,flex-basis 取 0%(最常用)
//此处为预处理语法
div{
diaplay:flex
.div {
flex-grow: 1;//要取的值
flex-shrink: 1;//默认
flex-basis: 0%;//默认
}
}
4、当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1
//此处为预处理语法
div{
diaplay:flex
.div {
flex-grow: 1;//默认
flex-shrink: 1;//默认
flex-basis: 0%;//要取得值
}
}
当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%
//此处为预处理语法
div{
diaplay:flex
.div {
flex-grow: 1;//要取的第一个值
flex-shrink: 1;//要取的第二个值
flex-basis: 0%;//默认
}
}
当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1
div{
diaplay:flex
.div {
flex-grow: 1;//要取的第一个值
flex-shrink: 1;//默认
flex-basis: 0%;//要取的第二个值
}
}
如何用flex实现等分布局?
//css
.box{
height: 500px;
display: flex;
}
.box div{
height: 300px;
border: 1px solid #000000;
flex: 1;//这就是flex:1的妙用
text-align: center;
}
//html
div class="box">
<div>等分效果</div>
<div>等分效果</div>
</div>
左边固定右边自适应
//css
.box {
height: 500px;
display: flex;
}
.box div {
height: 300px;
text-align: center;
}
.box div.right {
flex: 1;
border: 1px solid #000000;
}
.box div.left {
border: 1px solid #000000;
flex-basis: 100px;
}
//html
<div class="box">
<div class="left">左边固定效果</div>
<div class="right">右边自适应效果</div>
</div>
垂直水平居中对齐
//css
.box {
width: 100%;
height: 300px;
border: 1px solid purple;
display: flex;
justify-content: center;
align-items: center;
}
//html
<div class="box"><p>看看剧中了吗</p>
</div>
有了以上三种基础款,我们便可以扩展出各种布局
1、常见搜索框
//css
.box {
width: 100%;
height: 50px;
border: 1px solid purple;
display: flex;
}
.input{
flex:1;
border:1px solid #000000
}
.bottom{
flex-basis: 60px;
line-height: 50px;
text-align: center;
font-size: 16px;
}
//html
<div class="box">
<div class="input"></div>
<div class="bottom">搜索</div>
</div>
2、自适应导航栏布局
//css
ul{
display: flex;
height: 50px;
list-style: none;
padding: 0;
}
li{
flex:1;
text-align: center;
}
.active{
border-bottom: 1px solid rebeccapurple;
}
//html
<ul>
<li class="active">好好学习</li>
<li>上学</li>
<li>天天向上</li>
</ul>
3、常见的左图右文的list列表布局
//css
.box {
display: flex;
width: 100%;
height: 150px;
}
.left {
flex-basis: 100px;
background: #000;
color: #ffffff;
}
.right {
flex: 1;
position: relative;
text-align: right;
}
.btn {
border: 1px solid rebeccapurple;
width: 100px;
display: inline-block;
overflow: hidden;
margin-top: 20px;
text-overflow: ellipsis;
white-space: nowrap;
}
//html,
<div class="box">
<div class="left">代表是个图</div>
<div class="right">
<p>这个个大大的标题,</p>
<span>下边的烂七八糟</span>
<div class="btn">搞个按钮让你点点</div>
</div>
</div>
这里面有个坑,如果右边自适应的内容如果超过范围了,那么就会形成如下效果,解决办法也很简单,在这个自适应的地方价格min-width:0,即可,但是具体为啥,现在也没有在官方文档里面找到(有知道的大佬,请告知)
4、栅格布局
这个布局有点小小的瑕疵,会有除不尽的情况,但是无伤大雅,
//css
ul {
width: 100%;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
list-style: none;
padding: 0;
}
li {
flex: 0 0 33.333333%;
height: 80px;
box-sizing: border-box;
border:1px solid #000
}
//html
<ul>
<li>
方框
</li>
<li>
方框
</li>
<li>
方框
</li>
<li>
方框
</li>
<li>
方框
</li>
<li>
方框
</li>
<li>
方框
</li>
</ul>
5、底部固定,上部自适应
有人就会说了这个用定位来解决不久完事了,多一个选择啊,对吧?也许就是这个选择让你惊艳面试官
//css
.box {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
flex: 1;
}
.footer {
flex-basis: 100px;
background: red;
}
//html
<div class="box">
<div class="header">
这是头部,
</div>
<div class="footer">
这是底部
</div>
</div>
6、圣杯布局,双飞翼布局
这种布局,其实就是两层的flex 在第一层布局用了 flex-direction: column;而已,不在赘述
总结
乘着上期的文章还有热乎劲头,再来总结一些flex布局,夯实我推荐的移动端适配的写法 基础部分,借鉴阮一峰大佬:www.ruanyifeng.com/blog/2015/0…
作为一个曾被移动端困扰的人,痛定思痛总结如上:愿大家以后不被移动端布局困扰。
上期移动端适配:面试官:你了解过移动端适配吗?