響應(yīng)式網(wǎng)頁設(shè)計基礎(chǔ):靈活性
在過去的一年里,如果你不是住在深山里,就一定知道響應(yīng)式網(wǎng)頁設(shè)計,它已經(jīng)成為當今的主流。響應(yīng)式設(shè)計是Ethan Marcotte提出的,概念很簡單:使網(wǎng)站的頁面布局能夠根據(jù)不同設(shè)備和分辨率進行自動調(diào)整。
當我第一次了解到它時,我就立即被迷住了--特別是media queries,我馬上就用到我自己的個人兼職網(wǎng)站上。我甚至寫了一篇文章介紹《如何使用CSS3 Media Queries響應(yīng)不同設(shè)備》(強烈建議在讀這篇文章之前讀一下)。
在第一次嘗試使用media queries后,我很快意識到我忽略了一個響應(yīng)式設(shè)計的重點: 靈活性。
挑戰(zhàn)固定寬度
我的個人兼職網(wǎng)站使用了固定寬度的設(shè)計,所有的width, margin和padding都使用了固定的像素值。 我一般都會這樣寫網(wǎng)站,因為對我來說它更簡單,更快速。
但當我試圖在我的固定寬度的網(wǎng)站上應(yīng)用media queries的時候,那些簡單和快速的優(yōu)勢全部都消失了。為什么?因為對于固定寬度的設(shè)計,我需要非常細致的定義media queries并在CSS文件中調(diào)整每個單獨的像素值,基本上,我需要為每一種可能的分辨率都設(shè)計一個全新的布局,繁瑣!慢!!還不好玩!!!
我有幸聽了Marcotte先生在《In Control 2011》的演講,他討論了響應(yīng)式設(shè)計的理論和最佳實踐,諸如fluid grid(流體網(wǎng)格)實現(xiàn)方式。
流動且靈活的公式
流動式布局是靈活的。由于width,margin和padding(甚至字體和圖像)使用了百分比和em(相對長度單位),因此頁面布局會隨著瀏覽器的窗口變化而變化。隨著分辨率的改變,布局會成比例地進行調(diào)整,實現(xiàn)過程中不需要用到任何media query。
這對于實現(xiàn)響應(yīng)式網(wǎng)頁設(shè)計來說簡直太美妙了。如果我有一個基于比例值的布局,流動式的網(wǎng)格將替我完成大部分繁重的工作。我的media query將不再需要包含那些覆蓋其他分辨率的所有width, margin和padding的樣式定義。
但是也有一點讓我感到頭疼,計算流動式網(wǎng)格的比例寬度需要用到一些數(shù)學(xué)知識,我數(shù)學(xué)不太好…
幸運的是, Ethan 提供了一個很簡單(即便對我來說)的公式來計算比例寬度:
目標寬度÷上下文寬度=結(jié)果(比例寬度)
這個公式用子元素的像素寬度(目標寬度)除以它父元素的像素寬度(上下文寬度),得到的結(jié)果就是這個子元素的比例寬度。
圖1 實例:目標寬度(300px)和上下文寬度(960)像素
在圖1中,例如,深灰色區(qū)域?qū)挾葹?00px,包含在寬度為960px的淺灰色區(qū)域中.這里,960像素區(qū)域是上下文元素,300像素區(qū)域是目標元素,所以我們的數(shù)學(xué)公式是: 300 ÷ 960 = 0.3125
0.3125這個結(jié)果需要變成瀏覽器可識別的數(shù)值, 因此需要轉(zhuǎn)化成一個比例值, 將小數(shù)點右移兩位,變成31.25% 即可。然后在CSS中,將元素的寬度設(shè)定為這個比例值:
- aside{
- background-color:#ccc;
- float:left;
- width:31.25%;
- }
測試一下
公式雖然看起來很簡單,但我知道必須在實際的網(wǎng)站中檢驗一下才行。幸運的是,我最近加入了EE播客,正在重新設(shè)計那個網(wǎng)站。當我的搭檔給我她的 PS 設(shè)計文件時,我就決定將它打造成靈活布局的網(wǎng)站。
比例寬度
我首先記錄下所有元素的像素寬度。(在排版設(shè)計事,我們沒有嚴格遵循網(wǎng)格布局,這也是我建議的做法)正如你在圖2中看到的。整體寬度為940像素,Logo,主持人介紹和分享鏈接都有它們各自的像素寬度。
圖2 主頁和頂部導(dǎo)航元素的像素寬度
按照 Ethan 的公式,整體寬度940px就是我的上下文寬度,根據(jù)它就可以確定所有元素的比例寬度.
Logo: 240 ÷ 940 = .255319148
主持人介紹: 436 ÷ 940 = .463829787
分享鏈接: 90 ÷ 940 = .09574468
隨后我將這些浮點值轉(zhuǎn)換成百分比值,運用到我的CSS中:
- #logo a{
- width:25.5319148%;/*240px/940px*/
- }
- #hosts{
- width:46.3829787%;/*436px/940px*/
- }
- #push{
- width:9.574468%;/*90px/940px*/
- }
我沒有對這些百分比值進行四舍五入,而是直接運用在CSS中。我也從來沒有遇到過任何瀏覽器對這樣精度的百分比值識別錯誤的情況(包括IE)。
同時,我為每一個百分比值都注釋了計算它所用到的目標寬度和上下文寬度,這對于今后的開發(fā)來說是非常重要的參考。
確保你的上下文寬度是正確的
只要你的數(shù)學(xué)計算是正確的,那么將寬度值轉(zhuǎn)化為比例值的過程就是很簡單的,或者,更具體地說,只要你的上下文寬度是對的,那么你得到的比例值也就是正確的.
實戰(zhàn)中, 我通過計算得到的比例值很少會出錯,除非我將上下文寬度搞錯了。
像圖3中標示,主持人信息是一個包含<dt>, <dd>, <a>等元素的定義列表<dl>,這些元素的寬度值各不相同.
圖3 <dl>的寬度
剛開始計算的時候,我先用960像素作為我的上下文寬度,因此<dt>的寬度比例為: 116 ÷ 960 = .120833333
但是這個比例值(12.0833333%)不是我要的正確尺寸.直到我意識到我的上下文寬度是不同的,我才得到了正確的比例值.
對于<dt>來說,它的上下文元素實際是它的父元素<dl>,寬度為436像素。因此我改變了一下參數(shù),并計算出了我需要的百分比: 116 ÷ 436 = .266055045
如果你計算的比例寬度有任何問題,請先檢查一下選定的上下文寬度是否正確,這會幫你省不少事。
成比例的字號
我將ee-podcast.com變得更加“靈活”的第二步是使用比例字號,它和比例寬度的道理是相同的:將固定的像素值變成比例值,字體的比例值使用em進行計算.
要計算比例em,使用相同的公式(目標寬度 ÷上下文寬度 = 結(jié)果)即可,字體的上下文寬度就是它基本字號,通常在body元素中定義:
- body {
- font: 100%/1.5 "Open Sans",Arial,Helvetica,sans-serif;
- }
大多現(xiàn)代瀏覽器的基本字號是16px,如果你設(shè)定的比例字號是100%,字號同樣也是16px.
現(xiàn)在,我們來考慮一下主持人名字的字號,在版式設(shè)計時設(shè)定的是12px,使用公式12÷16=.75就得到了它的em值。這個浮點數(shù)不用轉(zhuǎn)換成百分比值就能直接在CSS中使用:
- #hosts dd{
- font-size:.75em;/*12px/16px*/
- }
成比例的padding和margin
對于padding和margin來說,那個神奇公式同樣有效. 讓我們考慮一下主持人信息當中,右margin被設(shè)定為20像素的<dt>元素(圖3).為了得到這個margin的比例值,我使用了和計算比例寬度相同的公式: 20 ÷ 436 = .04587159
將小數(shù)點右移兩位,得到的百分比值可用到CSS中:
- #hosts dt{
- margin-right:4.5871559%;/*20px/436px*/
- width:26.6055045%;/*116px/436px*/
- }
對于padding的計算來說也是一樣。
圖4 主區(qū)域的橫向padding
ee-podcast.com的主區(qū)域(如圖4所示)的寬度為940px,同時左右各有40px的橫向padding。我使用目標寬度(40px)除以上下文寬度(940px)得到它們的比例寬度:
- header,footer,.wrap {
- padding-right:4.25531%;/*40px/940px*/
- padding-left:4.25531%;/*40px/940px*/
- width:79.3%;
- }
#p#
特例
這個公式對于橫向padding比例寬度的計算有一個特例:對于padding而言,上下文元素永遠都是這個元素本身,無論父元素的寬度是多少。
例如圖5所示的分享鏈接,文字左側(cè)均有25像素的橫向padding來放圖標.
圖5 padding的上下文寬度
計算此padding的比例值時,應(yīng)將這個元素本身的寬度(90px)作為上下文寬度,而不是父元素的寬度940px.(圖2)
25 ÷ 90 = .277777777
因此padding的百分比值設(shè)定為:
- #push li a {
- padding-left: 27.7777777%; /* 25px / 90px */
- }
縱向值
到目前為止,我們已經(jīng)嚴謹?shù)赜嬎懔俗笥业乃街担俏覀冊趚軸和y軸方向都會設(shè)定padding和margin,這就意味著,上下文寬度應(yīng)該依據(jù)水平或垂直方向而變化。
正如你之前看到的那計算,水平方向的百分比值,都是以父元素的寬度作為上下文寬度的(padding是除外)。與此同時,縱向em值是以基本字體大小作為上下文值的。
如果你還記得成比例的字號的計算那一部分內(nèi)容,我們?yōu)镋E-podcast.com設(shè)定的基本字體大小是16px. 所以,如果我想指定縱向的margin和padding,上下文高度值就是16px. 此外,縱向值應(yīng)該用em表示,不是百分比 –和成比例的字號的單位一樣。
這個網(wǎng)站的<header>和<footer>都有縱向的padding:<header>有20px的頂部padding,<footer>有20px的底部padding。(見圖4)
要確定這些padding比例值,我將16px作為上下文高度值(也就是基本字體的大小),并使用相同的公式進行計算: 20 ÷ 16 = 1.25
請記住,垂直方向上的比例值應(yīng)該以em為單位。也就是說可以在CSS中直接使用浮點值,不用轉(zhuǎn)換成百分比:
- header,footer, .wrap{
- padding:1.25em 4.25531%;/*TB-20px/16px|RL-40px/940px*/
- width:79.3%;
- }
這里,我將橫向和縱向的padding值都簡寫了,修改了一些注釋的內(nèi)容,以便為今后的開發(fā)提供能多參考。
- padding:1.25em 4.25531%;/*TB-20px/16px|RL-40px/940px*/
在這些注釋中,我將頂部和底部的值都用TB- 前綴進行標識,左右的值用RL-前綴。這僅僅試是幫我記錄這些比例值是如何計算的。你同樣可以使用自己熟悉的格式或者語法,強烈建議你花些時間去記錄他們。
成比例的高度
在開發(fā)當中,我通常不會指定高度值。但是在EE Podcast網(wǎng)站中需要做很多高度的設(shè)定,比如,<header>的高度設(shè)定為148像素。
為了得到一個成比例的高度值,我用和計算水平值一樣的方法:上下文高度是基本字體的字號,因此<header>的高度為:
148 ÷ 16 = 9.25
我把結(jié)果用em做單位加到CSS中:
- header{
- height: 9.25em;/*148px/16px*/
- padding:.4375em 4.25531% 0; /*T-7px/16px|RL-40px/940px*/
- }
靈活的圖片
EE Podcast網(wǎng)站沒有太多的內(nèi)置圖片,只有一些背景圖片。目前我還沒決定對這些圖片做什么設(shè)置,因此也沒有什么可以向你展示的技術(shù)流程。
我唯一能做的就是向你分享一些我正在參考的網(wǎng)站,它們幫我決定是否有必要在我們的網(wǎng)站上使用靈活的圖片布局。
·對于背景圖片來說,我更關(guān)注background-size property是否會派上用場。對內(nèi)置圖片來說,
·max-width approach有著不錯的瀏覽器支持,可以用在溢出旁邊。
獨立工作流
我們已經(jīng)討論了如何使ee-podcast.com的頁面布局變得更加“靈活”。我應(yīng)該說明一下這是個個人項目,因此會在時間允許的情況下來完成它。因此,我實現(xiàn)網(wǎng)站靈活布局的過程是一個迭代的過程。從轉(zhuǎn)換固定寬度開始,慢慢使他能夠響應(yīng)不同的分辨率,整個過程花費了4個月的時間(包括那些和數(shù)學(xué)作斗爭的煩躁不安的時間)。
最終我完成了一個獨立的工作流
1.我首先直接利用PS設(shè)計稿完成了一個固定寬度的站點
2.把所有寬度變?yōu)榘俜直龋酥魅萜鞯膶挾龋O(shè)置為固定的940像素
3.把所有字體單位變成比例字號em
4.把所有的margin和padding變成百分比,然后把水平margin和padding變成單位為em的值
5.最終我將940像素變成一個百分比
為什么用這個流程?主要是因為,作為一個應(yīng)用靈活布局的新手,我希望首先確保自己有一個使用指定像素值的核心的布局(并且在所有瀏覽器上都能很好地顯示)。我的邏輯是,我可以一邊測試,一邊慢慢地使設(shè)計百分比化,但是總能知道基本版式(固定寬度版本)的樣子。
另外,這個網(wǎng)站會在我完成這個流程之前上線。因此,我將它拆分成可管理的模塊,以便在不影響基本功能的前提下在本地測試新功能,在確保這些功能達到預(yù)期之后發(fā)布它們。
我不打算繼續(xù)使用這樣的工作流了,因為它太費時間,在下一次靈活布局的嘗試中,我決定在開始的時候就使用百分比。
但是這種工作流的確給我教會了我很多東西:你可以在同一個布局中同時使用固定尺寸和百分比尺寸而不會引發(fā)任何問題(前提是你的數(shù)學(xué)公式是正確的)。如果你覺得使用百分比值有點兒困難,可以使用我嘗試的這種方法:從固定的像素值開始,慢慢替換成百分比值。
接下來要做什么?.
即使靈活式的布局解決了大量不同分辨率的自適應(yīng)問題,ee-podcast.com仍然需要media queries。也就是說,靈活和流動的布局只是響應(yīng)式網(wǎng)頁設(shè)計的一部分。
以圖6為例,這張圖展示了ee-podcast.com在一個24英寸桌面(1910 x 1200的分辨率)的靈活布局。這里,每個元素都是成比例的,但是仍然可以調(diào)整一些細節(jié)使得瀏覽體驗變得更好,比如使Logo和主持人信息之間的距離變得小一點。
圖6 1910 x 1200 分辨率
同樣,圖7中的行文字長度在這個分辨率下變得不適于閱讀。
圖7 1910 x 1200分辨率下的行長度
在稍小的分辨率下,會出現(xiàn)其他的問題.圖8是網(wǎng)站在iPad上(水平方向)1024 x 768分辨率下的樣式。比例縮放對自適應(yīng)起到了一定作用,但是出現(xiàn)了浮動內(nèi)容的顯示錯誤和需要重新對齊的問題,以及其他的小問題。正如你所看到的,主持人信息跑到到了Logo下面,谷歌日歷和.ics下載鏈接也出現(xiàn)了相似的問題。
圖8 1024 x 768 垂直方向
在iPhone(垂直方向,320 × 480分辨率下)上,正如你在圖9中看到的,比例縮放呈現(xiàn)出了極其糟糕的閱讀體驗。
圖9 320 x 480分辨率
這些問題可以通過media queries來解決,media queries允許你為不同的設(shè)備和分辨率提供不同的樣式。(要是你沒留意我之前的建議,可以去讀 《如何使用CSS3 Media Queries 應(yīng)對不同設(shè)備》)。同時,我也為我的main container設(shè)定了最大寬度和最小寬度值,這能讓網(wǎng)站在那些我沒空去定義media query樣式的屏幕分辨率下保持適于閱讀的樣式。
- header,footer,.wrap{
- …
- min-width:940px;
- max-width:940px;
- }
Media Queries資源
到了介紹media queries的時候了,比起寫關(guān)于Script Junkie文章的那個時候,我現(xiàn)在感覺自如多了,這多虧了很多(對我來說)新的工具和資源:
·想要在不同設(shè)備和分辨率下測試media query 效果?你可以看看Screenfly, 這并不完美,但我發(fā)現(xiàn)很實用
·Zoe Gillenwater (我至今見過的最好的CSS3資源的作者) 最近整合了“Essential Considerations for Crafting Quality Media Queries.”
·Respond.js:支持IE6到IE8的CSS3 media query, 通過使用Rock solid, lightweight polyfill增加最大和最小寬度
端正心態(tài)
對于我來說,將EE播客網(wǎng)站變成靈活式布局的目的是實現(xiàn)響應(yīng)式網(wǎng)頁設(shè)計,為我的個人兼職網(wǎng)站加入media queries的目的也是實現(xiàn)響應(yīng)式網(wǎng)頁設(shè)計。但是最后,這兩個網(wǎng)站呈現(xiàn)的效果都沒有完全達到我的目標,但是多虧了這兩個經(jīng)驗,我明白了,不可能只通過其中一種方式就實現(xiàn)響應(yīng)式設(shè)計。
響應(yīng)式設(shè)計不只是流動式的網(wǎng)格布局,也不只是media queries。響應(yīng)式設(shè)計是一種心態(tài),一種工作流,一個不能夠(也不應(yīng)該)被分隔理解的大的概念。特別是當“移動為先的設(shè)計”,以及“新設(shè)計過程”這些概念隨之出現(xiàn)的時候。