Flexbox 实战:使用 Flexbox 轻松实现下拉导航菜单

3,122 阅读5分钟
原文链接: svgtrick.com

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实现一个水平菜单

导航菜单的结构非常简单,主要是由navbarmenu两个类结构组成。

<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>
</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属性,这样可以使子元素能占满整个宽度了。

目前导航栏的基本布局完成了,代码预览地址

可以看到使用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>

类名为containerflex容器而且每一个子元素(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这个属性在布局上的威力,这里只是抛砖引玉下,在实际开发中还有很多的实用的地方。

demo地址

本文主要是从Building Mega Menus with Flexbox这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!