[翻譯]使用VH和VW實現真正的流體排版

前言

不像響應式佈局,經過media query,設置幾個變化點來適配,流體排版經過調整大小,適配全部設備寬度。這個方法可使咱們開發的網頁,在幾乎全部屏幕尺寸上均可以使用。但出於一些緣由,它的使用率還遠遠沒有響應式技術高。css

在印刷的歷史上,排版是根深蒂固的。關於「流體」的概念,在傳統思想裏並不存在。這是由於,在印刷上,尺寸大小都是有固定的,不用考慮在頁面上使用。我認爲流體排版技術能夠和網頁很好的匹配。這是在不一樣媒介上的一種解決方法。html

並不意味着咱們要推翻以前的全部關於排版的認識,只須要去學習如何用不一樣方式,去運用掌握新的技術。只要注意細節,就能夠製做出適配全部屏幕尺寸的完美的頁面。css3

流體排版上手

視口(viewport)單位,使流體排版在頁面上應用變爲可能。視口單位是根據瀏覽器的視口尺寸的百分比來定義的。web

舉個例子,1視口寬度(vw)等於視口寬度的1%,它不一樣於百分比的地方是,它的寬度是依賴於視口的寬度的,而百分比是元素的祖先元素來決定的。chrome

視口單位,不一樣於其它單位,它不依賴於基礎字體的大小。這種差異很重要,使它變得有意義並且獨特。npm

可使用的4種視口單位瀏覽器

  • vw:視口寬度(viewport width)
  • vh:視口高度(viewport height)
  • vmin:視口寬度或高度,選擇小的那個
  • vmax:視口寬度或高度,選擇大的那個

使用流體排版最簡單的方法,是把html元素的font-size,設置爲一個流體單位:sass

html{ font-size: 2vw; }ide

這個例子中,咱們把根元素的字體大小設置爲2vw。這裏咱們已經修改了根元素字體大小。由於直接或間接使用的em或rem單位,都是依賴於"root rem"的,因此也變成流體的了。例如模塊化

h1{  font-size:2em; }

h1的font-size:2em,若是它依賴的是根節點的字體大小,那麼 font-size:2*2vw=4vw。

只使用視口相關的單位也有一些不足。

  • 沒法精確地控制放大比率。
  • 沒有最大或最小字體大小。
  • 和使用font-size相比,用戶更容易使用像素來聲明大小。

控制視口單位來設置最小最大font-size

html設置爲font-size:2vw的方法,看起來既是流體的,調用起來也很方便,但有些場景無法覆蓋。視口單位不是萬能的,它也須要使用一些其它的方法,來解決沒法覆蓋的場景。因爲視口單位都是依賴於視口的,在很是小的屏幕上,會獲得很小的字體大小,已致沒法查看。(chrome的最小字體是12px,好像能夠解決了。)

理想狀況下,咱們能夠經過設置最小字體來避免這種狀況,但CSS中沒有min-font-size這個屬性。經過一些橫向思惟,咱們能夠獲得實現這種效果的方法。

首先,咱們可使用calc()表達式。

html{ font-size: calc(1em + 1vw); }

這樣就算咱們在一個0寬度的視口中,font-size的大小也會存在,併爲1em。在大的屏幕上,1vw也會在最小字體1em的基礎上增長。可是這種解決方法也不是最理想的。一般咱們只是想在一些小的屏幕上去設置最小字體。咱們可使用media query來解決:

@media screen and (min-width: 50em) {
  html {
    font-size: 2vw;
  }}

上面代碼設置,是僅在當視口寬度大於50em的時候,使用流體。雖然這樣能很好的工做,但也代表會在固定值和流體值之間跳動。爲了解決這個問題,咱們能夠計算出流體值和固定值之間的對應關係。

若是默認字體大小是16像素,而且2vw是2%的視口寬度,那麼能夠知道在800像素的視口時兩個值是相等的。(16/(2/100)=800

由於咱們想在media query中,使用em單位來匹配。如今來換算一下像素到em。800像素除以16:800/16=50。咱們也可使用這個公式來算1/(2/100)=50。和上面例子裏使用的變化條件同樣,2vw對應的是50em。最終,咱們獲得了一個不會在固定和流體之間,產生跳動變化的值。

一樣的能夠用公式去算出最大字體。若是咱們想使用的最大字體是24像素,那麼對應的視口寬度就是24/(2/100)=1200px。換算成字體,就是1.5/(2/100)=75em。若是視口寬度大於75em時,咱們就把字體大小設置成固定值。

@media screen and (min-width: 75em) {
  html {
    font-size: 1.5em;
  }}

這些計算都不是太難,下面作了一個表格,顯示了各視口寬度,流體大小對應的字體大小。

Image

經過這個表格,你能夠得到一些控制視口單位變化。使用單獨的視口單位,能夠只看對應的一列中的字體大小。

控制縮放比率

在不使用media query的狀況下,咱們不可能解決,在400像素的屏幕上顯示16像素的字體,在800像素顯示24像素的問題。

還有,你可能會說,可使用設置最大最小字體的方式,來解決這個問題。但這裏不是像那樣來處理的。

咱們要怎麼去解決這個問題呢?答案是使用calc()。使用calc和視口單位配合,咱們能夠用高級的流體排版,能夠精確地控制必定範圍內的視口寬度使用特定大小的像素值。這裏須要創建一個基本的數字函數:

Image(1)

這個函數能夠能過一個範圍內的一個值,能夠計算出另外一個對應範圍的值。若是你取1-100的中的50,用它獲取1-200的值 ,你將獲得100。(其實我獲得的是(1+(200-1)*(50-1)/(100-1)=99.4949495))。這兩個值都是各自範圍的中間值。

這是一個求映射值的工具函數,在JS中處理數據時常用。當我認識到這只是一個純粹的數學函數,我只須要一個變化的量,我使用calc()來運行這個函數。這裏的變化關鍵值是視口大小:視口大小就是一個變量。100vw是一個變化的值,它是根據視口的尺寸變化的。有了最終的設想,花了一段時間來得到了能工做的函數表達式。calc()函數以其獨特的方式來處理不一樣的單位類型。若是你對這方面感興趣,強烈推薦《 W3C對單位類型和值規範》,不爲別的,就爲了你在同事之間溝通時,能夠吹牛B。

計算看上去很複雜,其實很簡單。咱們選擇最小和最大字體值,而且能夠根據屏幕的尺寸來獲取精確的字體大小。咱們可使用任何單位,包括em,rem,px。這裏拿像素來舉例,是由於能夠解釋起來更方便並更好理解,但正常工做中我是使用rem單位的。看你本身的喜愛啦,但有一點,方程式裏全部的值必須是單位統一的,並且你也要像上面的例子中同樣,去除一些單位。

若是你不想輸入上面的代碼,有一些工具能夠幫助你實現。好比:SASS,LESS,PostCSS插件。這樣你就能夠輕鬆的工做了。

保持理想的閱讀長度

在《The elements of typographic style》,Robert Bringhurst 提出一個合理的閱讀長度 大約是45到75個字符的長度

Anything from 45 to 75 characters is widely regarded as a satisfactory length of line for a single-column page set in a serifed text face in a text size. The 66-character line (counting both letters and spaces) is widely regarded as ideal.

一樣的規則能夠直接運用到流體排版上,不少狀況下,文件縮放實現一致的閱讀長度是可能的。

在響應式方法裏,咱們在media query裏設置不一樣的字體大小,調整容器的寬度,來保持正確的閱讀長度。然而,使用流體排版,調整media query下的值方法已經行不通了。 只是設置容器的大小,使它的比率和字體相同。咱們可使用像上文提到的計算font-size的方法,使用 calc()來計算width屬性的值。這能夠保持閱讀長度-並且樣式表也更容易閱讀和維護了。

在很是小的屏幕維護理想的閱讀長度是不可能的。這種狀況下,咱們選擇把容器的寬度設置爲智能移動設備的寬度。

實現模塊化縮放

模塊化縮放是指一組成比例的數值。看圖能夠更直觀地看到效果:

Image(2)

每一個標題都是下面標題的1.2倍大小。

不用的屏幕尺寸顯示不一樣的綻開效果會更好。

Image(3)

在小屏幕的時候,標題大小顯示得更統一。在大屏幕上有足夠的空間能夠顯示更大的差異。咱們可使用排版技術來使在不一樣的模板縮放變化時更平滑。簡單地在不一樣的屏幕上選擇不的縮放比率,而後計算出每一個的標題級別,不一樣的最小和最大的字體大小。

計算模塊化的縮放,使用基礎字體大小乘以一個指望的比率來獲得一個大的值。獲得小值是用除法。使用相同的方法去計算出每一個縮放對應的值。

大值:

  • 1em × 1.125em = 1.125em
  • 1.125em × 1.125em = 1.266em
  • 1.266em × 1.125em = 1.424em
  • 1.424em × 1.125em = 1.602em

小值:

  • 1em ÷ 1.125em = 0.889em
  • 0.889em ÷ 1.125em = 0.790em
  • 0.790em ÷ 1.125em = 0.702em
  • 0.702em ÷ 1.125em = 0.624em

咱們使用1.125作爲咱們最小縮放比率,1.250作爲咱們最大縮放比率。下面咱們把這個縮放比率應用到每一個級別的標題級別上。

  • 最小縮放比:1.125
  • 最大縮放比:1.250

Image(4)

讓咱們在codepen上演示一下流體模塊縮放標題。你能夠從Tim Brown的《排版的意義》是去了解更多的模塊綻開信息。

如何去選擇一個合適的縮放比率,推薦 Jeremy Church的網站Type Scale,Tim brown、Scott Kellum的Modular Scale網站

保持垂直比例

縱向排版有必要保持頁面元素之間的空白一致。這方面信息能夠讀Espen Brunborg的《CSS Baseline: The Good, the Bad and the Ugly》。

在咱們的層上保持縱向排版,須要設置一個元素之間的垂直空白的比例。找到一個在大屏幕和小屏幕上都適配的垂直排版,是頗有挑戰性的。咱們一般但願找出大屏和小屏的基本度量,或使用不一樣的比例。

在流體排版中,基線也像字體大小同樣是流體的。事實上,你給根元素設置一個流體的值,你可使用em或rem單位。你也可使用calc()來計算。

咱們設置baseline爲1.5rem,而後把body的padding設置爲一個單位的baseline。

body {
  padding: 1.5rem;
}

能夠一樣來設置line-height和margin

p {
  line-height: 1.5rem;
  margin-bottom: 1.5rem;
}

給標題元素設置不一樣的line-height。我想讓line-height加margin值等於baseline的增量。這裏可使用calc()來計算。

h1 {
  font-size: 2rem;
  line-height: 2rem;
  margin-top: calc((1.5rem - 2rem) + 1.5rem);}

這個例子裏,標題元素的height加上margin值等於3rem,正好是baseline值的兩倍。

這裏用sass變量建立一個例子,方便你們理解。

將來,使用自定義css屬性,能夠對這項技術進行更多的擴展。咱們能在calc()表達式中,使用css變量,計算出對應media query中的baseline基值。

約束條件

當你想在WordPress或Bootstrap,這些已經有預約義的佈局中使用,或在已經存在佈局的網站上使用,流體排版時。容器有可能不是流體的,或它們不是根據字體大小的比率來改變的。

最近,幫助澳大利亞政府的民衆部,實現了流體排版。這是一個很大的網站,並且我必須根據已有的設計進行製做。在這種大流量的網站上實現流體佈局,我有兩個主要方面的問題。

第一問題,怎樣阻止佈局被破壞?在這個項目中,我預期導航容器裏的內容,會由於字體大小和窗口的改變的比例不一樣而溢出。但很神奇的是,並無出現這個問題。

實際狀況,正好相反。以前須要單獨設置來調整的地方,內容很天然的適配了它的容器。總之,樣式表中須要儘可能少的media query,大多的組件須要更少的樣式聲明。

還有一個好處是,咱們能夠不用單獨爲平板設備去製做一個單獨的版本,由於這已經能夠很好地在小屏幕上工做了。

下面是在過去須要去爲每種不一樣屏幕尺寸調整一個版本的導航組件。雖然在小屏幕下表現仍是不太完美,但能夠不破壞它的總體性和功能性。

image

第二個問題,由於裏面有不少的固定寬度,因此沒法保持每行的字符都有理解的閱讀長度。我在手機和平板電腦上,對字體大小進行了調整,使其保持在理想的閱讀長度--移動設備閱讀更重要。

主容器和文本的縮放比是不一樣的,當瀏覽器改變大小時,一些文本會從新排列。由於我不想在設備改變方向時,致使閱讀處置改變。這是沒法避免的狀況,咱們只能去測試一下主要設備的影響狀況。還好,在移動設備上重排的影響並非太大。

最後,咱們對結果滿意。毫無疑問,能夠作更多關於排版的改進,咱們已經提升了網站的可讀性。隨着流體排版的經驗愈來愈多,在下一個設計迭代中,主要的焦點會集中在排版和可讀性上。

在現有網站上,使用流體排版技術的幾點提示:

  1. 根據你的設計來,肯定最適合你的字體的最大最小值及縮放比。
  2. font-size使用em單位。若是你想在一個部分容器上(如導航),使用流體排版,給容器設置一個固定值。在這個容器中的em值,都是依賴於固定值的。
  3. 一樣的,若是你只是把主體容器設置成流體排版。若是你把一個塊容器的字體設置爲流體的,那麼全部這個容器中的em值都是流體的。
  4. 文本重排,若是隻是在瀏覽器改變大小時,或設備改變方向時發生,不用過於在乎。
  5. 維護一個好的閱讀長度是可能的。優先去考慮,手機或平板設備的理想閱讀長度。

瀏覽器支持狀況和BUGS

常常聽到在Safari和特別是移動版的Safari,在同時使用視口單位和calc()表達式時,會出現明顯的bug。但都沒有提出什麼具體的問題是什麼,因此這裏作了一些測試。

單獨測試了calc()表達式和視口單位,以及同時使用它們來實現流體排版技術。在使用些技術時,沒有發現什麼問題。

在現代瀏覽器中,calc()和視口單位都能很好的工做。

在Safari 8如下和ie 11如下瀏覽器,當窗口中瀏覽器改變大小時,calc()表達式中的視口單位,不會從新計算。

能夠經過media query來加以修正。

/* Older browsers */
  html { font-size: 16px; }
  
  /* Modern browsers only need this one */
  
  @media screen and (min-width: 25em){
    html { font-size: calc( 16px + (24 - 16) * (100vw - 400px) / (800 - 400) ); }
  }
  
  /* Safari <8 and IE <11 */
  @media screen and (min-width: 25em){
    html { font-size: calc( 16px + (24 - 16) * (100vw - 400px) / (800 - 400) ); }
  }
  @media screen and (min-width: 50em){
    html { font-size: calc( 16px + (24 - 16) * (100vw - 400px) / (800 - 400) ); }
  }

設置了Safary 8如下和ie 11如下,經過media query來從新計算字體大小。

老的瀏覽器則能過js來監聽窗口的改變事件來從新計算字體大小。

能夠在caniuse和查看支持狀況

Image

image

使用流體排版

若是要使用流體排版,要先想清楚要使用哪一種解決方案。

若是整個設計都是流體的,能夠考慮使用rem來定義流體,能夠聲明html字體大小爲一個流體單位。可使用em和rem來定義全部設計部分。

當心選擇你的最大最小字體。關於這點,你須要決定是否直接使用視口單位或對更加精確地縮放比率。若是是後者,使用Sass,LESS或PostCSS插件中的函數,能夠更簡單實現。

確保得到了正確的字體的最大最小值。這是問題的關鍵。一旦你選定了根元素的字體大小,其它的全部組件都是依賴這個值來計算的。項目中若是後面要調整這個值,那麼整個項目都要調整。

不要忘記,在使用流體排版以前定義一個默認的字體大小。默認字體大小,用來在那些不支持流體字體大小的瀏覽器上使用的,這個值不須要和字體最小值 相同。

最後,考慮你的設計上的限制,如何去解決像標題級別和閱讀長度的問題。能夠參與文中的處理方法。若是你的標題組件,想和常規的文本,以不一樣的比率進行縮放,在添加calc()表達式以前,先考慮可讀性和樣式代碼的可維護性。

我但願這能夠給你啓發,可讓你思考在下個項目中那裏能夠用到流體排版。

基本閱讀:

相關閱讀:

擴展閱讀:

原文:Truly Fluid Typography With vh And vw Units

原文連接:https://www.smashingmagazine.com/2016/05/fluid-typography/

相關文章
相關標籤/搜索