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

A Complete Guide to Flexbox

下来看看我们要做的导航菜单,如下图所示:

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这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!

demo地址

原文地址:http://svgtrick.com/tricks/d172c31188f427a598b00148337a621d

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐