Flex布局图文详解与示例代码

Flex 布局,即 Flex Box(弹性布局),是一种较为灵活、强大的页面 CSS 布局方式。在深入学习 Flex 布局前,我们需要了解一些 Flex 相关的概念和术语。

Flex 布局的优点:

  • 简便、完整、响应式
  • 浏览器支持良好
  • 传统盒状模型中,难以实现的垂直等布局等 ,Flex布局可以完美解决。

一、基础概念


首先,我们需要了解一下 Flex 布局中的一些概念和术语:

  • flex 容器(flex container)
  • flex 项目(flex item)
  • 主轴(main axis)
  • 交叉轴(cross axis)
  • 占用主轴空间(main size)
  • 占用交叉轴空间(cross size)
  • 线轴起止点(main start、main end、cross start、cross end)

在图1-1 非常清晰的展示了这些概念的相互关系。

图1-1 Flex 容器

1.1 容器与项目

使用 Flex 布局的元素(display: flex),称之为 Flex 容器(Flex Container),简称 "容器"。Flex 的布局发生在父容器和子容器之间,因此,元素一旦被申明为 Flex 布局后,它的所有子元素自动成为容器成员。通常,我们将容器内的成员统称为 Flex 项目(Flex item),简称 "项目"。

本文约定:"容器" 指的是 Flex 容器;"项目" 指的是 Flex 项目。

1.2 主轴、交叉轴

容器中默认存在两条线轴,即:主轴(main axis)交叉轴(cross axis)。主轴与交叉轴是垂直关系,值得注意的是主轴不一定是水平方向,而是由 flex-direction 属性所决定的。

  • main axis:主轴。
  • cross axis:交叉轴。

1.3 轴线起始位置

  • main start:主轴开始位置
  • main end:主轴结束位置
  • cross start:交叉轴开始位置
  • cross ennd:交叉轴结束位置

1.4 主轴、交叉轴空间

项目(flex item)默认是沿主轴方向排列的,单个项目占据主轴的空间称之为 main size,占据交叉轴的空间称之为 cross size

  • main size:占据主轴的空间
  • cross size:占据交叉轴的空间

二、容器、项目属性


本小节,主要介绍一下容器属性及项目属性。通过本章节,相信你会加深对 Flex 布局理解。为了形象说明这些属性的含义,作者 Billow 尽可能在每个示例中做到图文并茂。

2.1 容器属性

下表展示了容器的属性和取值。

属性取值说明
displayflex定义一个 Flex 容器,弹性盒子
inline-flex定义一个内联元素为 Flex 容器
flex-direction

row (默认)

从左到右

row-reverse 

从右到左

column 

从上到下
column-reverse从下到上
flex-wrap

nowrap (默认,不换行)

wrap(换行)

wrap-reverse(反向换行)

flex项目在一个轴线排不下情况,该如何换行。
flex-flow<flex-direction> <flex-wrap>

 flex-direction 与 flex-wrap 的缩写形式。

justify-content

flex-start(默认,左对齐)

flex-end(右对齐)

center(居中)

space-between 

space-around

flex项目在主轴上的对齐方式。

align-items

flex-start

flex-end

center

stretch

baseline

定义项目在交叉轴上对齐方式
align-content

flex-start

flex-end

center

space-between

space-around

stetch

定义多条线轴对齐方式,若只有一条线轴。

若仅有一条线轴,该属性无效。

2.1.1 flex-direction

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}

flex-direction 属性,定义了在哪个方向上排列项目。flex-direction有四个取值,分别为:

取值说明
row由左到右。(默认)
row-reverse从右到左。
column从上到下。
column-reverse从下到上。

图2-1 容器定义 flex-direction 属性示例图

图2-1 完整代码:

<!DOCTYPE html>
<html>
<head>
<style>
.flex-container-row {
  display: flex;
  flex-direction: row;
}

.flex-container-row-reverse {
  display: flex;
  flex-direction: row-reverse;
}

.flex-container-column {
  display: flex;
  flex-direction: column;
}

.flex-container-column-reverse {
  display: flex;
  flex-direction: column-reverse;
}

.flex-item {
  border:1px solid #fff;
  height:60px;
  width:60px;  
  text-align:center;
  line-height:60px;
  background: #f66;
  color:white;
}

.flex-item.blue {
  border:1px solid #fff;
  background: #33f;
}
</style>
</head>

<body>
  <div class="flex-container-row">
    <div class="flex-item">1.刘邦</div>
	<div class="flex-item">2.吕雉</div>
	<div class="flex-item">3.项羽</div>
	<div class="flex-item">4.虞姬</div>
  </div>  
  
  <div class="flex-container-row-reverse">
    <div class="flex-item blue">伯</div>
	<div class="flex-item blue">仲</div>
	<div class="flex-item blue">叔</div>
	<div class="flex-item blue">季</div>
  </div>
  
   <div class="flex-container-column">
  <div class="flex-item">金</div>
	<div class="flex-item">银</div>
	<div class="flex-item">铜</div>
  </div>
  
  
  <div class="flex-container-column-reverse">
  <div class="flex-item blue">苏洵</div>
	<div class="flex-item blue">苏轼</div>
	<div class="flex-item blue">苏辙</div>
  </div>
</body>

</html>

2.1.2 flex-wrap

flex-wrap 定义了项目在轴线上的排列方式,在默认情况下,项目都排列在一条轴线上,不会换行,可以通过 flex-wrap 来定义换行的方式。

取值说明
nowrap默认值,不换行
wrap项目沿着轴线方向排列,一行排不下后,换行排列。        
wrap-reverse反向换行。例如:在主轴线上,第一行会在第二行的下放。

 图2-2 容器定义 flex-wrap 示例

图2-2 完整代码:

<!DOCTYPE html>
<html>
<head>
<style>
.flex-container-nowrap {
  display: flex;
  flex-wrap: nowrap;
}

.flex-container-wrap {
  display: flex;
  flex-wrap: wrap;
  margin-top:10px;
}

.flex-container-wrap-reverse {
  display: flex;
  flex-wrap: wrap-reverse;
  margin-top:10px;
}

.flex-item {
  border:1px solid #fff;
  height:60px;
  width:120px;  
  text-align:center;
  line-height:60px;
  background: #f66;
  color:white;
  font-size:18px;
}

.flex-item.blue {
  border:1px solid #fff;
  background: #33f;
}

.flex-item.gray {
  border:1px solid #fff;
  background: #666;
}

.flex-item.circle {
  border-radius: 10%;
}

h3 {
  color: #666;
}
</style>
</head>

<body>
  <h3>nowrap</h3>
  <div class="flex-container-nowrap">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
    <div class="flex-item">8</div>
  </div>  

  <h3>wrap</h3>
  <div class="flex-container-wrap">
    <div class="flex-item gray">1</div>
    <div class="flex-item gray">2</div>
    <div class="flex-item gray">3</div>
    <div class="flex-item gray">4</div>
    <div class="flex-item gray">5</div>
    <div class="flex-item gray">6</div>
    <div class="flex-item gray">7</div>
    <div class="flex-item gray">8</div>
  </div>
  
  <h3>wrap-reverse</h3>
   <div class="flex-container-wrap-reverse">
    <div class="flex-item blue circle">1</div>
    <div class="flex-item blue circle">2</div>
    <div class="flex-item blue circle">3</div>
    <div class="flex-item blue circle">4</div>
    <div class="flex-item blue circle">5</div>
    <div class="flex-item blue circle">6</div>
    <div class="flex-item blue circle">7</div>
    <div class="flex-item blue circle">8</div>
  </div>
</body>
</html>

值得注意的是,当我们将 flex-wrap 设置为 nowrap 后,并将每一个项目的宽度设置为 120px ,但是,但主轴宽度无法容纳所有项目后,项目的实际宽度会被收缩,在flex项目属性中,我们会详细解释。

2.1.3 flex-flow

flex-flow 是 flex-direction 与 flex-wrap 的缩写形式。

语法:flex-flow: <flex-direction>  <flex-wrap>

例子:

flex-flow: row nowrap (默认值,项目沿着主轴排列,不换行。)

flex-flow: column  wrap-reverse(项目沿着交叉轴排列,反向换行)

2.1.4 justify-content

justify-content 定义了项目在主轴上的对齐方式。共有5个取值,如下表所示。

取值说明
flex-start左对齐
flex-end右对齐
center居中
space-between两端对齐,项目间隔相等
space-around项目间隔相等,两端也有间隔。

图2-3 容器定义  justify-content 示例

下图很好的解释了 space-between 与 space-around 的区别,space-between 会使项目两端对齐,并且项目之间的间距相同。space-around 同样会是的项目间距相同,不同之处是与两端也会有间距。

可以看出 space-around 项目与项目之间的距离是两端间距的2倍。你可以理解为:margin-left、margn-right 设置了相同的值。

图2-4 space-between 与 space-around 的区别

图2-3完整代码:

<!DOCTYPE html>
<html>
<head>
<style>

body {
  padding:0;
  margin:0;
}

.flex-container-flex-start {
  display: flex;
  justify-content: flex-start;
}

.flex-container-flex-end {
  display: flex;
  justify-content: flex-end;
}

.flex-container-center {
  display: flex;
  justify-content: center;

}

.flex-container-space-between {
  display: flex;
  justify-content: space-between;
}

.flex-container-space-around {
  display: flex;
  justify-content: space-around;
}

.flex-item {
  border:1px solid #fff;
  height:60px;
  width:120px;  
  text-align:center;
  line-height:60px;
  background: #f66;
  color:white;
  font-size:18px;
}

.flex-item.blue {  background: #33f; }
.flex-item.gray { background: #666; }
.flex-item.purple { background: #f6f; }
.flex-item.brown { background: #9e5b03; }
.flex-item.circle {
  border-radius: 10%;
}

h3 {
  color: #666;
  margin-top:10p;
  border: 1px dashed #dcdcdc;
}
</style>
</head>

<body>
  <h3>flex-start</h3>
  <div class="flex-container-flex-start">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
  </div>  

  <h3>flex-end</h3>
  <div class="flex-container-flex-end">
    <div class="flex-item gray">1</div>
    <div class="flex-item gray">2</div>
    <div class="flex-item gray">3</div>
    <div class="flex-item gray">4</div>
    <div class="flex-item gray">5</div>
    <div class="flex-item gray">6</div>
  </div>
  
  <h3>center</h3>
   <div class="flex-container-center">
    <div class="flex-item blue">1</div>
    <div class="flex-item blue">2</div>
    <div class="flex-item blue">3</div>
    <div class="flex-item blue">4</div>
    <div class="flex-item blue">5</div>
    <div class="flex-item blue">6</div>
  </div>

  <h3>space-between</h3>
  <div class="flex-container-space-between">
   <div class="flex-item purple">1</div>
   <div class="flex-item purple">2</div>
   <div class="flex-item purple">3</div>
   <div class="flex-item purple">4</div>
   <div class="flex-item purple">5</div>
   <div class="flex-item purple">6</div>
 </div>
 <h3>space-around</h3>
  <div class="flex-container-space-around">
   <div class="flex-item brown">1</div>
   <div class="flex-item brown">2</div>
   <div class="flex-item brown">3</div>
   <div class="flex-item brown">4</div>
   <div class="flex-item brown">5</div>
   <div class="flex-item brown">6</div>
 </div>

</body>
</html>

2.1.5 align-items

align-items 属性,定义了项目在交叉轴上的对齐方式,有5个取值。

取值说明
flex-start与交叉轴的起点对齐

flex-end

与交叉轴的终点对齐
center在交叉轴上居中对齐
baseline以项目中第一行文字基线对齐
stretch在未设置高度情况下,将占满容器的高度

2.1.6 align-content

align-content 属性定义了多根主轴线在垂直方向上的对齐方式。

align-content 取值说明
flex-start与交叉轴起点对齐
flex-end与交叉轴终点对齐
center在交叉轴上居中对齐
space-between与交叉轴两端对齐,轴线之间的间隔平均分布
space-around轴线之间的间隔平均分布,包括两端
stretch默认值,轴线占满交叉轴

2.2 项目属性

项目属性默认值说明
order0定义了项目的排列顺序。
flex-grow0扩大因子,定义了项目的放大比例
flex-shrink1收缩因子,定义了项目的缩小比例
flex-basicautoflex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
flex0 1 autoflex-grow、flex-shrink、flex-basis的缩写形式
align-selfauto

align-self 属性允许单个项目有与其他项目不一样的对齐方式,

也就是说改属性可以覆盖父容器设置的 align-items 属性。

在继续讲解这些项目属性之前,我们先来了解一个非常重要的概念 — 剩余空间

图 2-5 剩余空间

为了解释剩余空间,下面给出一个示例。如图2-5所示,我们将父容器的宽度设置为 800px,容器中3个项目宽度分别为100px、200px、300px。那么,剩余空间就是:

200px = 800px - (100px + 200px + 300px)

简言之, flex-grow、flex-shrink 和 flex-basis 都是围绕如何分配剩余空间展开的。

2.2.1 order 

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

.item { order: <integer> }

 图2-6 order 属性示例

图2-6 完整代码

<!DOCTYPE html>
<html>
<head>
<style>

.flex-container {
  display: flex;
  margin-top:5px;
}

.item {
  height:60px;
  width:60px;  
  text-align:center;
  line-height:60px;
  background: #f66;
  color:white;
  font-size:18px;
  border-radius: 100px;
}

.item.red {background: #f66;}
.item.blue {  background: #66f; }
.item.gray { background: #666; }
.item.purple { background: #f6f; }
.item.brown { background: #9e5b03; }

h3 {
  color: #666;
  margin-top:10px;
  border-bottom: 1px dashed #dcdcdc;
}
</style>
</head>

<body>
  <h3>order</h3>
  <div class="flex-container">
    <div style="order:0" class="item red" >一</div>
    <div style="order:1" class="item blue">二</div>
    <div style="order:2" class="item gray" >三</div>
    <div style="order:3" class="item purple">四</div>
    <div style="order:4" class="item brown" >五</div> 
  </div>  

  <div class="flex-container">
      <div style="order:4" class="item red" >一</div>
      <div style="order:3" class="item blue">二</div>
      <div style="order:2" class="item gray" >三</div>
      <div style="order:1" class="item purple">四</div>
      <div style="order:0" class="item brown" >五</div> 
   </div>
</body>
</html>

2.2.2 flex-grow

扩大因子,定义项目的放大比例 。

.item { flex-grow: <number> }

2.2.3 flex-shrink

收缩因子,定义了项目的缩小比例。

.item { flex-shrink: <number> }

 图 2-7 flex-grow 与 flex-shrink 的使用

图2-7 完整代码

<!DOCTYPE html>
<html>
<head>
<style>

.flex-container {
  display: flex;
  margin-top:1px;
}

.item {
  height:60px;
  width:60px;  
  text-align:center;
  line-height:60px;
  background: #f66;
  color:white;
  font-size:18px;
}

.item.red {background: #f66;}
.item.blue {  background: #66f; }
.item.gray { background: #666; }
.item.purple { background: #f6f; }
.item.brown { background: #9e5b03; }

h3 {
  color: #666;
  margin-top:10px;
  border-bottom: 1px dashed #dcdcdc;
}
</style>
</head>

<body>
   
   <h3>flex-grow</h3>
   <div class="flex-container">
      <div style="flex-grow:0" class="item blue">0</div>
      <div style="flex-grow:1" class="item red" >1</div>
      <div style="flex-grow:2" class="item blue">2</div>
      <div style="flex-grow:3" class="item red" >3</div>
      <div style="flex-grow:4" class="item blue">4</div>
      <div style="flex-grow:5" class="item red" >5</div>
   </div>
   <div class="flex-container">
      <div style="flex-grow:0" class="item blue">0</div>
      <div style="flex-grow:1" class="item red" >1</div>
      <div style="flex-grow:0" class="item blue">0</div>
   </div>

   <h3>flex-shrink</h3>
   <div class="flex-container" style="width:600px;border:1px dotted #dcdcdc;">
      <div style="flex-shrink:0;width:100px;" class="item blue">100</div>
      <div style="flex-shrink:1;width:100px;" class="item red" >100</div>
      <div style="flex-shrink:2;width:100px;" class="item blue">100</div>
   </div>

   <div class="flex-container" style="width:600px;border:1px dotted #dcdcdc;">
      <div style="flex-shrink:0;width:300px;" class="item blue">300</div>
      <div style="flex-shrink:1;width:300px;" class="item red" >300</div>
      <div style="flex-shrink:1;width:300px;" class="item blue">300</div>
   </div>

   <div class="flex-container" style="width:600px;border:1px dotted #dcdcdc;">
      <div style="flex-shrink:0;width:300px;" class="item blue">300</div>
      <div style="flex-shrink:1;width:300px;" class="item red" >300</div>
      <div style="flex-shrink:5;width:300px;" class="item blue">300</div>
   </div>
</body>
</html>

2.2.4 flex-basis

flex-basis 属性定义了在分配多余空间之前,项目占据主轴空间。默认值为:auto,即项目本来大小。

理解这段话的重点两个字就是 "之前"。

我们将3个 item 宽度分别设置为 100px、200px、300px,并且将第3个项目的 flex-basis 设置为 400px。可以看出,效果如下图第2行所示。

图2-8 加了 flex-basis 后的剩余空间

图2-8 完整代码:

<!DOCTYPE html>
<html>
<head>
<style>

.flex-container {
  display: flex;
  width: 800px;
  border: 1px solid red;
  margin-top:5px;
}

.item {
  width:60px; 
  text-align:center;
  line-height:60px;
  color:white;
  font-size:18px;
  border:1px solid #fff;

}

.item.red {background: #f66;}
.item.blue {  background: #66f; }
.item.gray { background: #666; }
</style>
</head>

<body>
  <div class="flex-container">
    <div class="item red" style="width:100px">100px</div>
    <div class="item blue" style="width:200px">200px</div>
    <div class="item gray" style="width:300px;">300px</div>
  </div>

  <div class="flex-container">
      <div class="item red"  style="width:100px">100px</div>
      <div class="item blue" style="width:200px">200px</div>
      <div class="item gray" style="width:300px;flex-basis:400px;">300px/400px</div>
   </div>
</body>
</html>

2.2.5 flex

flex 为 flex-grow、flex-shrink、flex-basis 的缩写形式。

flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]

默认值为: 0 1 auto

另外,改属性有两个快捷值:

flex: auto   相当于 flex: 1 1 auto

flex: none 相当于 flex: 0 0 auto

2.2.6 align-self

align-self 属性允许单个项目有与其他项目不一样的对齐方式。也就是说改属性可以覆盖父容器设置的 align-items 属性。

取值说明
auto继承父元素的 align-items 属性
flex-start与交叉轴的起点对齐

flex-end

与交叉轴的终点对齐
center在交叉轴上居中对齐
baseline以项目中第一行文字基线对齐
stretch在未设置高度情况下,将占满容器的高度

三、综合示例


为了加深对 Flex 布局的理解,下面给出几个综合性的例子。

3.1 春联

在古代,在竹简写字一般都是从右向左、从上向下的顺序。下面我们用 Flex 布局来实现这样的例子。实现从右到左,从上到下书写春联。

 图3-1 春联

图3-1 春联完整代码

<!DOCTYPE html>
<html>
<head>
<style>

/*定义一个Flex容器*/
#container {
  display: flex;
  flex-direction:column;
  flex-wrap: wrap-reverse;
  align-content: flex-start;
  height: 700px;  
  font-family: LiSu;
  background: #f33;
}

/*每一个字的样式*/
.word { 
  height: 100px;
  width: 100px;
  line-height: 100px;
  font-size: 50px;
  text-align:center; 
  background: #f33;
  border-left: 1px solid white;
  color:black;
}
</style>
</head>

<body>
  <div id="container"></div>
</body>

<script>
    var innerHtml = "";
	var p = "一年好运随春到" 
	      + "四季彩云滚滚来"
		  + "一年四季春常在"
		  + "万紫千红永开花";
	
	for(var i = 0;i < p.length;i++) {
	  innerHtml += "<div class='word'>" + p.charAt(i) + "</div>";
	}  
	document.getElementById("container").innerHTML = innerHtml;
	
</script>
</html>

与 Flex 布局相关的显式代码仅4行: 

#container {
  display: flex;  /*定义一个Flex容器*/
  flex-direction:column;  /*每个项目(每个字)的顺序为从上到下。*/
  flex-wrap: wrap-reverse;  /*反向换行,即:第二行在第一行的左面。*/
  align-content: flex-start; /*多条轴线,靠右对其。*/
  height: 700px;  
  font-family: LiSu;
  background: #f33;
}

当然,我们也可以用 flex-flow 实现:

#container {
  display: flex;  /*定义一个Flex容器*/
  /* flex-direction:column; */  /*每个项目(每个字)的顺序为从上到下。*/
  /* flex-wrap: wrap-reverse; */ /*反向换行,即:第二行在第一行的左面。*/
  flex-flow: column wrap-reverse; 
  align-content: flex-start; /*多条轴线,靠右对其。*/
  height: 700px;  
  font-family: LiSu;
  background: #f33;
}

手工码字,虽然已经检查多遍,难免有不足之处,发现有错误之处,请多多指教。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值