【翻譯】移動端友好的響應式導航欄教程

如下是譯文:

今天我來教你們設計一個色彩絢麗且移動端友好的響應式導航欄。這個導航欄的靈感源自一款叫作「無主之地(Borderlands)」遊戲中的一個叫作Maliwan武器生產商商標所採用的顏色集。導航欄會自動根據瀏覽器窗口的大小調整佈局格式:在PC寬度下呈現爲一行按鈕,在平板寬度下呈現爲三行按鈕,而在移動端則變成了一個菜單欄按鈕鏈接,點擊能夠顯示和隱藏整個導航欄。爲了使這個導航欄作到真正地移動端友好,咱們將採用圖標字體來做爲導航欄圖表,這樣的話,當界面放大縮小的時候,圖標也會自動調整分辨率,避免鋸齒(像素太高)和模糊(像素太低)。javascript

輸入圖片說明

###準備工做:選擇圖標字體html

圖標字體的製做不是一項簡單的任務,不過咱們徹底沒有必要給本身找這個麻煩。像IcoMoon,或者FontAwesome這樣的插件已經爲咱們準備好了現成的圖標以供選擇,咱們也可使用這些工具快速創造本身須要的圖標字體。使用圖標文字的好處是這些圖標像Web字體同樣,咱們能夠輕鬆地改變它的顏色和大小,而不會出現相似圖片放大以後模糊的情形。所以咱們就免得爲移動端再準備不一樣分辨率大小的同個圖片了。java

首先咱們須要製做本身所須要的圖標按鈕(固然你也能夠選擇插件已經制做好的圖標文字)。我主要使用Adobe Illustrator來製做矢量圖,固然其餘相似的矢量圖製做工具也能夠完成這個任務。咱們首先須要在矢量圖製做工具中作好所需的按鈕,而後將它們導出爲SVG格式的文件。爲了確保在全部瀏覽器中顯示正常,咱們必須把設計元素時的不一樣線條組合成一個完整的對象,而後將每個圖標導入到IcoMoon App Tool中:web

輸入圖片說明

導入好這些元素以後,點擊右下角下載旁邊的設置按鈕,咱們能夠對生成的字體進行詳細的配置,包括字體編碼格式,給每一個字體分配對應的字符等。固然大多數狀況下默認的配置是可以知足須要的,這時候咱們只要直接點擊下載按鈕,就能夠得到整個字體包和相關文件了。瀏覽器

輸入圖片說明

得到圖標字體以後,第一件事固然是放到咱們的項目中查看效果。IcoMoon下載包中提供了必要的4類字體文件資源,對應不一樣的瀏覽器,同時還有響應的CSS樣式。更方便的是它還提供了一個demo.html文件,咱們能夠直接在其中看到自定義圖標的效果。工具

###按鈕的HTML實現佈局

<nav  id="menu" class="nav">	
    <ul>
        <li>
            <a  href="#" title="">
                <span  class="icon"> <i aria-hidden="true"  class="icon-home"></i></span><span>Home</span>
            </a>
        </li>
        <li>		
            <a href="#" title=""><span class="icon"> <i aria-hidden="true" class="icon-services"></i></span><span>Services</span></a>	
        </li>	
        <li>
	    <a  href="#" title=""><span  class="icon"><i  aria-hidden="true" class="icon-portfolio"></i></span><span>Portfolio</span></a>
	</li>
	<li>
	    <a  href="#" title=""><span  class="icon"><i  aria-hidden="true" class="icon-blog"></i></span><span>Blog</span></a>	
	</li>
	<li>
	    <a  href="#" title=""><span  class="icon"><i  aria-hidden="true" class="icon-team"></i></span><span>The  team</span></a>	
	</li>
	<li>
	    <a  href="#" title=""><span  class="icon"><i  aria-hidden="true" class="icon-contact"></i></span><span>Contact</span></a>
        </li>
    </ul>
</nav>

在網頁中使用圖標字體的方法很是簡單,只須要在一個i標籤或者span標籤元素中增長名叫「icon-iconname」的class屬性就能夠了。這裏要提一下,咱們通常會在body標籤中添加no-js這個class屬性,當使用modernizr時,若是瀏覽器沒有禁用javascript,那麼modernizr會自動把no-js改爲js。這樣作的好處是,假如瀏覽器禁用了腳本,咱們能夠經過這個class屬性讓導航欄默認處於展開的狀態。Modernizr的功能十分強大,咱們還能夠用它來檢測移動設備對觸屏的支持如何,並作出應對策略。字體

###CSS和Javascript的實現動畫

/* 全局CSS配置,將在全部設備下生效 */

.nav ul {
	max-width: 1240px;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 1.5em;
	font-weight: 300;
}

.nav li span {
	display: block;
}

.nav a {
	display: block;
	color: rgba(249, 249, 249, .9);
	text-decoration: none;
	transition: color .5s, background .5s, height .5s;
}

.nav i{
	/* 確保圖標文字在谷歌瀏覽器下顯示清晰 */
	transform: translate3d(0, 0, 0);
}

/* 去掉webkit內核下點擊按鈕出現的藍色背景 */

a, button {
	-webkit-tap-highlight-color: rgba(0,0,0,0);
}

咱們先給按鈕添加一個鼠標懸停效果,當鼠標懸停在按鈕上方時,這個按鈕的變得半透明。this

/* PC端鼠標懸停在按鈕上方時的特效 */

.no-touch .nav ul:hover a {
	color: rgba(249, 249, 249, .5);
}

.no-touch .nav ul:hover a:hover {
	color: rgba(249, 249, 249, 0.99);
}

下面咱們介紹一個方法,能夠在不用給每一個li元素添加不一樣class屬性的狀況下,分別給他們賦予不一樣的顯示效果,這就是li:nth-child。咱們經過這種方法給列表中的每個按鈕賦予不一樣的顏色。

.nav li:nth-child(6n+1) {
	background: rgb(208, 101, 3);
}

.nav li:nth-child(6n+2) {
	background: rgb(233, 147, 26);
}

.nav li:nth-child(6n+3) {
	background: rgb(22, 145, 190);
}

.nav li:nth-child(6n+4) {
	background: rgb(22, 107, 162);
}

.nav li:nth-child(6n+5) {
	background: rgb(27, 54, 71);
}

.nav li:nth-child(6n+6) {
	background: rgb(21, 40, 54);
}

接下來介紹一下響應式界面設計基礎中的基礎,那就是@media的應用。這裏順帶簡單介紹一下em這個單位,em指的是相對於body全局字體大小,若是body全局字體大小是15px,那麼50em就等於800px。這樣作的好處是當body字體調整時,整個頁面的大小均可以跟着動態變化,有利於移動端的適配。

@media (min-width: 50em) {

	/* 當屏幕的寬度小於50em時,將水平的導航欄轉換成垂直的列表格式 */
	.nav li {
		float: left;
		width: 16.66666666666667%;
		text-align: center;
		transition: border .5s;
	}

	.nav a {
		display: block;
		width: auto;
	}

咱們給每一個按鈕添加選中點擊時彩色的底邊。加上focus和active這兩個選項,這樣當移動設備選中和使用鍵盤選中的時候也能夠看到效果。

/* 懸浮、選中和點擊的狀況下出現彩色的底邊 */

	.no-touch .nav li:nth-child(6n+1) a:hover,
	.no-touch .nav li:nth-child(6n+1) a:active,
	.no-touch .nav li:nth-child(6n+1) a:focus {
		border-bottom: 4px solid rgb(174, 78, 1);
	}

	.no-touch .nav li:nth-child(6n+2) a:hover,
	.no-touch .nav li:nth-child(6n+2) a:active,
	.no-touch .nav li:nth-child(6n+2) a:focus {
		border-bottom: 4px solid rgb(191, 117, 20);
	}

	.no-touch .nav li:nth-child(6n+3) a:hover,
	.no-touch .nav li:nth-child(6n+3) a:active,
	.no-touch .nav li:nth-child(6n+3) a:focus {
		border-bottom: 4px solid rgb(12, 110, 149);
	}

	.no-touch .nav li:nth-child(6n+4) a:hover,
	.no-touch .nav li:nth-child(6n+4) a:active,
	.no-touch .nav li:nth-child(6n+4) a:focus {
		border-bottom: 4px solid rgb(10, 75, 117);
	}

	.no-touch .nav li:nth-child(6n+5) a:hover,
	.no-touch .nav li:nth-child(6n+5) a:active,
	.no-touch .nav li:nth-child(6n+5) a:focus {
		border-bottom: 4px solid rgb(16, 34, 44);
	}

	.no-touch .nav li:nth-child(6n+6) a:hover,
	.no-touch .nav li:nth-child(6n+6) a:active,
	.no-touch .nav li:nth-child(6n+6) a:focus {
		border-bottom: 4px solid rgb(9, 18, 25);
	}

調整圖標的相對位置和漸變效果:

/* 調整圖標的位置 */
	.icon {
		padding-top: 1.4em;
	}

	.icon + span {
		margin-top: 2.1em;
		transition: margin .5s;
	}

當鼠標懸停在按鈕上方時,改變元素的高度,產生動畫效果:

/* 鼠標懸停的時候出現高度變化動畫 */
	.nav a {
		height: 9em;
	}

	.no-touch .nav a:hover ,
	.no-touch .nav a:active ,
	.no-touch .nav a:focus {
		height: 10em;
	}	

	/* 這裏讓文字跟着整個元素的高度變化而變化 */
	.no-touch .nav a:hover .icon + span {
		margin-top: 3.2em;
		transition: margin .5s;
	}

調整按鈕的位置,並設計CSS漸變效果:

/* 調整按鈕的位置,並設計CSS漸變效果 */
	.nav i {
		position: relative;
		display: inline-block;
		margin: 0 auto;
		padding: 0.4em;
		border-radius: 50%;
		font-size: 1.8em;
		box-shadow: 0 0 0 0.8em transparent;
		background: rgba(255,255,255,0.1);
		transform: translate3d(0, 0, 0);
		transition: box-shadow .6s ease-in-out;
	}

爲了得到咱們想要的效果,咱們改變盒模型的陰影,並將它的大小從0.8em漸變到0,將它的顏色從透明轉變到一個相對不透明的狀態。

/* 盒模型陰影動畫效果 */
	.no-touch .nav a:hover i,
	.no-touch .nav a:active i,
	.no-touch .nav a:focus i {		
		box-shadow: 0 0 0px 0px rgba(255,255,255,0.2);
		transition: box-shadow .4s ease-in-out;
	}
		
}

稍微調整一下屏幕寬度在800-980px之間時的位置:

@media (min-width: 50em) and (max-width: 61.250em) {

	/* Size and font adjustments to make it fit better */
	.nav ul {
		font-size: 1.2em;
	}

}

這樣算是完成了PC端的設計了,固然如今不少平板甚至手機的分辨率都已經達到1024px以上了,PC和移動端的界限愈來愈模糊。

/* 設計800px如下的屏幕布局樣式和特效 */

@media (max-width: 49.938em) {		
	
	/* 多排按鈕不能用改變border的特效,咱們換成改變背景透明度的特效 */
	.no-touch .nav ul li:nth-child(6n+1) a:hover,
	.no-touch .nav ul li:nth-child(6n+1) a:active,
	.no-touch .nav ul li:nth-child(6n+1) a:focus {
		background: rgb(227, 119, 20);
	}

	.no-touch .nav li:nth-child(6n+2) a:hover,
	.no-touch .nav li:nth-child(6n+2) a:active,
	.no-touch .nav li:nth-child(6n+2) a:focus {
		background: rgb(245, 160, 41);
	}

	.no-touch .nav li:nth-child(6n+3) a:hover,
	.no-touch .nav li:nth-child(6n+3) a:active,
	.no-touch .nav li:nth-child(6n+3) a:focus {
		background: rgb(44, 168, 219);
	}

	.no-touch .nav li:nth-child(6n+4) a:hover,
	.no-touch .nav li:nth-child(6n+4) a:active,
	.no-touch .nav li:nth-child(6n+4) a:focus {
		background: rgb(31, 120, 176);
	}

	.no-touch .nav li:nth-child(6n+5) a:hover,
	.no-touch .nav li:nth-child(6n+5) a:active,
	.no-touch .nav li:nth-child(6n+5) a:focus {
		background: rgb(39, 70, 90);
	}

	.no-touch .nav li:nth-child(6n+6) a:hover,
	.no-touch .nav li:nth-child(6n+6) a:active,
	.no-touch .nav li:nth-child(6n+6) a:focus {
		background: rgb(32, 54, 68);
	}

	.nav ul li {
		transition: background 0.5s;
	}	

}

屏幕大小在520px到799px之間時,讓導航欄按照2X3的形式進行佈局。

/* 導航欄按照2X3的形式佈局 */

@media (min-width: 32.5em) and (max-width: 49.938em) {
	
	/* 用左浮動的方法實現兩個按鈕並排 */
	.nav li {
		display: block;
		float: left;
		width: 50%;
	}
	
	/* 加入padding使得元素按鈕看上去好看些 */
	.nav a {
		padding: 0.8em;		
	}

	/* 用inline-block可讓按鈕在左邊,文字在右邊 */
	.nav li span, 
	.nav li span.icon {
		display: inline-block;
	}

	.nav li span.icon {
		width: 50%;
	}

	.nav li .icon + span {
		font-size: 1em;
	}

	.icon + span {
		position: relative;
		top: -0.2em;
	}

PC端的元素大小變化沒法在平板佈局下實現,所以咱們簡化動畫效果。

/* 在平板佈局的情形下,咱們以一種更爲保守的方式設計動畫,只改變一下border的大小 */
	.nav li i {
		display: inline-block;
		padding: 8% 9%;
		border: 4px solid transparent;
		border-radius: 50%;
		font-size: 1.5em;
		background: rgba(255,255,255,0.1);
		transition: border .5s;
	}

	/* border顏色漸變效果 */
	.no-touch .nav li:hover i,
	.no-touch .nav li:active i,
	.no-touch .nav li:focus i {
		border: 4px solid rgba(255,255,255,0.1);
	}

}

平板佈局下,調整文字的大小和寬度

/* 平板佈局下,調整文字的大小和寬度 */
@media (min-width: 32.5em) and (max-width: 38.688em) {
	
	.nav li span.icon {
		width: 50%;
	}

	.nav li .icon + span {
		font-size: 0.9em;
	}
}

對於更小的移動設備,咱們能夠隱藏整個導航欄,而後顯示一個導航按鈕,這樣經過點擊導航按鈕來顯示和隱藏導航欄。這個功能可能須要經過Javascript來實現。(譯者:更簡單的途徑是使用jQuery的toggleClass方法實現)。

//  切換class屬性的方法
var changeClass = function (r,className1,className2) {
	var regex = new RegExp("(?:^|\\s+)" + className1 + "(?:\\s+|$)");
	if( regex.test(r.className) ) {
		r.className = r.className.replace(regex,' '+className2+' ');
    }
    else{
		r.className = r.className.replace(new RegExp("(?:^|\\s+)" + className2 + "(?:\\s+|$)"),' '+className1+' ');
    }
    return r.className;
};	

//  寫入菜單欄按鈕
var menuElements = document.getElementById('menu');
menuElements.insertAdjacentHTML('afterBegin','<button type="button" id="menutoggle" class="navtoogle" aria-hidden="true"><i aria-hidden="true" class="icon-menu"> </i> Menu</button>');

//  點擊菜單欄按鈕時切換class屬性
document.getElementById('menutoggle').onclick = function() {
	changeClass(this, 'navtoogle active', 'navtoogle');
}

// 點擊文檔其餘位置時自動隱藏導航欄
document.onclick = function(e) {
	var mobileButton = document.getElementById('menutoggle'),
		buttonStyle =  mobileButton.currentStyle ? mobileButton.currentStyle.display : getComputedStyle(mobileButton, null).display;

	if(buttonStyle === 'block' && e.target !== mobileButton && new RegExp(' ' + 'active' + ' ').test(' ' + mobileButton.className + ' ')) {
		changeClass(mobileButton, 'navtoogle active', 'navtoogle');
	}
}

這一段採用Javascript原生的方法來進行class屬性的切換和點擊動做進行DOM文檔操做的實現。當按鈕點擊的時候,首先判斷按鈕帶有什麼屬性,而後改爲另外一個屬性,這樣就實現了class屬性的切換。實現了導航欄的隱藏與顯示以後,咱們接着設置一下樣式。

/* 導航欄按鈕的樣式,默認隱藏 */
.nav .navtoogle{
	display: none;	
	width: 100%;
	padding: 0.5em 0.5em 0.8em;
	font-family: 'Lato',Calibri,Arial,sans-serif;
	font-weight: normal;
	text-align: left;
	color: rgb(7, 16, 15);
	font-size: 1.2em;
	background: none;	
	border: none;
	border-bottom: 4px solid rgb(221, 221, 221);
	cursor: pointer;
}

.navtoogle i{
	z-index:-1;
}

.icon-menu {
	position: relative;
	top: 3px;
	line-height: 0;
	font-size: 1.6em;
}

若是檢測到屏幕小於519px,則顯示這個導航欄按鈕

@media (max-width: 32.438em) {

	/* 顯示導航欄按鈕 */
	.nav .navtoogle{
		margin: 0;
		display: block;
	}

接下來咱們實現導航欄的顯示和隱藏動畫。咱們經過元素的高度控制顯示和隱藏。特別要提出,若是檢測到頁面禁用了腳本,咱們應該讓導航欄默認是顯示的。

/* 若是禁用了腳本,那麼導航欄老是顯示的。 */
	.no-js .nav ul {
		max-height: 30em;
		overflow: hidden;
	}

	/* 若是腳本是可生效的,那麼咱們控制高度爲0,隱藏之 */
	.js .nav ul {
		max-height: 0em;
		overflow: hidden;
	}
	
	/* class的active屬性激活以後,給max-height一個動畫效果,就可以實現導航欄向下滾動出現的特效 */
	.js .nav .active + ul {		
		max-height: 30em;
		overflow: hidden;
		transition: max-height .4s;
	}

而後給這個小屏導航欄設置樣式

/* 小屏幕導航欄樣式設置 */
	
	.nav li span {
		display: inline-block;
		height: 100%;
	}

	.nav a {
		padding: 0.5em;		
	}
	
	.icon + span {
		margin-left: 1em;
		font-size: 0.8em;
	}

左側增長一個border效果(設計師須要多多關注這些細節:))

/* 左側增長一個border效果 */
	.nav li:nth-child(6n+1) {
		border-left: 8px solid rgb(174, 78, 1);
	}

	.nav li:nth-child(6n+2) {
		border-left: 8px solid rgb(191, 117, 20);
	}

	.nav li:nth-child(6n+3) {
		border-left: 8px solid rgb(13, 111, 150);
	}

	.nav li:nth-child(6n+4) {
		border-left: 8px solid rgb(10, 75, 117);
	}

	.nav li:nth-child(6n+5) {
		border-left: 8px solid rgb(16, 34, 44);
	}

	.nav li:nth-child(6n+6) {
		border-left: 8px solid rgb(9, 18, 25);
	}

接下來不少工做可能都是在調整移動端設備的效果上面了。咱們使用Modernizr這個工具能夠很方便的幫咱們識別移動設備的兼容性,這樣咱們能夠經過class屬性來爲特性支持或者特性不支持的設備進行調整。好比這個導航欄的按鈕在PC下面顯示正常,可是一樣的樣式在手機設備上可能顯得過小,很差按。這時候咱們這樣能夠進行樣式的調整。

/* 讓導航欄在觸屏設備下看起來更溫馨一些 */
	.touch .nav a {
		padding: 0.8em;
	}
}

這樣咱們就完成了一個至關絢麗的CSS3導航欄的製做,怎麼樣,是否是很簡單啊?

相關文章
相關標籤/搜索