这是一款效果很酷又简单实用的 jQuery 和 CSS3 二级下拉菜单特效,该特效在点击触发按钮后,二级下拉菜单会向下滑动覆盖原来的主菜单,关闭后二级下拉菜单又向上滑动回去,二级菜单不占用多余的空间。
这个菜单插件是替代标准的二级下拉菜单的好方法,特别是在你想显示更多的二级子菜单的时候。另外,你可以十分容易的自定义二级下拉菜单的样式,多添加一个搜索框或登录注册表单等等。
HTML结构
该二级下拉菜单的HTML结构有两个主要部分:使用<header>
元素来包裹导航菜单,使用<main>
元素来放置页面的内容。
主导航菜单由两个嵌套的无序列表组成,包裹在一个<nav>
元素中:
<header> <div class="cd-logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div> <nav class="cd-main-nav-wrapper"> <ul class="cd-main-nav"> <li><a href="#0">About</a></li> <!-- other list items here --> <li> <a href="#0" class="cd-subnav-trigger"><span>Categories</span></a> <ul> <li class="go-back"><a href="#0">Menu</a></li> <li><a href="#0">Category 1</a></li> <!-- other list items here --> </ul> </li> </ul> </nav> <a href="#0" class="cd-nav-trigger">Menu<span></span></a> </header> <main class="cd-main-content"> <!-- main content here --> </main>
CSS样式
在小屏幕设备上,主导航菜单位于屏幕的右侧,默认是隐藏的。当用户点击了导航按钮,<main>
元素和<header>
元素会从右向左滑动出来(为其应用nav-is-visible
class)。
当用户点击.cd-subnav-trigger(一个导航小箭头图标)
按钮,二级菜单会从右向左滑动出来覆盖主菜单。
header.nav-is-visible { transform: translateX(-260px); } .cd-main-content.nav-is-visible { transform: translateX(-260px); } .cd-main-nav { position: fixed; top: 0; right: 0; width: 260px; visibility: hidden; } .cd-main-nav.nav-is-visible { visibility: visible; } .cd-main-nav li ul { position: absolute; top: 0; left: 0; width: 100%; transform: translateX(260px); } .cd-main-nav.moves-out > li > a { /* push the navigation items to the left - and lower down opacity - when secondary nav slides in */ transform: translateX(-100%); opacity: 0; } .cd-main-nav.moves-out > li > ul { /* reveal secondary nav */ transform: translateX(0); }
在桌面设备上(分辨率大于1024px),二级菜单位于header的上部(默认隐藏),当点击导航按钮后会从上往下滑动下来,覆盖主菜单。可以为.cd-logo
(网站logo)和.cd-subnav-trigger
(二级菜单触发按钮)设置一个较高的z-index
,这样可以使它们显示在二级菜单之上。
另外,可以为二级菜单设置和.cd-main-nav
(主菜单)相同的padding
,使它们尺寸相同,还可以在列表的最后插入一个.placeholder
元素来制作和.cd-subnav-trigger
(二级菜单触发按钮)相同的空间大小。
@media only screen and (min-width: 1024px) { .cd-main-nav { height: 80px; /* padding left = logo size + logo left position*/ padding: 0 5% 0 calc(5% + 124px); text-align: right; } .cd-main-nav li ul { height: 80px; background-color: #7e4d7e; /* padding left = logo size + logo left position*/ padding: 0 5% 0 calc(5% + 124px); transform: translateY(-80px); transition: transform 0.3s 0.2s; } .cd-main-nav li ul li { opacity: 0; transform: translateY(-20px); transition: transform 0.3s 0s, opacity 0.3s 0s; } .cd-main-nav .placeholder { /* never visible or clickable- it is used to take up the same space as the .cd-subnav-trigger */ display: block; visibility: hidden; opacity: 0; pointer-event: none; } .cd-main-nav.moves-out > li > ul { transition: transform 0.3s; transform: translateY(0); } .cd-main-nav.moves-out > li ul li { opacity: 1; transform: translateY(0); transition: transform 0.3s 0.2s, opacity 0.3s 0.2s; } }
JAVASCRIPT
插件中使用jQuery来为元素添加和移除相应的class。
唯一值得注意的事情是在HTML结构中单行菜单要位于<header>
中。在移动设备上,我们希望导航菜单位于屏幕的侧边上,默认隐藏。这里使用jQuery来在移动设备上将导航菜单移出header之外。
jQuery(document).ready(function($){ //move nav element position according to window width moveNavigation(); $(window).on('resize', function(){ (!window.requestAnimationFrame) ? setTimeout(moveNavigation, 300) : window.requestAnimationFrame(moveNavigation); }); //mobile version - open/close navigation $('.cd-nav-trigger').on('click', function(event){ event.preventDefault(); if($('header').hasClass('nav-is-visible')) $('.moves-out').removeClass('moves-out'); $('header').toggleClass('nav-is-visible'); $('.cd-main-nav').toggleClass('nav-is-visible'); $('.cd-main-content').toggleClass('nav-is-visible'); }); //mobile version - go back to main navigation $('.go-back').on('click', function(event){ event.preventDefault(); $('.cd-main-nav').removeClass('moves-out'); }); //open sub-navigation $('.cd-subnav-trigger').on('click', function(event){ event.preventDefault(); $('.cd-main-nav').toggleClass('moves-out'); }); function moveNavigation(){ var navigation = $('.cd-main-nav-wrapper'); var screenSize = checkWindowWidth(); if ( screenSize ) { //desktop screen - insert navigation inside header element navigation.detach(); navigation.insertBefore('.cd-nav-trigger'); } else { //mobile screen - insert navigation after .cd-main-content element navigation.detach(); navigation.insertAfter('.cd-main-content'); } } function checkWindowWidth() { var mq = window.getComputedStyle(document.querySelector('header'), '::before').getPropertyValue('content').replace(/"/g, ''); return ( mq == 'mobile' ) ? false : true; } });