響應式導航欄實現

前言

最近想實現定製化的響應式頂部導航欄,即支持主流設備的正常訪問(Phone、Pad、PC),並根據屏幕比例實現對應的顯示效果。

曾嘗試使用以下方式

  • Element UI提供的導航欄(樣式單調,沒有響應式效果)
  • BootStrap 提供的導航欄(有響應式效果,需額外引入依賴包,且定製效果修改較繁瑣)

由此,產生自己動手實現響應式頂部導航欄的想法,並應當擁有以下特點:

  • 實現方式較爲簡單,無需引入額外依賴庫(或較少)
  • 可以實現動態添加功能菜單,個性化定製較爲簡便
  • 實現對多種設備的兼容性,保證顯示效果較爲美觀
效果展示
  • Tips:若 gif 圖片未加載出,請嘗試刷新。
提前準備
  • 掌握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、瀏覽器本地緩存解決頁面刷新後導航欄狀態恢復的問題

優化代碼後續更新,也歡迎大家積極討論,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章