From: http://tech.mozilla.com.tw/posts/4759/%E4%B9%9D%E5%80%8B%E9%81%A9%E6%87%89%E6%80%A7%E8%A8%AD%E8%A8%88%E5%B0%8F%E6%92%87%E6%AD%A5%EF%BC%8C%E6%8A%8A%E7%B6%B2%E7%AB%99%E6%89%93%E9%80%A0%E6%88%90%E8%AE%8A%E5%BD%A2%E9%87%91%E5%89%9B
----------------------------------------------------
繼之前蓋索林大師的一個打十個系列文章,介紹了 Gaia WebApp 支援多種設備的技巧,本系列文章將深入介紹一些網頁適應性設計相關的通用工具及方法。如果你還不知道什麼是適應性設計,底下有簡潔的介紹。
什麼是適應性設計?它適合我嗎?
適應性設計 (Responsive Web Design,簡稱 RWD,亦有人譯作「自適應網頁設計」、「響應式網頁設計」) 簡單來說,就是試圖使用同一份 HTML、CSS、Javascript,讓網頁內容可以自動適應不同的螢幕大小,無論是在電腦桌面上、平板、或手機上。讓使用者在小螢幕上瀏覽網站時不需要縮放、水平捲動的操作,用單指就可以輕鬆瀏覽。
如果你希望你的網頁能適應不同的裝置,那麼無論你要採用漸進加強 (progressive enhancement) 或是優雅降級 (gracefully degradation) 的作法,本文介紹的小技巧都會對你有所幫助。但在採用這些技巧之前,為了事半功倍,有幾點必須先思考清楚的:
一、想清楚你的核心內容以及設計
當螢幕變小時,能用的畫面空間不足,適應性設計的基本策略就是把內容往下擠、縮小或隱藏次要的元素功能。因此預先想好內容的排列順序,就能確保內容往下擠的時候最重要的內容留在最上面。一方面也要將可能被縮小、隱藏的元素和主要內容儘量切割開來,以免在調整樣式時連帶影響主要內容。
二、確定大部分的 HTML 元素可重用
適應性設計的重點在於「重用」,因此在實務上會儘量沿用保留現有的功能和內容。若要讓部分的元素根據螢幕尺寸而隱藏、顯現那沒問題,但如果你希望在行動版及桌面版網頁分別提供截然不同的內容或功能,那麼這裡有一些技巧可能就不適用。
三、是否了解且確實實踐 DRY 原則
要支援不同螢幕大小,同時又不需要另外從頭寫一份 HTML/CSS/Javascript,意味著同一份 CSS/Javascript 檔案裡包含了不同解析度相關的邏輯和設定值。因此在開發過程中時時保持程式碼的可維護性很重要。DRY (Don’t Repeat Yourself) 原則是一個基本的參考原則,用意在防止重覆的程式碼,因為同樣的程式碼通常有很大的機率在變更需求(變更螢幕大小)時會需要一併更改,重覆的程式愈多,要一起更改的地方就愈多,除了徒增麻煩,也更容易遺漏或出錯。因此對任何重覆出現的程式邏輯/設定保持警覺(當你發現自己正在複製貼上自己的 code 時就要小心了…),若發現重覆的程式碼未來可能有一併變更的需求,則隨時重構 (Refactoring) 以避免這樣的重覆出現。如此一來在實作適應性設計時會輕鬆許多。當然如果是不認同 DRY 原則,或是想多訓練打字以及抓蟲能力的人就另當別論啦。
活用原本就支援適應性設計的元素及 CSS 屬性來排版
很多人可能會把適應性設計和 CSS 的 media queries 畫上等號,但事實上 media queries 只是幫助我們解決部分的 CSS 問題,要做好網站的適應性設計,還需要結合各式不同的工具和方法,在本文中我們就先從最簡單-可能是你壓根都沒想到-而 CSS 本來就具備的基本排版功能開始。
撇步一:讓圖片維持原比例縮放-使用 img 標籤或 CSS 背景屬性
螢幕大小不同的情況下,網頁中的圖片常需要進行縮放以符合螢幕寬度,想讓圖片在縮放時不致於變形,基本上有兩種作法。
第一種:使用 img 標籤
img 標籤的好處是可以透過 CSS 設定很容易達成原比例縮放的效果,但壞處是無法透過 CSS media queries 針對不同解析度指定圖片。要設定原比例縮放的 img 很容易,只需要width 、 height 兩個屬性,其中一個數值(通常是 width )設定百分比來作為縮放依據,另一個數值(通常是 height )設定為 auto 即可,假設有一個 Firefox 圖案的 img 標籤 id 為 fx:
如此一來圖片就會跟隨上層元素的寬度等比縮放。若不想讓圖片過度放大而糊掉,只要把 width 改成 max-width 即可:
要注意的是此時 width 屬性不需設定(或設定為 auto ),才能讓圖片維持不超過原始大小的寬高。而 max-width: 100% 的作用是當外層元素寬度縮到小於圖片時,讓圖片自動縮小。
第二種:使用 CSS background 屬性
使用 CSS background 的好處如前面提到的,可彌補 img 無法針對螢幕大小指定合適圖片的缺點。但它並不是沒有缺點,比起 img 標籤,CSS background 要做到等比例縮放不免面臨圖片被裁邊的命運,在設計圖素時要稍微注意邊界的預留空間。背景圖等比縮放的原理和 img 差不多,也是需要一個 auto 和一個百分比值,透過 background-size 屬性來設定,假設一個空的標籤 <div id="join></div> :
背景圖的設定稍多了些, width 、 height 兩個屬性必須明確設定不能為 auto ,因為背景圖不像 img 標籤,無法以圖片本身的寬高撐開元素寬高。 background-size 內兩個值分別代表背景圖的寬高,而 background-position 的兩個數值則分別指定背景圖片的水平及垂直位置, 50% (或 center )表示置中。
以下是兩種作法的實際展示:
可以看到 CSS 背景的作法在元素比例不符合時邊緣會被裁切到,另外它也無法自動偵測圖片的原始大小而設定放大上限,設定放大上限必須明確指定像素值,如 max-width: 300px ,這是稍嫌麻煩的地方。
padding 讓圖片超出邊界?試試 box-sizing 屬性
有時候想透過 padding 屬性在圖片周圍留下固定像素寬度的空間,卻發現設定後整個版面爆開來。這是因為 box-sizing 屬性的預設值為 content-box ,例如寬度為 100% 的元素, padding 並不算在這 100% 內,而是會額外增加寬度,這時可使用 box-sizing:padding-box ,一行 CSS 解決你的煩惱!以下範例展示 box-sizing 的不同屬性設定:
撇步二:讓內容區塊自動往下排列-使用 inline-block 或 float
當網頁中的區塊被設計成固定大小,不想讓它隨著螢幕變小而減少寬度時,常見辦法就是讓超出邊界的區塊換行往下擠,這時你可以選擇使用 inline-block 或 float ,兩種作法能達到的效果幾乎一樣,要選擇哪一種單看你的內容需要什麼樣的特性:
想讓區塊浮在其它元素上-選 float 吧
只要在元素區塊上指定 float: left 或者 float: right ,所有同樣為 float 的區塊就會浮起來並照順序排排站,若寬度不足則自動換行往下跑。如果不希望你的浮動區塊跟其它區塊重疊,也可以使用常見的 clearfix,達到跟 inline-block 類似的效果。
假設 #float 元素內有很多設定了 float 的元素區塊,上面這段 CSS 在 #float 元素內的最後加上了一個隱形的虛擬元素 (pseudo element),在虛擬元素上指定 clear: both 即可消除浮動狀態,讓接下來的元素不會和 float 區塊重疊,同時也撐開 #float 元素的高度。
想要簡單的置中排列-選 inline-block
只要在元素上指定 display: inline-block ,元素就會像文字一樣一個接著一個照順序排列並自動換行,且可透過外層元素指定 text-align 屬性使元素靠左、靠右、或置中對齊。inline-block 要特別注意的一點是,它的 vertical-align 屬性要記得設定一致,否則很容易出現高低參差不齊的狀況。
靠右對齊時的順序-dochi?
兩種作法有另一個差異點-靠右對齊時的順序不同,因為 inline-block 的行為較像文字,基於文字預設的 ltr (由左至右)排列,所以就算設定 text-align: right ,順序還是由左至右,當然也可以透過 direction: rtl 屬性改變順序,但要小心元素內的文字也會變成由右至左的排列。
以下是兩種作法的展示:
撇步三:置中排列的小秘技-神奇的 margin: auto 屬性
想要讓區塊置中排列有很多方式,例如設定 border 、 margin 、 padding 等屬性。但設定的寬高數值愈多,除了在螢幕大小不同時很容易歪掉,也代表接下來要利用 media queries 覆寫屬性時要處理的屬性愈多,所以這邊整理了一些不需要針對寬高作特別設定的置中作法:
使用 display: block 時-固定寬度加上 margin: auto 屬性
這個作法適用單一區塊水平置中。只要區塊的寬度設定為某個「小於上層元素」的數值,加上 margin: auto 就可以輕鬆地將區塊置於上層元素的中央。這是最簡單常用的一種作法。
使用 display: inline-block 時-在外層設定 text-align: center
inline-block 的好處是同一行內的多個 inline-block 可以一起置中,第二、第三行以後也會像文字一樣置中排列,這是其它的方法難以簡單達成的。因為 inline-block 的特性是在上層元素寬度縮小時自動往下換行排列,所以當有多個區塊需要置中並支援適應性設計時,這個作法就可以簡單達成。
使用絕對定位時-margin: auto 加上左右定位
有時候為了因應排版需求,不得不使用 position: absolute 做絕對定位,這時候要如何置中呢?首先和 display: block 的作法一樣,必須固定寬度,再加上 margin: auto ,最後再設定左右位置兩個數值- left: 0; right: 0; 就大功告成啦!
以下是三種置中作法的展示:
絕對定位有兩個特點,一是可以垂直置中,二是就算區塊大小超過上層元素時也有辦法可以置中。
如果想要垂直置中的話只要加入上下定位即可:
如果區塊大小超過容器呢?其實只要在兩邊指定相同的負值即可:
要注意的是負值必須超過元素寬度的一半,否則無法順利置中。大家可以自己在 fiddle 上嚐試看看。
同場加映:文字對齊小秘技
大家都知道 text-align: center 可以置中文字,但對於一整段文字的對齊,其實有一個更好的選擇- text-align: justify ,也就是左右分散對齊,它的作用是平均分散每一行的文字以切齊左右邊界。
另一個常見的問題是,如何讓文字垂直置中?可能大家有用過 vertical-align: middle 屬性,但缺點是它需要搭配 line-height 屬性才能發揮作用,而 line-height 屬性除了無法設定百分比,遇到多行文字時更成為悲劇。這裡教你一個不需設定 line-height 就能將多行文字垂直置中的作法- display: table-cell 。只要將上層元素設定為 display: table ,並在文字區塊元素上設定 display: table-cell; vertical-align: center; 即可。缺點是為了彌補 diaplay: table 元素排版功能的不足,可能會需要在外面多包一層元素用作排版。
小結
本篇介紹了適應性設計的基本概念和一些簡便的 CSS 排版技巧,看完後有沒有覺得自己也可以來嚐試看看適應性設計呢?事不宜遲,馬上拿去現學現賣吧!本文的下篇將開始介紹 CSS media queries 以及一些好用的工具及套件,幫助你打造一個變形金剛網站,更多小撇步下集待續~