flex深度剖析-解决移动端适配问题!

前言

上回说到,移动端适配,推荐了,使用px为主,vw,百分比为辅助,再搭配flex的布局方式,因而有人就开始问我了,这个flex搭配布局应该怎么用,梳理一遍,巩固一下css

flex前世此生

在前端刚刚兴起html,css,js,还停留在初级阶段是的时候,前端工程化还不存在的时候,jqery还在统治江湖的时候,以及这张图还在大火的时候,额!我又盗图了html

我么们想要实现两个div一排显示除了行内块元素之外,只能用这让人又爱又恨的float前端

float

float 属性定义元素在哪一个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素均可以浮动。浮动元素会生成一个块级框,而不论它自己是何种元素。 web

其实float的设计初衷仅仅是为了实现:文字环绕效果,只不事后来在前端的迅速发展中,float被尝试用来了布局,因而,后来flaot就约定熟成的变成一种布局属性,虽然很好用,可是,既然设计初衷不是为了布局,那么强行安上一个布局的帽子,固然会有好多反作用!面试

反作用

一、当子元素都设置了浮动时,就会致使父元素的塌陷,即父元素撑不开,以下图所示:

二、没法实现动态实现自适应布局,

举个例子,若是想要实现二等分一排布局,width要为50%,可是若是忽然来个三等分呢,width设置50%显然是已经不行了前端工程化

三、margin padding设置值不能正确显示

因为浮动致使父级子级之间设置了css padding、css margin属性的值不能正确表达。特别是上下边的padding和margin不能正确显示。浏览器

四、若是前面的元素设置了浮动,那后面的元素就有可能产生异位的现象。

如图所示,因为元素1浮动了,脱离文档流,致使元素2上去了安全

这些问题让众多开发这至关苦恼,尤为是在相对复杂的项目,各类float会搞得页面至关复杂(特别是移动端),出现很差解决的诡异bug,稍微欠点火候的web开发者,有可能被搞得晕头转向。bash

然后随着移动互联网兴起,移动端的h5页面铺天盖地,布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对移动端布局很是不方便(引用阮老师),因而flex横空出世,终于,这个万能的float终于要退出历史舞台了!markdown

flex初探

2009年,W3C 提出了一种新的方案----Flex(弹性盒模型) 布局,能够简便、完整、响应式地实现各类页面布局。目前,它已经获得了全部浏览器的支持,这意味着,如今就能很安全地使用这项功能。

在2020的今天,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

一、flex-direction属性

flex-direction属性决定主轴的方向(即项目的排列方向)。

.box {
  flex-direction: row | row-reverse | column | column-reverse;
}
//依次表示主轴为水平方向,起点在左端。(默认)
//主轴为水平方向,起点在右端。
//主轴为垂直方向,起点在上沿。
//主轴为垂直方向,起点在下沿。
复制代码

二、flex-wrap属性

默认状况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,若是一条轴线排不下,如何换行。

.box{
  flex-wrap: nowrap | wrap | wrap-reverse;
  //依次是不换行
  //换行,第一行在上方。
  //换行,第一行在下方。
}
复制代码

三、flex-flow属性

flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。

.box {
  flex-flow: <flex-direction> || <flex-wrap>;
}
复制代码

四、justify-content属性(这个很重要,常常用)

justify-content属性定义了项目在主轴上的对齐方式。

.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
  //依次是左对齐(默认值)
  //右对齐
  //居中
  //两端对齐,项目之间的间隔都相等。
  //每一个项目两侧的间隔相等。因此,项目之间的间隔比项目与边框的间隔大一倍。
}
复制代码

五、align-items属性(这个也很重要。也经常使用)

align-items属性定义项目在交叉轴上如何对齐。

.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
  //依次是交叉轴的起点对齐。
  //交叉轴的终点对齐。
  //交叉轴的中点对齐。
  //项目的第一行文字的基线对齐。
  //若是项目未设置高度或设为auto,将占满整个容器的高度(默认值)
}
复制代码

六、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

一、order属性

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

.item {
  order: <integer>;
}
复制代码

二、flex-grow属性(很重要)

flex-grow属性定义项目的放大比例,默认为0,即若是存在剩余空间,也不放大。

若是全部项目的flex-grow属性都为1,则它们将等分剩余空间(若是有的话)。若是一个项目的flex-grow属性为2,其余项目都为1,则前者占据的剩余空间将比其余项多一倍。

.item {
  flex-grow: <number>; /* default 0 */
}
复制代码

三、flex-shrink属性

flex-shrink属性定义了项目的缩小比例,默认为1,即若是空间不足,该项目将缩小。

若是全部项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。若是一个项目的flex-shrink属性为0,其余项目都为1,则空间不足时,前者不缩小。

注意:负值对该属性无效。

.item {
  flex-shrink: <number>; /* default 1 */
}
复制代码

四、flex-basis属性(这个是重点,经常使用)

flex-basis属性定义了在分配多余空间以前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的原本大小。

它能够设为跟width或height属性同样的值(好比350px),则项目将占据固定空间。

五、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,阮大佬的文章算是抄完了(阮大佬的文章实在太好了,一激动就没有本身写,感谢大佬)

实战

基础的东西咱是抄完了,怎么也得有点本身的东西啊,废话少说,实战开始

一、经常使用的flex 1究竟是啥意思?

上文说到。flex 是 flex-grow、flex-shrink、flex-basis的缩写,那咋晕的忽的由来个1呢,其实他又以下规则(mdn上的至关难记请看这里大佬们整理好的):

一、当 flex 取值为 none,则计算值为 0 0 auto

//此处为预处理语法
div{
diaplay:flex
 .div {
    flex-grow: 0;
    flex-shrink: 0;
    flex-basis: auto;
}   
}

复制代码

二、当 flex 取值为 auto,则计算值为 1 1 auto

//此处为预处理语法
div{
diaplay:flex
 .div {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: auto;
}   
}

复制代码

三、当 flex 取值为一个非负数字,则 flex-grow 数字,flex-shrink 取 1,flex-basis 取 0%(最经常使用)

//此处为预处理语法
div{
diaplay:flex
 .div {
    flex-grow: 1;//要取的值
    flex-shrink: 1;//默认
    flex-basis: 0%;//默认
}   
}

复制代码

四、当 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>
复制代码

有了以上三种基础款,咱们即可以扩展出各类布局

一、常见搜索框

//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>
复制代码

二、自适应导航栏布局

//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>
复制代码

三、常见的左图右文的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,便可,可是具体为啥,如今也没有在官方文档里面找到(有知道的大佬,请告知)

四、栅格布局

这个布局有点小小的瑕疵,会有除不尽的状况,可是无伤大雅,

//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>
复制代码

五、底部固定,上部自适应

有人就会说了这个用定位来解决不久完事了,多一个选择啊,对吧?也许就是这个选择让你惊艳面试官

//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>
复制代码

六、圣杯布局,双飞翼布局

这种布局,其实就是两层的flex 在第一层布局用了 flex-direction: column;而已,不在赘述

总结

乘着上期的文章还有热乎劲头,再来总结一些flex布局,夯实我推荐的移动端适配的写法 基础部分,借鉴阮一峰大佬:www.ruanyifeng.com/blog/2015/0…

做为一个曾被移动端困扰的人,痛定思痛总结如上:愿你们之后不被移动端布局困扰。

上期移动端适配:面试官:你了解过移动端适配吗?

相关文章
相关标签/搜索