传统布局的局限性:
Flex布局相较于传统布局方式有哪些优点;
为什么我们要采用Flex布局来进行页面设计;
我们如何通过Flex布局来设计页面。
传统布局——基于盒子模型,依赖 display 属性、position属性、float属性。
它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。
并且,传统布局代码冗长,出错率高,要时刻注意清除浮动或者在进行绝对定位时给父元素添加相对定位。否则就容易造成页面布局混乱。
但是,Flex布局就就可以避免这种情况:
Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为Flex布局。
注意,设为 Flex 布局以后,子元素的float、clear和vertical-align属性都将失效!!!
那么如何实现Flex布局,它可以帮助我们实现什么效果呢
容器属性:
- flex-direction属性:决定主轴的方向(即项目的排列方向);
- flex-wrap属性:规定如果一条轴线排不下,如何换行;
- flex-flow属性:是flex-direction属性和flex-wrap属性的简写形式,默认值为row/nowrap;
- justify-content属性:定义了项目在主轴上的对齐方式;
- align-items属性:定义项目在交叉轴上如何对齐;
- align-self属性:定义了单独子项的对齐方式;
- flex:n 是三个属性的集合 “flex-basis”、“flex-grow"和"flex-shrink”。
容器属性具体实现效果:
一、flex-direction属性:决定主轴的方向(即项目的排列方向)。
- row(默认值):主轴为水平方向,起点在左端;
- row-reverse:主轴为水平方向,起点在右端;
- column:主轴为垂直方向,起点在上沿;
- column-reverse:主轴为垂直方向,起点在下沿。
简介
引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的条目进行排列、 对齐和分配空白空间。
图 1. 弹性盒布局模型相关的概念
弹性盒布局的容器(flex container)指的是采用了弹性盒布局的 DOM 元素,而弹性盒布局的条目(flex item)指的是容器中包含的子 DOM 元素。图中的最外围的边框表示的是容器,而编号 1 和 2 的边框表示的是容器中的条目。
所有代码示例中,容器的 CSS 类名统一为 flex-container,而条目的 CSS 类名则为 flex-item。
基本布局
首先从最基本的布局开始介绍弹性盒布局模型。要实现的布局效果是一个简单的图片缩略图预览页面。
简单的图片缩略图预览页面的 HTML 代码
<ul class="flex-container">
<li class="flex-item"><img src="http://placehold.it/300&text=1"></li>
<li class="flex-item"><img src="http://placehold.it/300&text=2"></li>
<li class="flex-item"><img src="http://placehold.it/300&text=3"></li>
<li class="flex-item"><img src="http://placehold.it/300&text=4"></li>
<li class="flex-item"><img src="http://placehold.it/300&text=5"></li>
<li class="flex-item"><img src="http://placehold.it/300&text=6"></li>
</ul>
该页面的基本 HTML 是很简单的。在一个
- 元素下面有 6 个
- 元素。每个
- 元素中包含一个大小为 300x300 的缩略图图片。
- 元素作为弹性盒布局的容器,而
- 元素则是容器中的条目。
简单的图片缩略图预览页面的 CSS 代码
.flex-container {
list-style: none;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.flex-item {
padding: 5px;
}
在代码2 中,对于弹性盒布局的容器,使用"display: flex"声明使用弹性盒布局。CSS 属性声明"flex-direction"用来确定主轴的方向,从而确定基本的条目排列方式。"flex-direction"属性的可选值及其含义如表1所示。
表 1. “flex-direction”属性的可选值及其含义
默认情况下,弹性盒容器中的条目会尽量占满容器在主轴方向上的一行。当容器的主轴尺寸小于其 所有条目总的主轴尺寸时,会出现条目之间互相重叠或超出容器范围的现象。CSS 属性"flex-wrap"用来声明当容器中条目的尺寸超过主轴尺寸时应采取的行为。"flex-wrap"属性的可选值及其含义如表2所示。
表 2. “flex-wrap”属性的可选值及其含义
可以使用"flex-flow"属性把"flex-direction"和"flex-wrap"结合起来,如下代码所示。
3. “flex-flow”属性的使用示例
flex-flow: row wrap;
容器中的条目
除了弹性盒布局模型中的容器之外,容器中的条目也可以通过 CSS 属性来改变其布局行为。下面介绍容器中的条目可以使用的 CSS 属性声明。
条目的顺序
默认情况下,容器中条目的顺序取决于它们在 HTML 标记代码中的出现顺序。可以通过"order"属性来改变条目在容器中的出现顺序。对于代码中的 HTML 标记添加4中的 CSS 声明,运行之后的效果是最后一个
元素出现在了其他
元素的最前面。
-
4. “order”属性的使用示例
.flex-item:last-child { order: -1; }
"order"属性的主要作用是兼顾页面的样式和可访问性。支持可访问性的设备,如屏幕阅读器,都是按照 HTML 中代码的顺序来读取元素的。这就要求一些相对重要的文本出现在 HTML 标记的前面。而对于使用浏览器的一般用户来说,在某些情况下把一些相对不重要的图片显示在前面是更好的选择。比如在一个商品的展示页面中,在源代码中把商 品描述的文本放在商品图片之前。这样可以方便屏幕阅读器的读取;而在 CSS 中使用"order"属性把图片放在文本的前面。这样可以让用户首先看到图片。
条目尺寸的弹性
弹 性盒布局模型的核心在于容器中条目的尺寸是弹性的。容器可以根据本身尺寸的大小来动态地调整条目的尺寸。当容器中有空白空间时,条目可以扩展尺寸以占据额 外的空白空间;当容器中的空间不足时,条目可以缩小尺寸以防止超出容器范围。条目尺寸的弹性由 3 个 CSS 属性来确定,分别是"flex-basis"、“flex-grow"和"flex-shrink”。
"flex-basis"属性声明接 受的值与"width"属性是一样的,用来确定弹性条目的初始主轴尺寸。这是条目的尺寸被容器调整之前的初始值。如果"flex-basis"的值为 auto,则实际使用的值是主轴尺寸属性的值,即 width 或 height 属性的值。如果主轴尺寸属性的值也是 auto,则使用的值由条目内容的尺寸来确定。
"flex-grow"属性的值是一个没有单位的非负数,默认值是 0。"flex-grow"属性的值表示的是当容器有多余的空间时,这些空间在不同条目之间的分配比例。比如,一个容器中有 3 个条目,其"flex-grow"属性的值分别为 1,2 和 3,那么当容器中有空白空间时,这 3 个条目所获得的额外空白空间分别占全部空间的 1/6、1/3 和 1/2,如代码清单 5所示。预览的页面见这里。
清单 5. “flex-grow”属性的使用示例
.flex-item:nth-child(1) { flex-grow: 1; } .flex-item:nth-child(2) { flex-grow: 2; } .flex-item:nth-child(3) { flex-grow: 3; }
“flex-shrink"属性在使用上类似于"flex-grow”。该属性的值也是无单位的,表示的是当容器的空间 不足时,各个条目的尺寸缩小的比例。在进行尺寸缩小时,条目的缩小比例与"flex-basis"的值相乘之后,就得到了应该缩小的尺寸的实际值。例如, 在容器中有 3 个条目,其"flex-shrink"属性的值分别为 1,2 和 3。每个条目的主轴尺寸均为 200px。当容器的主轴尺寸不足 600px 时,比如变成了 540px 之后, 则需要缩小的尺寸 60px 由 3 个条目按照比例来分配。3 个条目分别要缩小 10px、20px 和 30px,主轴尺寸分别变为 190px、180px 和 170px。预览的页面见这里。
使 用属性"flex"可以同时声明"flex-basis"、"flex-grow"和"flex-shrink"的值,格式是"none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]"。该属性的值的 3 个组成部分的初始值分别是"0 1 auto"。当属性"flex"的值为 none 时,相当于"0 0 auto"。当组成部分"flex-basis"被省略时,其值为 0%。代码清单 6给出了属性"flex"的使用示例。
清单 6. 属性“flex”的使用示例
.flex-item:nth-child(1) { flex: 1 1 auto; } flex: 1; // flex-grow 的值为 1,flex-shrink 的值为 1,flex-basis 的值为 0%。
需要注意的是,在容器分配额外空间时是以"行"为单位的。容器先根据"flex-wrap"的属性值来确定是单行布局或多行布局,然后把条目分配到对应的行中,最后在每一行内进行空白空间的分配。如代码清单 7中的 CSS 声明示例,在容器中有 4 个条目。
清单 7. 多行布局的 CSS 声明
.flex-container { width: 990px; } .flex-item { width: 300px; flex: auto; }
由于容器的宽度只有 990px,所以在一行中只能排列 3 个条目,而剩下的 1 个条目则会被排列到单独的一行中。在 3 个条目的行中,多余的空间 90px 被平均分配给 3 个条目;而在一个条目单独的行中,多余的 690px 被该条目完全占据。
条目对齐
当容器中的条目的尺寸确定之后,可以设置这些条目在容器中的对齐方式。对齐条目的方式有 3 种。
第一种方式是使用自动空白边,即"margin: auto"。在使用自动空白边时,容器中额外的空白空间会被声明为 auto 的空白边占据,如代码清单 8所示。CSS 声明 profile 中通过"margin-left: auto"使得该条目左边的空白边会占据额外的空间,从而"Profile"文本会靠右显示。预览的页面见这里。
清单 8. 使用自动空白边进行条目对齐
<div class="flex-container"> <div class="logo">Logo</div> <div class="profile">Profile</div> </div> .flex-container { display: flex; } .profile { margin-left: auto; }
第二种方式是在主轴方向上的对齐。这是通过容器上的"justify-content"属性来进行设置,可以调整条目在 主轴方向上的对齐方式。这种条目对齐方式的调整发生在修改条目的弹性尺寸和处理自动空白边之后。当容器中的一行中的条目没有弹性尺寸,或是已经达到了它们 的最大尺寸时,在这一行上可能还有额外的空白空间。使用"justify-content"属性可以分配这些空间。该属性还可以控制当条目超出行的范围时 的对齐方式。"justify-content"属性的可选值和含义如表3所示,实际的布局效果见图 2。
表 3. “justify-content”属性的可选值和含义
第 三种方式是交叉轴方向上的对齐。除了在主轴方向上对齐之外,条目也可以在交叉轴方向上对齐。容器上的属性"align-items"用来设置容器中所有条 目在交叉轴上的默认对齐方向,而条目上的属性"align-self"用来覆写容器指定的对齐方式。属性"align-items"的可选值和含义如表4所示,实际的布局效果见图 3。
表 4. 属性“align-items”的可选值和含义
属性"align-self"的可选值除了表中列出的之外,还可以设置为"auto"。当"align-self"的值为 auto 时,其计算值是父节点的属性"align-items"的值。如果该节点没有父节点,则计算值为"stretch"。
图 3. 属性“align-items”不同值的布局效果
交叉轴空白处理
当 容器在交叉轴方向上有空白空间时,属性"align-content"用来对齐容器中的行。该属性的作用类似于"justify-content",只不 过"justify-content"是在主轴方向上对齐行中的条目。当容器中只有单行时,该属性不起作用。属性"align-content"的可选值 和含义如表5所示,实际的布局效果见图 4。
表 5. 属性“align-content”的可选值和含义
应用示例
下面通过一个示例来具体说明弹性盒布局在实际开发中的应用。该示例是一个博客帖子的典型页面布局。在展示一个博客帖子时,页面上通常包括标题、发表者、日期和时间、评论数量、正文、插图、评论列表等元素。这些元素基本上按照从上到下的顺序依次排列。
<div class="post"> <h1>This is my first blog post</h1> <div class="post-meta"> <div class="author">Alex Cheng</div> <div class="datetime">2014-07-02 10:10 am</div> <div class="comments-count">2 comments</div> </div> <div class="post-body"> My first blog post. </div> <div class="post-image"> <img src="http://placehold.it/500x200&text=1"> </div> <div class="post-comments"> <h3>Comments</h3> <ul> <li><div class="author">Bob</div><div>This is a good post.</div></li> <li><div class="autho">David</div><div>Good post.</div></li> </ul> </div> </div>
清单 10. 博客页面的 CSS 代码
.post { display: flex; flex-flow: column wrap; } .post-meta { display: flex; flex-flow: row wrap; order: 1; } .post-body { order: 3; } .post-comments { order: 4; } .comments-count { margin-left: auto; } .post-image { order: 2; align-self: center; }
该示例中主要使用了"order"属性来改变条目的显示位置,以及使用"align-self"来使得图片居中显示。