我所知道的所有的響應式網站排版

響應式排版是一個棘手的問題。下面這段代碼是我一開始寫響應式網站時所能想出來的最好的方法:

p { font-size: 16px; } @media (min-width: 800px) { p { font-size: 18px; } } /* Repeat for h1 – h6 and other type groups */

在那之後,我學習了更多的有關排版的問題,而且收集了一些非常棒的例子,比如使用相對單位,vertical rhythms和恰當的文本縮放排版。

這些新的例子都是非常棒的,它們讓我的網站更加美觀,更加賞心悅目。但是,實現這些功能的過程卻是非常糟糕的,民宿訂房系統

我必須去寫很復雜的代碼,而且我發現在巨大的時間壓力下,響應式網頁設計,我掙扎於編寫響應式網站中。

在幾個月的辛瘔工作之後,現在我終於找到了一個可以和各位分享的一個解決方法——Typi。

Typi是非常棒的,因為在三個簡單的步驟之後,它不僅允許我去使用我曾經學過的例子,同時它還解決了大部分我所遇到的問題。現在,就讓我通過我研究響應式排版時用過的例子,來向你具體解釋一下這三個步驟。

當屏幕的大小增長時,增大字體大小和正文的行高。

移動端瀏覽網頁和在PC端瀏覽網頁是完全不同的體驗。當你在一部屏幕比較小的移動端上瀏覽網頁時,毫無疑問你會將設備靠近你自己。

和移動端相比,你的PC的屏幕會離你更遠。因此,相同大小的字因為更遠的距離的緣故在PC上顯得略微小一點。

為了增加可讀性,彌補由距離帶來的字的大小上的視覺損失,我們增加了字體的大小。

我第一次接觸這個例子是通過 ia.net 上的一篇文章———— Responsive Typography: The Basics 。如果你對我說的不是很了解,我強烈建議你去看看這篇文章。

下面貼出的代碼是用Sass對這個例子的實現:

html { font-size: 16px; @media (min-width: 800px) { font-size: 18px; } @media (min-width: 1200px) { font-size: 20px; } }

注:當我們增加字體的大小時,我們也可能需要去增加行高以滿足每行文字間的空白。用Sass我們可以這麼寫:

html { font-size: 16px; line-height: 1.3; @media (min-width: 800px) { font-size: 18px; } @media (min-width: 1200px) { font-size: 20px; line-height: 1.4; } } 為你的排版設置模塊化文本縮放

為你的排版元素選擇字體大小是很難的(從 <h1> 到 <h6> ),尤其是如果你想讓它們更加的美觀。一個模塊化的文本縮放,或者說文本縮放排版是一個很好的工具,你可以用它來幫助你選擇能夠和空白部分完美契合的排版字體。

它們是一序列通過比例關聯在一起的數字。它可以是你的文本字體大小乘上或除以一個比例來得到的。得到的數字之後再次乘上或者除以那個比例。

一個上圖中模塊化文本縮放的代碼可以如下:

html { font-size: 16px } h1 { font-size: 50px } h2 { font-size: 37px } h3 { font-size: 28px } // …

當然,事情沒有這麼簡單。如果你記得之前我們討論到的第一個例子,你可能會意識到正文的字體大小應該隨著你的屏幕大小改變而改變。

當你必須為了保證縮放的一緻性,從而去改變每個斷點處你的所有元素的排版大小時,這個問題就會發生了,看下面的代碼:

html { font-size: 16px; line-height: 1.3; @media (min-width: 800px) { font-size: 18px; } @media (min-width: 1200px) { font-size: 20px; line-height: 1.4; } } h1 { font-size: 50px; @media (min-width: 800px) { font-size: 56px; } @media (min-width: 1200px) { font-size: 63px; } } h2 { font-size: 37px; @media (min-width: 800px) { font-size: 42px; } @media (min-width: 1200px) { font-size: 47px; } } h2 { font-size: 28px; @media (min-width: 800px) { font-size: 32px; } @media (min-width: 1200px) { font-size: 35px; } } // …

想知道這個問題的答案的話可以看下一個例子。

注:如果你需要為你的模塊化縮放選擇開始的字體大小和縮放比例,我建議你讀Tim Brown的一篇文章———— More Meaningful Typography 。

使用相對排版單位

在CSS中的相對單位有百分號( % ),視窗單位( vh , vm , vmin , vmax ), em 單位( em )和 rem 單位( rem )。最常用的排版單位是 em 和 rem 。

你可以同時在同一個行為中用 em 和 rem 來解決我們在第二個例子中遇到的問題。為了將像素 px 轉換成 em ,我們將 font-size 的值除以瀏覽器默認的基本字體大小(base-font size)。

看下面貼出來的代碼:

html { font-size: 16px; @media (min-width: 800px) { font-size: 18px; } @media (min-width: 1200px) { font-size: 20px; } } h1 { font-size: 3.125em; } // 50 ÷ 16 = 3.125 h2 { font-size: 2.3125em;} // 37 ÷ 16 = 2.3125 h3 { font-size: 1.75em; } // 28 ÷ 16 = 1.75 // … // Note: These are approximate values. // The actual values derived from modularscale.com are 3.129em, 2.3353em and 1.769em respectively.

現在就好很多了!

這兒有一些問題需要我們注意,高雄網頁設計。當屏幕寬度增加到 1200px 時, <h1> 的值變成大約 63px 。

63px 太大了。閱讀標簽 <h1> 內的文本已經不是很舒服了。一個更好的決定是將它的值調到 47px (也就是 <h2> 的大小)。

當這個情況發生的時候,你可能會想去降低標簽 <h2> 的大小,因為標簽 <h1> 可以很好的強調。有時候,你也可能需要去改變 line-height 的值。

所以代碼現在就變成了這樣:

html { font-size: 16px; @media (min-width: 800px) { font-size: 18px; } @media (min-width: 1200px) { font-size: 20px; } } h1 { font-size: 3.129em; line-height: 1.2; @media (min-width: 1200px) { font-size: 2.3353em; line-height: 1.3; } } h2 { font-size: 2.3353em; @media (min-width: 1200px) { font-size: 1.769em; } } h3 { font-size: 1,網路開店.769em; @media (min-width: 1200px) { font-size: 1.33em; } } // …

額。。。現在我們回到出發點 🙁

是時候來聊一聊Typi了,讓我們先不管這些例子來看看Typi是怎麼幫助你的吧。

使用Typi

Typi是一個Sass庫,它可以允許你建立在分開的Sass map上所有排版元素的 font-size 和 line-height 屬性。這些map可以被用來輸出我們下面解決方案中的代碼。下面讓我說說它是怎麼工作的。

首先,你需要建立一個 $typi map,如下:

$typi: ( null: 16px, small: 18px, large: 20px );

null , small 和 large 是斷點。

Typi自動的尋找一個 $breakpoints 圖來建立你的媒體查詢(意思就是將作者寫的一個庫 mappy-breakpoints 完美的整合在一起。)

$breakpoints: ( small: 800px, large: 1200px );

一旦 $typi map被建立,我們在 html 選擇器中調用 typi-base() 摻合模式。

html { @include typi-base(); }

這個 typi-base() 摻合模式創建了和我們在例2中給 <html>,桃園網頁設計; 標簽寫的一樣的樣式。唯一的不同是 font-size 是用百分號表示。

html { font-size: 100%; /* This means 16px */ } @media all and (min-width: 800px) { html { font-size: 112.5%; /* This means 18px */ } } @media all and (min-width: 1200px) { html { font-size: 125%; /* This means 20px */ } }

我們也提到當 font-size 的值改變時有可能需要改變 line-height 的值。你可以提前在Typi上通過給每個需要它的斷點上提供一個第二 line-height 值來改變 line-height 的值。

$typi: ( null: (16px, 1.3), // Sets line-height to 1.3 small: 18px, large: (20px, 1.4) // Sets line-height to 1.4 );

從我們更新的 $typi 圖中我們可以得到CSS如下:

html { font-size: 100%; /* This means 16px */ line-height: 1.3; } @media all and (min-width: 800px) { html { font-size: 112.5%; /* This means 18px */ } } @media all and (min-width: 1200px) { html { font-size: 125%; /* This means 20px */ line-height: 1.4; } }

在創建 $typi 圖後,我們可以用同樣的格式來創建別的 font-maps ,下面是例子:

$h1-map: ( null: (3.129em, 1.2), large: (2.3353em, 1.3) ); $h2-map: ( null: 2.3353em, large: 1.769em ); $h3-map: ( null: 1.769em, large: 1.333em ); // …

之後,我們可以通過 typi 摻合模式來調用每一個font-maps

h1 { @include typi($h1-map) } h2 { @include typi($h2-map) } h3 { @include typi($h3-map) } // …

最後得到的CSS如下:

h1 { font-size: 3.129em; line-height: 1,網頁設計.2; } @media (min-width: 1200px) { h1 { font-size: 2.3353em; line-height: 1.3; } } h2 { font-size: 2.3353em; } @media (min-width: 1200px) { h2 { font-size: 1.769em; } } h3 { font-size: 1.769em; } @media (min-width: 1200px) { h3 { font-size: 1.333em; } }

非常的整齊是吧,你必須先去 下載Typi 來使用它(Sassmeister和Codepen上面還不能支持Typi)。

小技巧:

如果你不想在每個不同的字體map上寫準確的 em 值(例如 1.769em ),你可以使用Sass mixin的模塊化文本縮放。

如果你想這麼做的話,你需要 下載庫 並且把它導入到你的Sass文件中,之後你就可以用 ms() 函數來改變字體maps了。

$h1-map: ( null: (ms(4) 1.2),rwd網頁設計, large: (ms(3), 1.3) ); $h2-map: ( null: ms(3), large: ms(2) ); $h3-map: ( null: ms(2), large: ms(1) ); // …

所以簡而言之,Typi通過幫助你在不同斷點上寫 font-size 和 line-height 屬性來讓響應式排版更容易。

現在我已經向你介紹了Typi,讓我們回到之前的剩下的最後兩個例子(一些問題我已經找到了解決方法)。

應用vertical rhythms

Vertical Rhythms在我看來是一個來自印刷設計的概唸。在印刷設計中,我們需要保證一個頁面中的元素的垂直距離與其他頁面的一緻性。這個想法與應用文本縮放的排版很類似————允許你的頁面中的元素很好的浮動。

在實例中,我們經常用到 line-height 屬性作為vertical rhythms一緻性的基礎。讓我們把你的頁面設置為 line-height = 25px ,你需要做下面的兩件事情:

這是它看起來像CSS的地方(這兒還沒有用到上面我們提到的三個實例)

html { font-size: 18px; line-height: 25px; } // Resets margins body, h1, p { margin: 0; } h1 { font-size: 63px; line-height: 75px; margin: 25px 0; } p + p { margin-top: 25px; }

這看起來非常的棒!讓我們更進一步:將代碼改成相對單位。當進行這一步時,你會遇到 em 和 rem 的沖突。

Em vs Rem

讓我們首先把代碼轉換成ems為單位,然後再轉換成rems。順便提一句, line-height 的值最好應該是沒有單位的 。

html { font-size: 1.125em; line-height: 1.4; // This is 25.2px to be accurate } // Resets margins body, h1, p { margin: 0; } h1 { // font size is 63.147px to be more precise font-size: 3.5082em; // 63.147 ÷ 18 = 3.5082em line-height: 1.1972; // 75.6 ÷ 63.147 = 1.1972 margin: 0.3991em 0; // 25.2 ÷ 63.147 = 0.3991 } p + p { margin-top: 1.4em; }

特別要注意的是我們應該怎麼把 <h1> 標簽中的 margin 屬性轉換成ems。

要注意的是我們怎麼用 63.147px 作為除數?這必須被解決因為以ems為單位的大小的計算需要依據當前的字體大小。它總會導緻混亂並包含很多復雜的數學問題。

現在,這兒出現了一個問題。儘管我們嘗試去做到更加的精確,但是瀏覽器似乎不和我們合作。你需要注意我們的vertical rhythms開始變得古怪。

兩個問題導緻了這個古怪的現象。

第一,我們沒有百分之百的精確我們的數學計算。我們可以更加精確(比如精確到十位小數),但是這會讓我們的代碼像地獄一樣丑陋。

第二,不同的瀏覽器處理子像素的捨入問題是不同的。這意味著不管我們怎麼努力的去嘗試,我們都不能獲得最好的像素規律。

好了,我不想糾結於子像素的捨入問題,因為我們真的沒有什麼可以做的。現在,讓我們轉而看看 rem 是如何解決這個復雜的數學問題的,好嗎?

html { font-size: 1.125rem; line-height: 1.4; // This is 25.2px to be accurate } // Resets margins body, h1, p { margin: 0; } h1 { font-size: 3.5082rem; // 63.147 ÷ 18 = 3.5082 line-height: 1.1972; // 75.6 ÷ 63.147 = 1.1972 margin: 1.4rem 0; // 25.2 ÷ 18 = 1.4 } p + p { margin-top: 1.4rem; }

請注意我們是如何用margin屬性中的 1.4rem 來替代 1.3991em 的,RWD自適應式網頁設計?Rem作為單位來進行vertical rhythms的計算會更佳簡單。

這並不是說你必須不假思索的就將單位轉換成 rem 單位。Rems和em都是很有用的,他們可以被用作不同的目的。我會在之後的某一天討論這個話題。現在,讓我們回到vertical rhythms,台中網頁設計

現在,我們將vertical rhythms轉換成相對單位,讓我們看一看當我們將它與實例一結合起來的時候它是怎麼運行的。( font-sizes 和 line-heights 應該隨著屏幕大小的改變而改變)。

我們可以用一個 media-query 來讓這個例子儘可能的簡單。我們也可以用 rem 單位。

html { font-size: 1.125em; line-height: 1.4; @media (min-width: 1200px) { font-size: 1.25em; // this is 20px // Slight change in line heights at 1200px line-height: 1.45 // this is 29px } } // Resets margins body, h1, p { margin: 0; } h1 { font-size: 3.5082em; line-height: 1.1972; margin: 1.45rem 0; @media (min-width: 1200px) { // font-size is now 70.164px line-height: 1.24; // 29px * 3 ÷ 70.164 = 1.24 margin: 1.45rem 0; } } p + p { margin-top: 1.4em; @media (min-width: 1200px) { margin-top: 1.45em } }

額。。。我們也許必須加 20000 個media queries來改變所有元素的 margin 和 line-height 僅僅因為我們改變了 <html> 中 line-height 的一個值。而且我們還沒有講 padding 屬性和 border 屬性呢!

所以,在這兒我明白了。在不同的瀏覽器之間實現完美的響應式vertical rhythms是不可能的。至少以現在的技術是不可能的。

那麼,我們可以做那些事情來替代它呢?

保持文本計量在45-75字符之間

當然,這個實例很簡單。只需要記住:一個字符大約是 0.5em 。一個文本計量意思是你的文本的寬度必須在 22.5em 和 37.5em 之間。

舉個例子,在實際情況中,我主要會擔心文本超出了 75 個字符,SEO優化。而如果你的文本沒有到 45 個字符大小,那麼你可能需要改變你的字體大小了。

article { max-width: 30em; /* Anywhere between 22.5em to 37.5em. Use your discretion */ } 總結

響應式排版很難。雖然現在還是沒有完美的解決辦法,但是我們可以儘我們最大的努力來解決它。

本文根據 @Zell 的《 Everything I know about Responsive Web Typography 》所譯,整個譯文帶有我們自己的理解與思想,如果譯得不好或有不對之處還請同行朋友指點。如需轉載此譯文,需注明英文出處:

飛魚

常用暱稱“飛魚”,目前是高雄大學的學生,專業是軟件工程。對HTML5,CSS,JavaScript等前端技術有濃厚的興趣,希望在這兒能和大家分享自己的興趣與愛好。