来源:GBin1.com
经过长时间研究移动响应布局,我花了很大功夫研究不同的UI设计。在页面上的主要亮点往往是网站主导航。用户需要快速访问到内容页面,而且这一点是最基本的,无论是在完整的显示器或较小的移动响应屏幕。
在本教程中,我要演示如何结合CSS3 media queries和jQuery管理滑动导航菜单。链接出现在前端,但下降为一个隐藏的菜单,调整后的大小低于600px。同时将出现一个小的下拉菜单,图标会切换打开和关闭命令。
顶部区域包含文件的一小部分,我们用来创建效果。我从由谷歌托管的最新jQuery库中复制了常规样式表,所有自定义JS函数被存储在外部文件命名为menu.js。
<!doctype html> <html lang="en-US"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>Responsive Sliding Navigation Demo</title> <meta name="author" content="Jake Rocheleau"> <link rel="shortcut icon" href="http://designshack.net/favicon.ico"> <link rel="icon" href="http://designshack.net/favicon.ico"> <link rel="stylesheet" type="text/css" media="all" href="styles.css"> <link rel="stylesheet" type="text/css" media="all" href="http://fonts.googleapis.com/css?family=Boogaloo"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript" language="javascript" charset="utf-8" src="menu.js"></script> </head>
大部分页面标记不是很重要,除了标题区域。我试图把一切都设定为固定的高度,但header不能用固定CSS属性,否则控制打开和关闭时页面将不会扩展滑动菜单。所以标题和导航链接在CSS中用line-height设置。
<header id="topnav">
<nav>
<ul>
<li><a href="#" class="sel">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Get in Touch</a></li>
</ul>
</nav>
<a href="#" id="navbtn">Nav Menu</a>
<h1><a href="#">Designee</a></h1>
</header><!-- @end #topnav -->
页h1标题最适合最后一个元素,所以header将始终保持恒定高度。标题旁边有一个锚链接 ID #navbtn,包含了滑动菜单链接图标。当宽度低于一定阈值,这个CSS链接才会显示。
通常情况下我不会用到jQuery。切换菜单的唯一问题是,我们无法在CSS中达到效果。jQuery的方法将适用于内联CSS样式,并覆盖默认样式。所以解决方案是使用CSS定位元素,并恰当使用JavaScript完成动画效果。
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; outline: none; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; -ms-text-size-adjust: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { height: 101%; } body { background: #f8f8f8 url('images/bg.png'); /* BG Neutral http://subtlepatterns.com/ps-neutral/ */ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 62.5%; line-height: 1; color: #343434; padding-bottom: 55px; } ::selection { background: #b9e9b9; color: #555; } ::-moz-selection { background: #b9e9b9; color: #555; } ::-webkit-selection { background: #b9e9b9; color: #555; } a { color: #6992c0; } a:hover { color: #77a4dc; } h2 { font-size: 2.9em; line-height: 1.4em; color: #626262; margin-bottom: 22px; } p { font-size: 1.6em; line-height: 1.7em; color: #777; margin-bottom: 15px; } #w { display: block; max-width: 900px; min-width: 300px; margin: 0 auto; } #content { margin: 0 1em; background: #fff; padding: 0 10px; } #pagebody { padding: 15px 25px; }
我的默认CSS浏览器重置包括一组自定义代码的页面排版,而且body背景标题是脱离于Subtle模式中立的PS。我不得不把包装 容器和主题容器拆分成2个div,因为要保证页面左右两侧填充,不让页面宽度变为100%。在margin: 0 auto;属性上添加margin值,则会导致失去正中定位。
/* navigation bar */ #topnav { display: block; width: 100%; position: relative; } #topnav #navbtn { display: none; float: right; top: 0; width: 20px; height: 70px; background: url('images/menu.png') center no-repeat; text-indent: -99999px; overflow: hidden; } #topnav nav { position: absolute; top: 0; right: -10px; } #topnav nav ul { list-style: none; } #topnav nav ul li { display: block; float: left; font-size: 1.4em; margin-right: 4px; } #topnav nav ul li a { display: block; text-decoration: none; line-height: 70px; color: #8ea188; font-weight: bold; padding: 0 10px; border-bottom: 2px solid #fff; } #topnav nav ul li a:hover { color: #6f8767; background: #ddecd9; border-bottom-color: #bdd8b5; }
通过编辑内部<nav>元素,可以保留对标题栏的控制。通过设置绝对位置我们可以控制导航链接离标题的距离。注意#navbtn是如何保持隐藏的,直到调整大小低于560px,才会显示。除此之外还需设定高度、宽度和定位。
如果浏览器窗口小于560px,我只需做一点小小的改动。560并不是多么神奇的数字,而是默认导航区与logo文本之间恰好比较适合的距离。也是隐藏导航菜单和切换显示图标的临界值。
/* responsive styles */ @media screen and (max-width: 560px) { h2 { font-size: 2.2em; } p { font-size: 1.45em; line-height: 1.55em; } #topnav { height: auto; } #topnav nav { display: none; position: static; width: 100%; top: auto; right: auto; } #topnav nav ul li { float: none; margin: 0; } #topnav nav ul li a { display: block; width: 100%; line-height: 1.4em; border: 0; padding: 6px 9px; background: #dcf4dc; } #topnav nav ul li a:hover { background: #cbdcc5; } #topnav nav ul li a.sel { color: #6f8767; background: #cbdcc5; } #topnav #navbtn { display: block; } }
这也意味着从导航元素除去绝对定位,这样使它呈现为一个静态块。点击屏幕时,导航锚链接会以100%的宽度行呈现以达到最快访问。此外,内部页面headers+paragraphs将被调小,匹配上合适的行高值。
menu.js代码最后一点也可以直接包含到HTML文档中。但是由于我们需要处理不只一个切换方法,把标记从动态效果分离出来比较清爽而且高效率。我会把文件分成几段,以便阅读。
$(function(){ var nb = $('#navbtn'); var n = $('#topnav nav'); $(window).on('resize', function(){ if(nb.is(':hidden') && n.is(':hidden') && $(window).width() > 569) { // if the navigation menu and nav button are both hidden, // then the responsive nav is closed and the nav menu is still hidden. // just display the nav menu which will auto-hide at <560px width and remove class. $('#topnav nav').show().addClass('keep-nav-closed'); } });
第一大块可以说是最令人困惑的。需要处理微小的错误,来调整浏览器响应与不响应的问题,而不能影响到智能手机。我们把一个事件关联到窗口检查.on() resize。两个不同逻辑语句核对变量目标header nav元件,与之相随的是导航菜单切换链路。
当浏览器可响应状态,用户切换菜单开/关时,将附加内联样式属性。这将超过任何写在样式表中的优先级,而且当菜单打开或者关闭之后也会是个问题。nav有一个永久的显示display: none;甚至当大小被调整到大于560px。
这就是第二个if{}语句检查的目的。当导航和菜单按钮都隐藏,布局响应,用户打开/关闭菜单,然后调整大小恢复到常规视图。所以我们只需要再次显示导航。但有一个问题,jQuery中show()方法也将被附加风格内嵌,意味着调整大小时响应的导航菜单保持永久开放。为了解决这个问题,我添加了一个类.keep-nav-closed.如果关闭导航后调整更大,类就会得到补充。如果保持开放,响应时则一直开放直到调整更大然后再次回落。
if($(this).width() < 570 && n.hasClass('keep-nav-closed')) { // if the nav menu and nav button are both visible, // then the responsive nav transitioned from open to non-responsive, then back again. // re-hide the nav menu and remove the hidden class $('#topnav nav').hide().removeAttr('class'); }
另外一个if{}语句应该有意义,这就是为什么我们要检查这个类。只出现在第二次调整之后,导航打开,然后我们知道当调整回到响应阈 值内它会保持关闭。这是一个奇怪的错误,除了完全移除属性(仍然会导致问题)以外,我还没有找到较微小或更快的解决方案,用于处理内嵌jQuery风格。 所以现在让我们继续来看最后一段JavaScript代码。
$('#topnav nav a,#topnav h1 a,#btmnav nav a').on('click', function(e){ e.preventDefault(); // stop all hash(#) anchor links from loading }); $('#navbtn').on('click', function(e){ e.preventDefault(); $("#topnav nav").slideToggle(350); });
两个事件处理程序检查点击事件针对不同的目标。首先是锁定到所有不同的锚链接标题导航和页脚节。href值是hash symbols (#)我将它们设置为不加载任何东西。与之类似的是点击导航切换,因为我们不希望加载hash到页面URL。响应隐藏导航菜单将在350毫秒内切换打开和 关闭,完全无视href值。
via 极客标签