百度在PWA中闡述的彈性佈局-[CSS]

原文連接javascript

響應式佈局

自從進入移動互聯網時代,響應式佈局這個詞常常出如今 Web 設計和開發領域,它讓 Web 頁面在不一樣尺寸的設備上都具備良好的瀏覽體驗。css

開始以前

在講解響應式佈局以前,須要先了解一下基礎知識,只有對它們都有必定的瞭解,才能在作響應式佈局時選取合適的技術方案。html

像素

像素這個單位很常見,指的是圖像中最小的單位,一個不可再分割的點,在計算機屏幕上通常指屏幕上的一個光點。例如常見的描述中 iPhone X 的分辨率是 1125x2436,通常指的是在長和寬上像素點的個數。可是在 Web 開發中,咱們知道 iPhone X 的像素是 375x812,那麼這又是怎麼回事呢?這裏須要講到設備像素(Device Pixels)和虛擬像素,也能夠叫 CSS 像素(CSS Pixels)或者邏輯像素,後面咱們統一使用 CSS 像素這個稱呼,在 Android 開發中能夠叫設備無關像素(Device Independent Pixel,簡寫 dip)。設備像素很好理解,對應屏幕上光點的數量。java

在科技發展到今天,屏幕分辨率已經達到人眼沒法區分單個像素的程度,人眼沒法在 iPhone X 寬不到 7cm 的屏幕上數出 1125 個像素點。Web 開發人員眼中的 1px 可能對應多個設備像素,Peter-Paul Koch 在他的博文中有詳細的講解《A pixel is not a pixel is not a pixel》。git

好比在 iPhone X 上,設備像素是 1125x2436,而 CSS 像素是 375x812,那麼一個 CSS 像素對應的是長和寬各 3 個設備像素,9個設備像素點。github

1 css pixel = 3 x 3 device pixels

那個這個比值 3 就是咱們平時所說的設備像素比(Device Pixel Ratio),簡稱爲 DPR。DPR 它並非一個單位,而是一個比值,這個比值能夠在瀏覽器中經過 JavaScript 代碼獲取。web

// 設備像素比,在 iPhone X 中等於 3,在 iPhone 6 中等於 2
window.devicePixelRatio

EM vs REM

EM

EM 是相對單位,相對於元素自身的 font-size,它不像像素是固定的單位,所以很適合用來作響應式佈局。npm

<style>
h1 {
  font-size: 20px;
  margin: 1em; /* 1em = 20px */
}
p {
  font-size: 14px;
  padding: 1em; /* 1em = 14px */
}
.outer {
  font-size: 12px;
}
.inner {
  font-size: 2em;
  padding: 1em; /* 1em = 24px*/
}
</style>
<div class="outer">
  <div class="inner"></div>
</div>

若是當前元素沒有設置 font-size,那麼 1em 實際大小是多少?canvas

p {
  padding: 1em; /* 1em 等於多少像素*/
}

在上面的代碼中沒有設置 <p>font-size,它會從繼承父元素的字體大小,若是父元素也沒有設置字體大小,會一直找到根元素 <html>,而 <html> 元素的默認 font-size 通常是 16px。有的元素有默認的字體大小,好比 <h1>font-size 默認等於 2em,最終計算仍是會追溯到最外層。瀏覽器

<html>
<head></head>
<body>
  <p>1em = 16px</p>
</body>
</html>

REM

REM = Root EM,顧名思義就是相對於根元素的 EM,是根據根元素來計算出CSS 像素點的大小。根元素就是 <html>,而它的默認字體大小是 16px。

h1 {
  font-size: 20px;
  margin: 1rem; /* 1rem = 16px */
}
p {
  font-size: 1rem; /* 1rem = 16px */
}

因此,若是咱們改變根元素的字體大小,頁面上全部使用 rem 的元素都會被從新計算元素屬性並重繪。

EM vs REM

EM 和 REM 都是相對單位,二者均可以用來作響應式佈局的單位。根據它們的特性,EM 和 REM 互有優劣。

  • EM - 對於模塊化的頁面元素比較好,好比 Web Components 標籤,標籤內的元素都根據父元素計算像素大小,只需設置最外層父元素的字體大小可同時影響子元素,保持自定義元素具備必定的模塊封閉性。但,EM 比較難以追溯,須要逐層向上排查顯示設置了字體大小的元素。
  • REM - 方即是 REM 最大的好處,只需知道 <html> 的字體大小便可計算當前的實際像素大小。

有的開發者所有都用 REM,有些開發者所有用 EM,這其實都是不合理的用法。開發者應該視狀況不一樣採用不一樣的單位,但在如今的環境下,REM 使用的更普遍一些。

開發者根據設計師提供的 UE 圖進行開發時,測量出來的大小單位通常是像素,若是須要轉換爲 REM,能夠採用 PostCSS 的插件 postcss-px2rem 自動轉換爲 rem 單位。

vw, vh,百分比

vwvh

vw 和 vh 如今還不常見,但也逐漸開始被開發者使用,特別是在佈局上。

  • vw - viewport width,視口寬度,1vw = 1% 視口寬度
  • vh - viewport height,視口高度,1vh = 1% 視口高度

vw 和 vh 的邏輯比較簡單,100vw = 100% 視口寬度,視口(viewport)會在後面詳細講解。下面的代碼演示如何在 iPhone X 上計算 vw 的實際 CSS 像素大小,vh 的計算方法和 vw 同樣。

<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
  p {
    width: 50vw; /* 1vw = 1 / 100 * 375px = 3.75px */
  }
  </style>
</head>
<body>
  <p>50vw = 50% viewport width = 50% * 375px = 187.5px</p>
</body>
</html>

瀏覽器對 vw 和 vh 支持相對較晚,目前在 Android 4.4 如下的 Android Browser 上還不支持,可是國內主流應用的 WebView 內核都是本身定製的,內核版本都高於系統自帶的,所以在國內 vw 和 vh 的支持度比 Can I Use 統計的要高不少,並且隨着版本的推移,vw 和 vh 會更流行。

vw, vh vs 百分比

如今咱們知道了,1vw = 1% 視口寬度,那麼它們是否是等價呢?咱們先來看一下下面的代碼,一樣仍是以 iPhone X 爲例。

<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
  .p1 {
    width: 50vw; /* 1vw = 1 / 100 * 375px = 3.75px */
  }
  .outer {
    width: 80vw;
  }
  .p2 {
    width: 50%;
  }
  </style>
</head>
<body>
  <p class="p1">50vw = 187.5px</p>
  <section class="outer">
    <p class="p2">50% = 150px</p>
  </section>
</body>
</html>

將上面的代碼在瀏覽器中運行,發現第二個 <p> 標籤的實際寬度爲 150px,不是 187.5px。其實原理很是簡單,就和 EM 和 REM 同樣,百分比相對於父元素的寬度來計算,而 vw 根據視口的寬度來計算。

因此再回顧上面的例子中的第二個 <p> 標籤,.outer 元素的寬度爲 80vw = 300px,那麼其子 <p> 標籤的寬度爲 300px * 50% = 150px。

除 vw 和 vh 外,還有 vmin 和 vmax 元素,這裏就不繼續展開,感興趣的開發者能夠訪問 《Fun with Viewport Units》瞭解更多,這篇文章中對 vw 和 vh 講的很詳細,還有很多示例。

Web 開發中還有不少其餘的單位,如 in(英尺),mm(毫米),cm(釐米)等,但由於使用的很少,開發者僅做了解就能夠。

彈性框

上面咱們講到了百分比和 vw/vh,它們均可以用來實現響應式的佈局,可是不如咱們接下來要講的彈性框靈活,它不是單位,而是一種佈局方式。

區別於傳統的佈局方式,如標準文檔流、浮動佈局和定位佈局,彈性框(flexbox)佈局更加靈活,彈性框中的元素能夠彈性伸縮,能夠定義排版方向,還能夠指定 flex 元素的順序。下面是一個簡單的例子。

<style>
.container {
  display: flex; /* 設置容器爲彈性佈局 */
}
.box {
  width: 100px;
  height: 30vh;
}
.b1 {
  background: #009;
}
.b2 {
  background: #06c;
}
.b3 {
  background: #39f;
}
.b4 {
  background: #6cf;
  width: 50px;
}
</style>
<div class="container">
  <div class="box b1"></div>
  <div class="box b2"></div>
  <div class="box b3"></div>
  <div class="box b4"></div>
</div>

上面的例子在瀏覽器中的表現以下圖所示,咱們能看到,每一個 <div> 元素都是橫排,這是由於彈性佈局默認排列爲橫向排列,咱們能夠經過 flex-direction 屬性決定排列方向,同時在小於 350px 寬的瀏覽器裏,會按比例自動縮小每一個 <div> 的寬度。

彈性框在不一樣寬度瀏覽器下的表現

從上面的例子中,能發現,有兩個重要的角色須要開發者關注,一個是容器,一個是其子元素。

容器樣式屬性

容器指的是 display: flex 的元素,它能夠定義其餘的屬性,決定子元素的排列,以下。

  • flex-direction - 定義主軸方向,即子元素的排列方向,取值爲 row, row-reverse, columncolumn-reverse,默認爲 row,即水平從左到右
  • flex-wrap - 默認狀況下,彈性佈局會將全部元素都壓縮到一行,能夠經過設置 flex-wrap 告訴瀏覽器在適當時候換行,取值爲 nowrap, wrapwrap-reverse,默認爲 nowrap
  • flex-flow - 這個屬性值是 flex-directionflex-wrap 的簡寫,如 flex-flow: row nowrap,等價於 flex-direction: row; flex-wrap: nowrap
  • justify-content - 定義子元素在主軸上對齊方式,取值爲 flex-start, flex-end, center, space-between, space-around,默認爲 flex-start
  • align-items - 定義子元素在垂直於主軸的交叉軸的排列方式,取值爲 stretch, flex-start, flex-end, center, baseline,默認爲 stretch,即若是沒設置高度,將填滿交叉軸方向
  • align-content - 定義了子元素在多條軸線上的對齊方式,若是隻使用了一條軸線,那該屬性不起做用,取值爲 flex-start, flex-end, center, space-between, space-between, space-aroundstretch,默認爲 stretch

在彈性佈局以前,開發者若是要實現子元素水平和垂直居中會比較麻煩,在彈性佈局中,很是容易實現,只須要在容器上設置軸線對齊方式,以下代碼所示。

.container {
  display: flex; /* 設置容器爲彈性佈局 */
  justify-content: center; /* 設置在主軸上居中對齊 */
  align-items: center; /* 設置在交叉軸上居中對齊 */
}

子元素樣式屬性

一樣,子元素也有不少新增的樣式屬性,以下:

  • order - 設置子元素在主軸方向上的順序,取值爲數字,從小到大排列,默認爲 0
  • flex-grow - 定義子元素的放大比例,取值爲數字,默認爲 0
  • flex-shrink - 定義子元素的縮小比例,取值爲數字,默認爲 1
  • flex-basis - 定義在分配多餘空間以前,子元素的默認大小,默認爲 auto
  • flex - 是 flex-grow, flex-shrinkflex-basis 的簡寫,默認值爲 0 1 auto
  • align-self - 覆蓋父元素的 align-items 屬性,可讓子元素自身採用不一樣的對齊方式,默認爲 auto,繼承父元素的 align-items

彈性佈局很是靈活,屬性值也足夠應對大部分複雜的場景。能夠閱讀這篇文章查看詳細的介紹《A Complete Guide to Flexbox》。

那麼,開始以前須要瞭解的內容就到這了,接下來看如何實現響應式佈局。

設置 viewport

支持響應式第一步,須要作的是設置頁面的 viewport。移動端網頁會在頭部書寫 viewport 的元標籤,它告訴瀏覽器頁面多大尺寸,是否須要縮放。

<meta name="viewport" content="width=device-width, initial-scale=1">

想要理解 viewport 能夠閱讀 Peter-Paul Koch 寫的三篇文章,《A tale of two viewports — part one》,《A tale of two viewports — part two》,《Meta viewport》。

在早期,移動設備常常須要打開 PC 端的網頁,早期的移動設備設備像素比較低,多爲 320px,而 PC 端的網頁寬度通常都很大,因此,若是將 PC 端的網頁在移動設備上打開,會由於頁面太窄而致使佈局錯亂。爲了解決這個問題,瀏覽器會將頁面默認 viewport 設置爲一個較大的值(Safari 默認是 980px),因此 PC 端的網頁在移動設備瀏覽器上都能正常打開,只是元素看上去比較小。

在上面的例子中,viewport 的值 width=device-width,告訴瀏覽器用 屏幕寬度(單位爲 CSS 像素)來做爲頁面寬度渲染,在 iPhone X 下是 375px,不一樣的設備寬度可能不同。這個視口被 Peter-Paul Koch 稱爲理想視口(ideal viewport),也是體驗最好的視口大小。

viewport 設置先後對比圖,右側設置了 viewport

viewport 元標籤的取值有 6 種,以下表所示

字段名 取值 說明
width 正整數,device-width 定義視口的寬度,單位是 CSS 像素,若是等於 device-width,則爲理想視口寬度
height 正整數,device-height 定義視口的高度,單位是 CSS 像素,若是等於 device-height,則爲理想視口高度
initial-scale 0 - 10 初始縮放比例,容許小數點
minimum-scale 0 - 10 最小縮放比例,必須小於等於 maximum-scale
maximum-scale 0 - 10 最大縮放比例,必須大於等於 minimum-scale
user-scalable yes/no 是否容許用戶縮放頁面,默認是 yes

確保內容不會超出 viewport

設置了 viewport 爲理想視口,若是在 iPhone X 上,有元素的寬度超出了 375px,那麼就會溢出到視口外面,致使出現橫向滾動條。不管是在 PC 端,仍是移動端,用戶的都習慣上下滾動,而不是左右滾動,強迫用戶橫向滾動或者縮小頁面來瀏覽所有的內容,體驗很很差。

所以,不能指望設置 viewport 寬度能解決適配問題,還須要開發者記住如下原則。

  • 不要使用大的固定寬度的元素,若是不考慮穿戴式設備,不要設置大於 320px 的寬度
  • 不該該讓內容在某一個特定寬度的 viewport 下才能正常顯示
  • 使用相對單位或者媒體查詢讓元素在不一樣大小的視口下適配

對於圖片或者視頻等嵌入式的元素,能夠在站點 CSS 中添加下面的代碼。

img, embed, object, video {
  max-width: 100%; /* 設置 img 等元素最大寬度威 100% */
}

設置圖片最大寬度先後對比,左側沒有設置 max-width 爲 100%

使用媒體查詢

媒體查詢(media query)讓開發者能夠有選擇性的應用不一樣 CSS,媒體查詢提供了簡單的判斷方法,能夠根據不一樣的設備特徵應用不一樣樣式,好比設備的寬度、類型、方向等,能夠參考 MDN 上的文檔《CSS 媒體查詢》

<!-- 在 viewport 寬度大於 600px 時,應用 example.css 中的樣式 -->
<link ref="stylesheet" href="example.css" media="min-width: 600px">
<style>
/* 若是設備類型爲屏幕而且 viewport 小於 800px 寬,設置 body 背景顏色爲灰色 */
@media screen and (max-width: 800px) {
  body {
    background: #ccc;
  }
}
</style>

若是須要使用媒體查詢應用的樣式比較多,能夠獨立爲一個文件,經過在 <link> 標籤中設置媒體查詢條件。

媒體查詢支持不少設備特徵,經常使用的主要是 viewport 的寬高和設備方向,以下表所示。

設備特徵 取值 說明
min-width 數值,如 600px 視口寬度大於 min-width 時應用樣式
max-width 數值,如 800px 視口寬度小於 max-width 時應用樣式
orientation portrait|landscape 當前設備方向,portrait 垂直,landscape 水平

如何選擇 min-widthmax-width 的取值,咱們稱爲選擇斷點,主要取決於產品設計自己,沒有萬能媒體查詢的代碼。但通過實踐,咱們也總結了一套比較具備表明性的設備斷點,代碼以下。

/* 很小的設備(手機等,小於 600px) */
@media only screen and (max-width: 600px) { }

/* 比較小的設備(豎屏的平板,屏幕較大的手機等, 大於 600px) */
@media only screen and (min-width: 600px) { }

/* 中型大小設備(橫屏的平板, 大於 768px) */
@media only screen and (min-width: 768px) { }

/* 大型設備(電腦, 大於 992px) */
@media only screen and (min-width: 992px) { }

/* 超大型設備(大尺寸電腦屏幕, 大於 1200px) */
@media only screen and (min-width: 1200px) { }

若是要對細分屏幕大小進行適配,能夠查看文章,列出了詳細的常見設備的媒體查詢條件,《media queries for common device breakpoints》。

最佳實踐

響應式文字

大多數用戶閱讀都是從左到右,若是一行文字太長,用戶閱讀下一行時容易出錯,或者用戶只會讀一行文字的前半部分,而略讀後半部分。在上世紀就有研究代表,一行 45 ~ 90 個英文字符是最好的,固然這要看是什麼字體,一箇中文漢字通常對應兩個英文字符,因此,對於中國用戶來講,一行文字合理的數量應該是 22 ~ 45 個字符。

字體大小對閱讀體驗一樣重要,基本字體通常不小於 16px,行高大於 1.2em。

p {
  font-size: 16px;
  line-height: 1.2em; /* 1.2em = 19.2px */
}

而設備的尺寸多種多樣,若是設計師但願在平板上將字體設置爲 18px,開發者可使用前面講到的 REM 和媒體查詢,代碼以下。

/* 在屏幕寬度大於 600px 的設備上使用下面的樣式 */
@media only screen and (min-width: 600px) {
  p {
    font-size: 1.125rem; /* 1.125rem = 16px * 1.125 = 18px */
  }
}

響應式圖片

一圖勝千言,圖片佔網頁流量消耗的 60%,可見其在 Web 的重要性。在上文提到圖片不要超出視口的寬度,給圖片設置 max-width: 100%,這確實很是有做用,那還有沒有其餘須要咱們注意的呢。

圖片的質量

現代設備的 DPR (設備像素比)都很高,iPhone X 的 DPR 是 3,所以若是咱們用 375px 寬的圖片在 iPhone X 上顯示,實際只能利用它三分之一的設備像素點,會讓圖片看起來很模糊,視覺體驗較差。若是咱們都用 3 倍分辨率的圖片來顯示,實際屏幕較小的設備沒法徹底顯示如此高清晰度的圖片,就會在顯示時進行壓縮,這對於實際屏幕比較小的設備來講會浪費較多帶寬。

爲此,圖片質量也須要能響應式。

<!-- 響應式圖片 -->
<img
  srcset="example-320w.jpg 320w,
          example-480w.jpg 480w,
          example-800w.jpg 800w"
  sizes="(max-width: 320px) 280px,
         (max-width: 480px) 440px,
         800px"
  src="example-800w.jpg" alt="An example image">

這裏 sizessrcset 不少開發者比較陌生。在兼容性很差的瀏覽器裏,會繼續使用默認 src 屬性中的圖片。

srcset

定義了幾組圖片和對應的尺寸,格式比較簡單,主要的兩個部分是圖片地址和圖片固有寬度,單位爲像素,可是這裏使用 w 代替 px

sizes

定義了一組媒體查詢條件,而且指名了若是知足媒體查詢條件以後,使用特定尺寸的圖片。

若是開發者書寫了上面代碼中的圖片,瀏覽器會根據下面的順序加載圖片。

  1. 獲取設備視口寬度
  2. 從上到下找到第一個爲真的媒體查詢
  3. 獲取該條件對應的圖片尺寸
  4. 加載 srcset 中最接近這個尺寸的圖片並顯示

因此,若是咱們在視口寬度爲 375px 的設備上,會採用最接近 440px 的圖片,example-480w.jpg

若是對 srcsetsizes 還想了解更多,能夠訪問 MDN 的文檔《響應式圖片》

圖片藝術方向

咱們提到將圖片的 max-width 設置爲 100%,圖片就會在手機屏幕上壓縮到視口的寬度,若是這張圖片實際上很大,圖片中的內容就會看不清,特別是若是圖片主要內容集中在中間,如人像,瀏覽效果會比較差。遇到這樣的狀況,最好的方式是在不一樣的屏幕尺寸下采用不一樣的圖片,讓主要內容保持在視口中間,以下圖。

藝術方向示意圖,圖片來源於 https://developers.google.com/web/fundamentals/design-and-ux/responsive/images

HTML 標準中有一個標籤 <picture>,容許咱們在其中設置多個圖片來源,就和 <video><audio> 標籤同樣。

<picture>
  <source media="(max-width: 799px)" srcset="example-480w-portrait.jpg">
  <source media="(min-width: 800px)" srcset="example-800w.jpg">
  <img src="example-800w.jpg" alt="An example img">
</picture>

<picture> 標籤的做用和上面在 <img> 中設置 sizessrcset 同樣,都能在不一樣的設備寬度下顯示不一樣的圖片,筆者更建議使用 <picture> 實現此效果。

圖片的其餘注意事項

響應式佈局在 PWA 中是很是重要的概念,在實現響應式的同時,還須要關注響應式圖片是否會帶來性能問題。在開發過程當中,還須要注意下面幾個問題。

  1. 對圖片進行懶加載
  2. 對於小的簡單的圖片,可使用矢量圖或者字體,保證在不一樣尺寸設備下都很清晰
  3. 對於尺寸小的圖片,可使用 Data URI 的方式,將圖片轉成 base64 內聯在 CSS 或者 HTML 中,避免請求,但這樣一樣沒法利用 HTTP 緩存,所以通常只對小於 1.5K 的圖片作處理
  4. 挑選恰當的圖片格式,PNG,JPEG 等,能夠在 Android 下使用 WebP 格式
  5. 對圖片進行壓縮和優化
  6. 採用 CSS 和 CSS 動畫代替一些簡單的圖片和動態圖,如加載中 GIF 圖

響應式佈局

利用相對單位、flexbox、媒體查詢等技術,開發者能應付各類類型的頁面和佈局,爲了方便開發者可以快速上手,下面介紹 5 種常見的響應式佈局模式。這些模式最初由 Luke Wroblewski 總結並提出。

爲了更好的理解這些響應式佈局,筆者準備了 5 個例子。

# 從 GitHub 下載代碼到本地 pwa-book-demo 目錄
$ git clone https://github.com/lavas-project/pwa-book-demo.git

# 進入到 chapter02/responsive-web-design 目錄
$ cd chapter02/responsive-web-design

# 安裝 npm 依賴
$ npm install -g edp

# 啓動 chapter02 responsive-web-design 示例
$ edp ws start

啓動完成以後,訪問 http://localhost:8848/ 能看到 5 個不一樣的目錄,如 mostly-fluid,點擊目錄裏的 index.html 就能看到不一樣模式的效果,嘗試拖動改變瀏覽器的大小吧。

第一種:大致流動(Mostly Fluid)

大致流動佈局的主要特色是在大屏幕上,內容區域寬度是固定的,所以在多數設備上,主要佈局結構並無很大改變,若是屏幕寬度大於內容區域,就在內容左右留白。而在視窗寬度較窄時,會逐漸掉落呈堆放,以下圖所示。

大致流動佈局示意圖

大致流動佈局比較簡單,每每只須要少許的媒體查詢就能夠實現,以下代碼所示。

<style>
.box {
  width: 100%;
  height: 150px;
}
/* 設置各個區塊的顏色 */
.b1 {
  background: #009;
}
.b2 {
  background: #06c;
}
.b3 {
  background: #39f;
}
.b4 {
  background: #6cf;
}
.b5 {
  background: #cff;
}
/* 在大於 450px 時,將 .b2, .b3 寬度設置爲 50% */
@media screen and (min-width: 450px) {
  .b2, .b3 {
    width: 50%;
  }
}
/* 在大於 800px 時,將 .b1, .b2 寬度設置爲 50%,讓 .b3, .b4, .b5 平分一行 */
@media screen and (min-width: 800px) {
  .b1, .b2 {
    width: 50%;
  }
  .b3, .b4, .b5 {
    width: 33.333333%;
  }
}
/* 定義最大寬度爲 980px */
@media screen and (min-width: 980px) {
  .container {
    max-width: 980px;
    margin: auto;
  }
}
</style>
...
<div class="container">
  <div class="box b1"></div>
  <div class="box b2"></div>
  <div class="box b3"></div>
  <div class="box b4"></div>
  <div class="box b5"></div>
</div>

第二種:列掉落 (Column Drop)

列掉落,佈局中的每列隨着寬度變小而逐個掉落,在視口最小的時候,每一個元素都縱向堆放。和大致流動佈局不一樣點在於,列掉落佈局不會設置最大寬度,若是視口足夠大,列掉落佈局也會填滿整個頁面。媒體查詢的斷點選擇須要根據網頁自己的內容來選擇。

列掉落佈局示意圖

列掉落比大致流動佈局要簡單,代碼以下。

<style>
/* 在大於 450px 時,將 .b1 和 .b2 放置在同一行,分別佔據 30% 和 70% */
@media screen and (min-width: 450px) {
  .b1 {
    width: 30%;
  }
  .b2 {
    width: 70%;
  }
}
/* 在大於 800px 時,.b1, .b3 各佔 20% 區域,.b2 在中間佔 60% */
@media screen and (min-width: 800px) {
  .b1, .b3 {
    width: 20%;
  }
  .b2 {
    width: 60%;
  }
}
</style>
...
<div class="container">
  <div class="box b1"></div>
  <div class="box b2"></div>
  <div class="box b3"></div>
  <div class="box b4"></div>
  <div class="box b5"></div>
</div>

第三種:佈局移位(Layout Shifter)

佈局移位是最靈活的佈局方式,它不只僅將元素按照從前到後,從上到下排列,有時還會改變元素的位置。

佈局移位佈局示意圖

代碼以下:

<style>
/* 在大於 800px 時,將 .b1 和 .b4 放置在同一行,分別佔據 20% 和 80% */
@media screen and (min-width: 800px) {
  .b1 {
    width: 20%;
  }
  .b4 {
    width: 80%;
  }
}
</style>
...
<div class="container">
  <div class="box b1"></div>
  <div class="box b4">
    <div class="box b2"></div>
    <div class="box b3"></div>
  </div>
</div>

第四種:微調(Tiny Tweaks)

微調,意思就是在視口發生變化時,對內容進行一些小的調整,好比調整字體、圖片大小或者元素間距等。

字體微調示意圖

<style>
.b1 {
  background: #39f;
  text-align: center;
  padding-top: 10%;
  font-size: 1em;
}
@media screen and (min-width: 450px) {
  .b1 {
    font-size: 2em;
  }
}
@media screen and (min-width: 800px) {
  .b1 {
    font-size: 4em;
  }
}
</style>
...
<div class="container">
  <div class="box b1">字體大小</div>
</div>

第五種:畫布溢出(Off Canvas)

在畫布溢出佈局中,內容不是從上到下的,而是將不經常使用的內容,好比應用菜單和導航欄,摺疊起來,留下一個打開的入口,只有當屏幕足夠大的時候才顯示。畫布溢出佈局很常見,不只在 Web App 中,在 Native App 中使用更多。這樣的佈局通常都須要配合 JavaScript 使用。

畫布溢出示意圖

在示例中,咱們經過 transform: translate(-275px, 0) 將左側側邊欄隱藏在視口外,點擊菜單後,菜單欄會從左側劃出。在頁面視口大於 800 時,將佈局改成 flexbox 彈性佈局,直接顯示左側菜單欄,代碼以下。

<style>
  nav {
    width: 275px;
    height: 100%;
    position: absolute;
    /* 將菜單欄隱藏起來 */
    transform: translate(-275px, 0);
    transition: transform 0.3s ease-in-out;
    background: #39f;
    z-index: 2;
  }
  nav.open {
    transform: translate(0, 0);
  }
  /* 在視口大於 800px 時,將菜單欄直接顯示出來 */
  @media screen and (min-width: 800px) {
    nav {
      position: relative;
      transform: translate(0, 0);
    }
    body {
      display: flex;
      flex-flow: wrap;
    }
    main {
      width: auto;
      flex: 1;
    }
  }
</style>
<nav></nav>
<main>
  <a id="menu">...</a>
</main>
<div id="mask"></div>
<script>
  let mask = document.querySelector('#mask')
  let nav = document.querySelector('nav')
  let menu = document.querySelector('a')

  // 點擊菜單,顯示或隱藏菜單欄
  menu.addEventListener('click', event => {
    nav.classList.toggle('open')
    mask.classList.toggle('open')
  })
  // 點擊遮罩,隱藏菜單欄
  mask.addEventListener('click', event => {
    nav.classList.remove('open')
    mask.classList.remove('open')
  })
</script>

以上就是比較常見的 5 種響應式佈局模式,大多數狀況下都須要多種模式同時使用。

總結

響應式佈局從設計角度出發,藉助視口設置、CSS 媒體查詢等方法,使開發者能夠更易於維護適用於不一樣尺寸屏幕的網頁。在本節中,咱們介紹了一些文字、圖片以及佈局方面常見的響應式設計最佳實踐,開發者應用這些經驗,能夠更好的優化 PWA 在不一樣尺寸大小設備的用戶體驗。

相關文章
相關標籤/搜索