Flexbox 布局 与 常见布局需求实现对比

Flexbox 布局是 CSS 3 新增的布局模式,在 display 中的值是 display: flex; display: inline-flex;。flex 具有很好的适应性,在电脑浏览器和手机浏览器中都有很好的表现。虽然其标准仍然是“候选(CR)”,但是在各个浏览器已经得到了很广泛的支持。如图1,从图中我们可以看出,flex模块已经得到了几乎所有浏览器的支持,IE11部分支持,我们可以在实际的项目中尝试使用,如果是IE Version<=11的话,要做一定的 polyfill。

flex浏览器支持程度

what for?

flexbox,是’flexible box’ 的缩写,声明为display: flex/inline-box 的元素可以改变子元素的高度和/或宽度,来适应不同大小的浏览器尺寸和显示设备类型,是响应式布局的一种技术。利用块级元素布局基于垂直方向,行内元素基于水平方向,flexbox 则是水平和垂直方向都能很好的适应。关于 Flexbox ,我觉得记住一点就好,声明 display: flex;或者 display: inline-flex;的元素的子 flex 条目会充满父元素的所有空间。

没有 flexbox 时,使用 css 布局时,我们使用 float 、display 和 position,这些技术没有问题,但是实现不是很直观。但是利用这些技术,且对于一些特殊任务实现起来仍然有困难,比如 垂直居中元素。flex 实现这些布局是相当容易的事情,我们可以总结说,Flexbox 就是一种“弹性布局”模型,能很好支持不同视口尺寸和设备。

看完整篇文章后,你会觉得这个和 table 布局十分类似啊!下面说点具体的 【严肃脸】。

内容

说明: 主轴为 flex-direction 指定的方向,侧轴是与主轴方向垂直的轴,借用 MDN 上的一张图说明。main axis 即为主轴,主轴方向开始叫做‘main start’,结束叫做‘main end’;cross axis 为侧轴,开始为 cross start,结束为 cross end。在这里指出这些知识,是因为以下的 flex 的条目对其将会涉及到相应的概念。

MDN轴方向说明图

容器可以设置的属性:

属性值及其说明
flex-direction条目放置的方向(主坐标轴),row(默认值),水平放置;column,垂直放置
flex-wrapflex条目溢出父元素时是否应该换行,nowrap(默认值),不换行显示;wrap表示换行,按照父元素的尺寸来布局,如果溢出,那么溢出的将换行显示,最终结果为显示为多行,且无论哪一行,有几个子元素,都会自适应填充满每一行;wrap-reverse,与wrap相同,但是顺序相反
flex-flowflex-direction和flex-wrap的简写,和margin、padding等简写四个方向类似
justify-content规定flex条目在主轴方向的排布规则。flex-start,条目左对齐,最左边的元素的margin边框将会失效;flex-end,条目右对齐,最右边的元素的margin边框将会失效;center,居中对齐;space-between,沿主轴方向均匀分布,开始和结束margins失效;space-around,沿主轴均匀分布,与space-between不同之处在于开始和结束的margins等于相邻两个flex条目间距的一半
align-item规定flex条目在侧轴(flex-direction规定的主轴垂直方向)方向的排布规则。flex-start,垂直上对齐;flex-end,垂直下对齐;center,垂直居中对齐;baseline,stretch(默认值),在侧轴方向拉伸flex条目,以期在侧轴方向填满整个容器


条目可以设置的属性:

属性值及其说明
flex-grow主轴方向flex条目所占比例,值为Number类型
flex-shrink主轴方向flex条目缩放比例,值为Number类型
flex-basis主轴方向flex条目最小尺寸,px或者%
flex是 flex-grow、flex-shrink 和 flex-basis 属性的简写,确立弹性项目的伸缩性
orderflex条目在所有flex条目中的次序
align-self同父元素的align-item,定义了单个弹性项目在侧轴上应当如何对齐,这个定义将覆盖由 align-items 所确立的默认值

看完这些说明,我们来看看如何利用 Flexbox 实现我们常用的布局。

各种常见布局要求的 Flexbox 实现

水平方向多列自适应布局

要求:两列布局,左侧列宽度固定,右侧列自适应,填充整个容器。
  1. 传统做法:浮动定位或绝对定位左侧列,右侧列margin实现与左侧列隔离。
  <section>

     <article class="left">
       <b>left width-fixed</b>
     </article>

     <article class="right">
       <b>right auto-fill</b>
     </article>

   </section>

样式:

   html, body{
     height: 100%;
     margin: 0;
     padding: 0;
   }
   section, article{
     height: 100%;
   }
   .left{
     float: left;
     width: 300px;
     background-color: rgb(255, 0, 0);
   }
   .right{
     margin-left: 300px;
     background-color: rgb(0, 255, 0);
   }

效果如下:

自适应-窄

自适应-宽

==========附带一提(但是很重要的点)============

外边距(margin)叠加问题,简单的说,就是当两个或更多的垂直外边距相遇时,它们将形成一个外边距,这两个外边距的高度等于两个发生叠加的外边距的高度中的较大者。比如,我在上面的例子中,每一个 article 内的标题都是使用 b 标签,如果我换成 h* 标签,那么就会出现这个问题。如图,我将b 标签换成了 h2,h2 是块级元素,有垂直外边距,在chorme 中,本例的 h2 默认外边距是 19.920 像素,外边距为0的父元素叠加外边距为 19.920 像素的子元素,将会出现 19.920 像素的垂直外边距:

外边距叠加

需要注意,如果父元素是float 定位,那么该问题不会出现,所以你会看到左侧 article 中的 h2 元素外边距在 article 元素中。

  1. 使用 Flexbox 实现

同样是上面的 HTML 结构,样式如下。

      html, body{
        height: 100%;
        margin: 0;
        padding: 0;
      }
      section, article{
        height: 100%;
      }
      section{
        display: flex;
      }
      .left{
        width: 300px;
        background-color: rgb(2,138,201);
      }
      .right{
        flex-grow: 1;
        background-color: rgb(78,55,115);
      }

效果如下图,这下好了,h* 的外边距都在里边了,没有出现外边距叠加了,可见,article元素已经不是普通的定位了。但是要注意,article 高度必须大于 h2 的盒模型总的高度,否则仍然会溢出。

Flexbox实现

垂直方向多行自适应布局

要求:三行布局,第一行和第三行高度固定,第二行自适应,填充整个容器。
  1. 传统做法,使用 table 布局。
    <section>

      <header>
        <h2>header</h2>
      </header>

      <article class="content">
        <h2>content</h2>
      </article>

      <footer>
        <h2>footer</h2>
      </footer>

    </section>

样式:

   html, body{
     height: 100%;
     margin: 0;
     padding: 0;
   }
   section{
     height: 100%;
     width: 100%;
     display: table;
   }
   .content{
     display: table-row;
     background-color: rgb(2,138,201);
   }
   header, footer{
     display: table-row;
     background-color: rgb(72,82,94);
   }
   header{
     height: 90px;
   }
   footer{
     height: 80px;
   }

效果和使用 Flexbox 实现的效果完全一致,这里就不贴图了,可以看 Flexbox 的实现效果图。

  1. Flexbox 实现
   html, body{
     height: 100%;
     margin: 0;
     padding: 0;
   }
   section{
     height: 100%;
     display: flex;
     flex-direction: column;
   }
   .content{
     flex-grow: 1;
     background-color: rgb(2,138,201);
   }
   header, footer{
     background-color: rgb(72,82,94);
   }
   header{
     height: 90px;
   }
   footer{
     height: 80px;
   }

这里写图片描述

这里写图片描述

看完效果是不是感觉很 nice 呢。以后遇到这种布局需求,就是用 Flexbox 吧!结合水平的和垂直的布局,可以做出一些复杂的单页应用布局。

水平居中且垂直居中

使用 Flexbox 做页面居中也很容易,

   <section class="container">
     <div class="spacer"></div>

     <section class="horizontal">
       <div class="spacer"></div>

       <article class="content">
           居中的内容
       </article>

       <div class="spacer"></div>
     </section>

     <div class="spacer"></div>
   </section>

样式:

    html, body{
      height: 100%;
      margin: 0;
      padding: 0;
    }
    .container{
      height: 100%;
      display: flex;
      flex-direction: column;
      background-color: rgba(0, 0, 0, 0.8);
    }
    .spacer{
      flex: 1;
    }
    .horizontal{
      display: flex;
      flex-direction: row;
    }
    .content{
      height: 200px;
      width: 400px;
      background-color: rgb(255, 255, 255);
      color: rgb(0, 0, 0);
      border-radius: 4px;
      padding: 10px;
    }

HTML 中我们使用了四个名为spacer类的垫片,这里主要利用了 flex 条目会占据所有可用空间的特性,让它们把主要的内容挤到中间的位置 ^_^。我给内同区域添加了圆角效果和内边距,最终效果如下图。看到没,就这么简单就做出了一个弹出层,再加上一点鼠标和键盘事件,这不就是一个我们常用的 bootstrap“模态框”么 【笑】。

页面居中的弹出层

有一个叫做绝对居中的技术,我从其他博客作者看到的,内容较多,这里我们不再介绍,找个机会我们和 Flexbox 实现做一个对比。

大屏和小屏之间的响应性

结合 flex-direction , flex-wrap,order 和 媒体查询,做出的布局会有比较好的跨设备的特性。下面举个例子,咱一起看看它们的威力。

  <section>
    <nav>
      <button> 测试 </button>
      <button> 测试 </button>
      <button> 测试</button>
    </nav>

    <article>
      主要内容
    </article>

  </section>

样式:

   html, body{
     height: 100%;
     margin: 0;
     padding: 0;
   }
   section{
     height: 100%;
     display: flex;
   }
   nav{
     width: 200px;
     display: flex;
     background-color: rgb(2,138,201);
   }
   button{
     height: 30px;
     flex: 1;
   }
   article{
     flex: 1;
     background-color: rgb(72,82,94);
   }
   @media screen and (max-width: 640px) {
     section{
       flex-direction: column;
     }
     nav{
       width: 100%;
       flex: 1;
       order: 2;
       flex-direction: row;
     }
     article{
       flex: 3;
     }
   }
   @media screen and (max-width: 320px) {
     nav{
       flex-direction: column;
     }
   }

效果,例子中利用媒体查询,根据浏览器宽度分了三个阶段,当然 640,320都是胡诌的,真实情况下,并不是这个界限,合适的尺寸可以参考 Bootstrap 的分段阈值或者根据实际情况制定。多余的我就不说了,你肯定能看懂。

  • >640px,判断为电脑浏览器;
  • 640px > width >320px,判断为平板浏览器;
  • <320px,判断为手机浏览器。

这里写图片描述

这里写图片描述

这里写图片描述

总结

只要理解了 Flexbox 的设计初衷,并了解其属性和值的含义及用处,那么在实际的需求面前就可以很从容的应用这项技术了。这也是我的学习新东西的思路,首先想为什么有这个东西,为解决什么问题的,有什么 API,然后和其它技术的对比,然后在具体问题面前灵活运用。

转载于:https://my.oschina.net/m2gIGj8g1iU/blog/809915

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值