CSS3弹性盒子(Flexible Box 或 Flexbox),是一种用于在页面上布置元素的布局模式,使得当页面布局必须适应不同的屏幕尺寸和不同的显示设备时,元素可预测地运行。对于许多应用程序,弹性盒子模型提供了对块模型的改进,因为它不使用浮动,flex容器的边缘也不会与其内容的边缘折叠。
浏览器对Flexbox的支持越来越好。使用它可以轻松实现一些复杂的UI用户界面,不需要任何的CSS或者是javascript的黑科技。
使用Flexbox可以轻松实现各种水平或者是垂直的布局,对于不同尺寸的屏幕,不需要很多的媒体查询就可以轻松做到自适应。
这篇教程,我们使用Flexbox来实现一个复杂一点的下拉导航菜单。当然这里不会花太多文字放在Flexbox的一些基本属性的介绍,Flexbox基本的介绍和使用可以去下面这些文章看看:
Flexbox Course by Guy Routledge
A Friendly Introduction to Flexbox for Beginners
下来看看我们要做的导航菜单,如下图所示:
demo地址
下载地址
主要用到了下面三个方面的知识:
1、使用Flexbox实现一个包含下拉菜单的水平方向导航栏
2、实现一个单栏的下拉菜单
3、实现一个多栏的下拉菜单
使用Flexbox实现一个水平菜单
导航菜单的结构非常简单,主要是由navbar和menu两个类结构组成。
<
nav
class
=
"navbar"
>
<
ul
class
=
"menu"
>
<
li
>
<
a
href
=
"#"
>
Electronics
<!-- FontAwesome icon -->
<
i
class
=
"fa fa-angle-down"
></
i
>
</
a
>
</
li
>
<!-- ... More nav items here... -->
<
ul
>
</
ul
></
ul
></
nav
>
|
首先导航菜单是水平方向的布局,我们期望的是每个导航栏目在没有足够的空间时,也能自动的根据空间来进行响应式适用。
这种布局使用Flexbox来实现再好不过了。首先要声明menu这个元素的flex属性,可以使用display:flex来声明,这样menu元素的所有子元素都具有来flex属性。
现在设置flex的值为1,即如果空间不足,该项目将缩小。
.navbar .menu {
display
: flex;
position
:
relative
;
}
.navbar .menu li {
flex:
1
;
display
: flex;
text-align
:
center
;
}
.navbar .menu a {
flex:
1
;
justify-
content
:
center
;
color
:
#ffffff
;
padding
:
20px
;
}
|
从上面的代码可以看到,对于.navbar .menu li和.navbar .menu两个元素都设置了display:flex的属性。从demo可以看到,当鼠标滑过菜单选项的时候可以看到背景颜色发生了改变。如果不设置display的值为flex,那么li元素只会占据本身内容所占的宽度,而不是根据整个导航栏的宽度来平分了。
为了使导航菜单的子元素能根据父级元素的宽度来扩展自己的宽度,所以在li元素和a元素上都声明了flex:1属性,这样可以使子元素能占满整个宽度了。
目前导航栏的基本布局完成了,代码预览地址。
demo地址
下载地址
可以看到使用Flexbox可以非常轻松的完成这样类型的布局,而且简洁高效。
下面来实现下拉菜单这一项。
单栏下拉菜单
下面是下拉菜单的结构,当然它可以复用到其它地方。
<
ul
class
=
"container"
>
<!-- single column -->
<
div
class
=
"container__list"
>
<!-- menu item -->
<
div
class
=
"container__listItem"
>
<
div
>Televisions</
div
>
</
div
>
<!-- ... other menu items here -->
</
div
>
</
ul
>
|
类名为container是flex容器而且每一个子元素(containerlist)都是容器成员,即Flex项目。而且每一个**containerlist项目都有多个导航栏目,所以我使用了一个div**来包裹它。
下面是CSS代码:
.container {
/* initially hidden; display:flex on hover */
display: none;
position: absolute;
top: 56px;
left: 0;
right: 0;
background-color: #ffffff;
padding: 20px;
text-align: left;
}
.container__list {
flex: 1;
display: flex;
flex-wrap: wrap;
}
.container__listItem {
flex: 0 0 25%;
padding: 10px 30px;
}
.container__listItem > div {
color: #DB6356;
}
|
从上面代码可以注意到我在container__list容器上使用了flex-wrap属性,我们想它的宽度是占整个宽度的25%,当空间不够时,它就自动换行。
flex-grow属性定义项目的放大比例,我们设置它的值为0,即如果存在剩余空间,也不放大。
对于container__listItem元素,为了使文字太宽而影响布局的美观,需要做一下截断处理,比如超过指定的宽度,就显示省略号,可以使用下面的代码来实现:
.container__list {
flex: 1;
display: flex;
flex-wrap: wrap;
/* updated */
min-width: 0;
}
.container__listItem {
flex: 0 0 25%;
padding: 10px 30px;
/* updated */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.container__listItem > div {
color: #DB6356;
/* updated */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
|
实现多栏下拉菜单
在上面单栏菜单的基础上实现多栏菜单,就非常简单了。在这里,直接复用单栏菜单的结构即container__list的结构到菜单选项Appliances里面。当然这里只是简单的复制结构实现一个实例,在实际开发中,一般会使用到javascript来动态生成这些菜单选项。
这里会额外的增加一个has-multi类来区分开单栏与多栏的区别,并且来针对多栏菜单声明一些单独的属性的值。
.container.has-multi .container__list {
flex-basis: 33.333%;
}
.container.has-multi .container__list:not(:last-child) {
border-right: solid 1px #f3f3f3;
margin-right: 20px;
}
.container.has-multi .container__listItem {
flex-basis: 100%;
}
|
这里指定了多栏菜单选项的flex-basis的值为33.333,即多栏菜单选项占据的宽度为33.333,这样可以显示为三栏菜单。
当然,这个菜单并不是完全是响应式的。在小屏幕上只是简单垂直显示选项,而且选项下的子菜单并没有显示,还有很多改进的余地。总之通过这一个下拉导航菜单的实例,可以充分的证明Flexbox这个属性在布局上的威力,这里只是抛砖引玉下,在实际开发中还有很多的实用的地方。
本文主要是从Building Mega Menus with Flexbox这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!
原文地址:http://svgtrick.com/tricks/d172c31188f427a598b00148337a621d