响应式导航栏实现

作者: 打酱油12138 | 来源:发表于2019-09-27 09:32 被阅读0次
    前言

    最近想实现定制化的响应式顶部导航栏,即支持主流设备的正常访问(Phone、Pad、PC),并根据屏幕比例实现对应的显示效果。

    曾尝试使用以下方式

    • Element UI提供的导航栏(样式单调,没有响应式效果)
    • BootStrap 提供的导航栏(有响应式效果,需额外引入依赖包,且定制效果修改较繁琐)

    由此,产生自己动手实现响应式顶部导航栏的想法,并应当拥有以下特点:

    • 实现方式较为简单,无需引入额外依赖库(或较少)
    • 可以实现动态添加功能菜单,个性化定制较为简便
    • 实现对多种设备的兼容性,保证显示效果较为美观
    效果展示
    最终效果
    提前准备
    • 掌握H5、CSS布局技巧
    • 理解掌握CSS媒体查询
    • 掌握一种渐进式框架(这里结合Vue进行实现)
    • 对所要实现导航栏有一定的设计规划
    实现

    思路:将导航栏分为左右两部分,当窗口宽度减少时,使用css媒体查询实现样式修改,当宽度减小至最小时,隐藏当前导航显示,替换为下拉列表展示。

    • 主要通过css媒体查询实现样式改变
    • 为方便扩展,导航选项设置为对象数组

    Header.vue

    • template 部分
    <template>
      <!--xs: phone, sm: pad, md: pc, lg: 2k-pc, xl: 4k-pc-->
      <nav class="header">
        <!-- 顶部导航 -->
        <div class="container">
          <ul class="container-left-ul">
            <li>
              <img id="icon" src="@assets/image/icon.png"/>
            </li>
            <li :class="$store.state.activeName === item.activeName ? 'menu-item-active' : 'container-left-li'" @click="toActiveMenuItem(item)"
              v-for="(item, index) in leftMenuList" :key="index">
              {{ item.titleName }}
            </li>
          </ul>
          <ul class="container-right-ul">
            <li :class="$store.state.activeName === item.activeName ? 'menu-item-active' : 'container-right-li'" @click="toActiveMenuItem(item)"
              v-for="(item, index) in rightMenuList" :key="index">
              {{ item.titleName }}
            </li>
            <li id="bars" @click="dropDownShow = !dropDownShow">
              <i class="fa fa-bars fa-lg"/>
            </li>
          </ul>
        </div>
    
        <!-- 下拉菜单 -->
        <transition name="dropdown-fade-show">
          <div v-show="dropDownShow" class="dropdown">
            <ul class="dropdown-top-ul">
              <li class="dropdown-top-li" v-for="(item, index) in leftMenuList" :key="index" @click="toActiveMenuItem(item)">{{ item.titleName }}</li>
            </ul>
            <ul class="dropdown-bottom-ul">
              <li class="dropdown-bottom-li" v-for="(item, index) in rightMenuList" :key="index" @click="toActiveMenuItem(item)">{{ item.titleName }}</li>
            </ul>
          </div>
        </transition>
    
      </nav>
    </template>
    
    • script 部分
    export default {
      name: 'Header',
      data () {
        return {
          dropDownShow: false, // 控制下拉菜单显示
          leftMenuList: [ // 左侧菜单内容
            { activeName: 'Home', titleName: '主页', activeUrl: '/index' },
            { activeName: 'Infinity', titleName: 'Infinity', activeUrl: '/infinity' },
            { activeName: 'About', titleName: '关于', activeUrl: '/about' }
          ],
          rightMenuList: [ // 右侧菜单内容
            { activeName: 'Support', titleName: '赞助', activeUrl: '/support' }
          ],
          activeName: '' // 导航栏激活名称
        }
      },
      methods: {
        toActiveMenuItem (item) { // 激活导航菜单
          this.activeName = item.titleName
          this.$router.push(item.activeUrl)
          this.dropDownShow = false
        }
      }
    }
    
    • css 部分(这里使用stylus)
    <style lang="stylus" scoped>
    @import "../../assets/stylus/init.stylus" // 初始化导航栏参数
    @import "../../assets/stylus/fade.stylus" // 实现导航栏下拉展示动画效果
    .header
      color $headerTextColor
      background $headerBg
      height $header-height
      width 100%
      position fixed
      top 0
      padding 0 10%
      .container
        width 100%
        height 100%
        .container-left-ul
          float left
          li
            height 100%
            line-height $header-height
            width $header-li-width
            display inline-block
          #icon
            height 30px
            vertical-align middle
            transition transform 0.5s
          #icon:hover
            transform scale(1.5, 1.5) rotate(180deg)
          .container-left-li:hover
            color $menu-active-color
            box-shadow 0px -4px 0px $menu-active-color inset
        .container-right-ul
          float right
          li
            height 100%
            line-height $header-height
            width $header-li-width
            display inline-block
          .container-right-li:hover
            color $menu-active-color
            box-shadow:0px -4px 0px $menu-active-color inset
          #bars > i
            padding 8px 14px
            border 1px $headerTextColor solid
            border-radius 5px
      .dropdown
        border 1px red solid
        width 100%
        background $headerBg
        li
          height 40px
          line-height 40px
        li:hover
          background black
    
    .menu-item-active
      color $menu-active-color
      box-shadow 0px -4px 0px $menu-active-color inset
    
    @media screen and (max-width: 992px) {
      .header {
        padding 0
      }
    }
    @media screen and (max-width: 768px) {
      .container-left-li {
        display none !important
      }
      .container-right-li {
        display none !important
      }
    }
    @media screen and (min-width: 768px) {
      #bars {
        display none
      }
      .dropdown {
        display none
      }
    }
    </style>
    
    • init.stylus
      • params.stylus (参数配置)
      • color.stylus (颜色配置)
    /* params.stylus (参数配置)*/
    // 配置页头的相关参数
    $header-height = 60px
    $header-li-width = 70px
    // 导航栏菜单激活颜色
    $menu-active-color = $googleYellow
    $headerBg = #282C34
    $headerTextColor = #ffffff
    
    /* color.stylus (颜色配置) */
    $googleRed = #f4433c
    $googleBlue = #2d85f0
    $googleGreen = #0aa858
    $googleYellow = #ffbc32
    

    Tips:

    • css变量的引入可以更好的解决主题等相关配置问题

    导航栏实现后,屏幕尺寸缩小后,显示出下拉菜单,此时应给菜单显示和消失添加动画效果,实现el-zoom-in-top类似效果(借助vue的<transition>实现效果)。

    • fade.stylus
    // 下拉菜单出现效果
    .dropdown-fade-show-enter-active
      animation fadeShow .25s
    .dropdown-fade-show-leave-to
      animation fadeShow .25s reverse
    @keyframes fadeShow {
      0% {
        transform-origin 0 top
        transform scaleY(0)
        opacity 0
      }
      100% {
        transform-origin 0 top
        transform scaleY(1)
        opacity 1
      }
    }
    
    结语

    这里只是提供响应式导航布局的设计思路,细节部分仍可优化。

    待优化点:

    • 可以通过设计及css优化相关样式
    • 结合Vuex、浏览器本地缓存解决页面刷新后导航栏状态恢复的问题

    优化代码后续更新,也欢迎大家积极讨论,共同进步!

    相关文章

      网友评论

        本文标题:响应式导航栏实现

        本文链接:https://www.haomeiwen.com/subject/byuldctx.html