#简单的响应式菜单实现方案 响应式的菜单设计方案已经不是什么新鲜事了,以下方案用了非常简单的方式实现了一个简单的响应式菜单。 ##思路 我的思路是,在PC端上按正常的横向菜单展示,在设备宽度小到一定宽度时,自动换行显示;而在移动端上则以下拉菜单的形式展示。 换行显示可通过流式布局实现,而下拉菜单则通过媒体查询完成,可以说响应式布局就是流式加媒体查询。 最简单的方案自然是在手机端上写一套select标签,套上对应的菜单项,在PC端上隐藏该select,在手机端上展示该select,同时隐藏PC端上的菜单。 ##按PC端的方式开始 首先以PC端的开发方式写好HTML,同时写好对应的CSS即可。

首先是HTML结构:

<div class="responsive-menu">
      <ul class="menu-list mdedia-desktop">
        <li class="menu-item s-active"><a class="menu-link" href="#">菜单一</a></li>
        <li class="menu-item"><a class="menu-link" href="#">菜单二</a></li>
        <li class="menu-item"><a class="menu-link" href="#">菜单三</a></li>
        <li class="menu-item"><a class="menu-link" href="#">菜单四</a></li>
        <li class="menu-item"><a class="menu-link" href="#">菜单五</a></li>
      </ul>
</div>

对应的样式,我使用了SASS语法进行编写,使用SASS的优点如下:

  1. 方便维护
  2. CSS的模块化
  3. 通过暴露SASS变量,能够很方便的定制组件风格

对应的SASS如下:

/*
* $menuBgColor:菜单项背景色
* $menuHoverColor:菜单项hover
* $menuActiveColor:激活菜单项色
* $menuItemMargin:菜单项外间距
* $menuLinkPadding:菜单项内间距
*/
$menuBgColor: #ecebeb;
$menuHoverColor: #f8f8f8;
$menuActiveColor: #999;
$menuItemMargin: 15px 15px 0;
$menuLinkPadding: 4px 15px;

.responsive-menu {
   ul {
     list-style: none;
   }

   a {
        text-decoration: none;
   }

  .menu-item {
    float: left;
    margin: $menuItemMargin;
  }

  .menu-item.s-active .menu-link {
    background: $menuActiveColor;
  }

  .menu-link {
    display: block;
    padding: $menuLinkPadding;
    background: $menuBgColor;
    color: #000;
  }

  .menu-link:hover {
    background: $menuHoverColor;
  }

}

如上所示,我暴露了5个SASS变量,使用者可以很方面的定制自己的菜单风格。

生成的CSS如下:

.responsive-menu ul {
  list-style: none; }
.responsive-menu  a {
  text-decoration: none; }
.responsive-menu .media-phone {
  display: none; }
.responsive-menu .menu-item {
  float: left;
  margin: 15px 15px 0; }
.responsive-menu  .menu-item.s-active .menu-link {
  background: #999; }
.responsive-menu .menu-link {
  display: block;
  padding: 4px 15px;
  background: #ecebeb;
  color: #000; }
.responsive-menu .menu-link:hover {
  background: #f8f8f8; }

在浏览器上的效果如下:

![菜单图](/img/menu.jpg) ##移动端的适配 在PC端上完成了基本的页面,则可以开始加入移动端的HTML,以下是完整的HTML片段: ```html

``` HTML结构上,我分别对两个菜单各用了一个divc进行包裹,方面以后更加灵活的扩展。 对应的SASS如下: ```sass /* *$menuBgColor:菜单项背景色 *$menuHoverColor:菜单项hover色 *$menuItemMargin:菜单项外间距 *$menuLinkPadding:菜单项内间距 *$changeWidth:切换为下拉式状态的最大宽度 */ $menuBgColor: #ecebeb; $menuHoverColor: #f8f8f8; $menuActiveColor:#999; $menuItemMargin: 15px 15px 0; $menuLinkPadding: 4px 15px; $changeWidth: 480px; .responsive-menu { a { text-decoration: none; } .menu-list { list-style: none; } .media-phone { display: none; } .menu-item { float: left; margin: $menuItemMargin; } .menu-item.s-active .menu-link { background: $menuActiveColor; } .menu-link { display: block; padding: $menuLinkPadding; background: $menuBgColor; color: #000; } .menu-link:hover { background: $menuHoverColor; } } @media screen and (max-width: $changeWidth) { .responsive-menu { .media-desktop, .media-tablet { display: none; } .media-phone { display: block; } } } ``` 关键点在最后一段媒体查询,当设备宽度小于SASS变量$changeWidth所定义的值时,即展示下拉菜单,同时隐藏桌面菜单! 到此,一个简单的响应式菜单设计就出来了,在Android手机chrome上的效果图如下:

![menu-phone](/img/menu-phone.png) DEMO如下: 您可以缩放浏览器窗口,或者用手机体验一把~ ##一些需要改进的地方 1.若作为导航菜单,PC端上可直接作为链接点击跳转,而在移动端上则只有通过事件监听来改变, 造成了极大的不方便。因此需要通过增加相关的JS让使用者体验保持一致,DEMO中简单的监听了select的change事件,可自行增加更多的行为操作。 2.若要将菜单进行完善的组件化,还应该提供相关的JS接口和事件接口 ##总结 响应式的改进增加工作量是不可避免的,对HTML结构的灵活有了更大的要求,总的来说最狗血的方案应该是写两套HTML,一套隐藏一套显示。 对于简单的HTML尚可这样,比如文章中的下拉菜单,工作量并不大。 若是HTML较为复杂,则更需要谨慎考虑,HTML一旦变动,随之影响的是CSS与JS。 __[menu的SASS文件](https://github.com/Exodia/responsedpl/blob/master/menu.scss)__