筆記 - 應用 Flexbox 實作 RWD 排版

應用 Flexbox 排版實作 RWD。

RWD (Responsive Web Design) 響應式網站設計

  • 同一組網頁內容,在不同裝置不同尺寸的螢幕上,必須有不同的呈現方式
  • 透過 CSS 的控制,讓同一份 HTML 網頁能在螢幕尺寸改變時,自動回應最適當的 CSS layout
  • RWD 是一種「設計原則」,包含不同的流動模式,例如 mostly fluid, column drop, tiny tweaks 等等。參考學習資源
  • 原生 CSS 中適合應用 RWD 的佈局系統包括:
    • flexbox
    • grid

DevTools: viewport 分成 Responsive 與 特定裝置

網站與應用程式開發期間使用 responsive 模式為預設模式。透過調整 viewport 大小觀察網站的行為



製作 RWD 的基本動作順序

  1. 定義預設的 viewport 尺寸
  2. 使用 CSS media queries (媒體查詢)
  3. 設定 breakpoint (分界點)

Mobile First 行動優先的設計原則

此設計原則強調:

  1. 應該從最小螢幕尺寸開始考慮,也就是手機。由於小螢幕能顯示的內容比較少,能運用的佈局有限,因此它應該優先被考慮。先做出迎合最小螢幕的網站內容,再慢慢思考當螢幕變大時,可以追加什麼網站內容。

Mobile First 的焦點是「網站內容如何逐漸變多」,而不是單純把同一套內容塞進不同尺寸

  1. 把行動裝置的使用者體驗放在設定的核心

  2. 考慮行動裝置效能略差於電腦,且程式是逐行執行,故將行動版的城市碼放在前面,以提高提供行動版畫面的速度。

Breakpoint

當尺寸改變時,網頁佈局發生了顯著的變化,這些尺寸的界線叫做 breakpoint,也就是 CSS 樣式轉換的發生點。常見的有:320px、480px、720px、768px、960px、1024px。每設一個 breakpoint 意味需要準備多一份 CSS 樣式,要抓得多細是看設計的需求。

除了上述幾個在設備間切換的主要分界點 (major breakpoint),也會設定次要分界點 (minor breakpoint) 來調整比較細微的 CSS 變化,像是元素的邊距、避免文字超過頁面寬度,或是調整圖片尺寸。

例如:

  • 3 major breaks: 480 / 768 / 1024
  • 3 minor breaks: 320 / 720 / 900

主要分界點負責重大排版變化,次要分界點負責細部的設計優化

CSS media queries

指定媒體類型 media types (早期使用)

以前 (CSS2) 只需要區分螢幕看網頁與列印,引入不同的 CSS 樣式檔案,透過 media 指派給不同的裝置。例如以下依序為所有裝置 (all)、螢幕 (screen)、印表機 (print):

1
2
3
<link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
<link href="css/screen.css" rel="stylesheet" type="text/css" media="screen" />
<link href="css/print.css" rel="stylesheet" type="text/css" media="print" />

媒體查詢 media queries

直接指定媒體名稱作法無法應付各式各樣的螢幕尺寸,CSS3 直接使用條件查詢,稱為 media queries。在 media type 上加入 media feature ,用括號表示,如下例。設定不同的 breakpoint 來引入不同的 CSS layout 達到能回應不同寬度螢幕的網頁。

1
2
3
@media (max-width: 600px) {...//styles}
@media screen and (max-width: 600px) {...//styles}
@media screen and (min-width: 600px) and (max-width: 1000px) {...//styles}

各種 media feature,可用 and / or / not 等,條件為 true 就會繼續執行

  • max-width
  • max-width
  • min-height
  • min-height
  • orientation=portrait 任何高度大於寬度的瀏覽器(直向)
  • orientation=landscape 任何寬度大於高度的瀏覽器(橫向)

根據 mobile first 原則,尺寸小的設定放在最上面

@import 進入 CSS

若樣式太多,CSS 可以使用 @import 來引入文件,就可以在同一份 CSS file 中統一管理網站樣式。

1
@import url('styles.css') screen and (max-width: 670px);


Viewport & Pixels

名詞解釋:

  • 實體像素與 PPIs
  • 螢幕解析度
  • CSS 像素 px

實體像素與 PPIs

實體像素(或稱硬體像素)指螢幕上會發光的最小硬體單位。手機上常用「每寸像素數 pixels per inch」,也就是像素密度。

螢幕解析度

螢幕解析度指一個螢幕每一個方向的像素數量,例如1280 x 920 表示橫向有 1280像素,縱向有 920 像素,螢幕像素總數為 1280 x 920 個。單位面積內的像素越多,代表解析度越高。

CSS 像素 px

CSS 像素是由全球資訊網 (World Wide Web, 也就是 W3C) 創立的抽象名詞,它是一個無視裝置差別而且等長的測量單位,專門用在網頁開發使用。

設定 viewport

  • 告訴瀏覽器 viewport 的寬度以什麼為基準

  • 這個寬度與 CSS 之間的比例關係

    1
    2
    <!-- <head> 中 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">

    使用 <meta name="viewport"> 標籤並帶入以下兩個屬性:

  • width=device-width 調整內容寬度為裝置寬度

  • initial-scale=1.0 設定「CSS 像素」和「裝置像素」的比例為 1:1



相對單位

百分比

最常用的相對單位,viewport 尺寸改變時,元素與 viewport 同時動態縮放。根據父元素的比例計算:target ÷ context = result

  • target: 原本的絕對單位
  • context: 父元素的單位
  • result: 百分比

Viewport 相對單位

想抓取 viewport 的長度,尤其是當你在製作佔滿一整個頁面的全版視覺的時候,會使用 viewport 百分比長度,這些單位會隨著 viewport 尺寸一起縮放

  • vw: 對應到 width of viewport 的比例
  • vh: 對應到 height of viewport 的比例
  • vmin: 等於 vw 或 vh 較小的值
  • vmax: 等於 vw 或 vh 較大的值

以 viewport 寬 1200 像素、高 900 像素為例:
1vw = viewport 寬度的 1% = 12 像素
1vh = viewport 高度的 1% = 9 像素
1vmax = 12 像素
1vmin = 9 像素

width: 100 vw 就佔了整個視窗寬度
width: 50 vw 就是一半視窗寬度

em 字體相對單位

em 用於文字大小,以父元素的 font-size 為基準。

以父元素的字體大小為 16px 為例,子元素設定
1em = 16 像素
0.5em = 8 像素
2em = 32 像素

限制彈性

使用相對單位時,內容會隨著 viewport 縮放,但又想控制最大或最小高或寬,不想太大,維持圖片的清晰度。

例如圖片寬度隨父元素縮放,但最大寬度不超過 960px

1
2
3
4
img {
width: 100%;
max-width: 960px;
}

max-width 應用:container

將網站內容整個包在 container 中(或稱 wrapper)中,以便讓內容置中。這個 container 通常會設定為 width: 100%,但如果放在超級寬的螢幕上,container 延展開來一行文字會被拉的很長,反而不好閱讀。故此時使用 max-width來限制 container 最大寬度,若 viewport 太大時寬度還是可以維持。

1
2
3
4
.container {
width: 90%;
max-width: 960px;
}

min-width 應用:表單寬度

例如填寫地址或 e-mail 的欄位,用 min-width 設定寬度下限,就不會隨 viewport 縮到太小。



以下學習 RWD 設計模式:局部流動(Mostly Fluid)與細微調整(Tiny Tweaks)。使用 media queries 配置,max-width 設定延伸限制。

RWD 設計原則 - Mostly Fluid

流動指內容佈局會隨 viewport 尺寸而流動。

  • 在小螢幕上,內容垂直堆疊;大螢幕上,內容多欄排列
  • 當 viewport 放大到某個 breakpoint 時,內容會停止流動,固定置中,維持網頁易讀性。

Flexbox 架構

根據 HTML 結構,定義出 flexbox 架構

container: .wrapper

items: <header>, <nav>, <main>, <aside>, <footer>

1
2
3
4
5
/* 將 .wrapper 宣告為 flex container, 並且用 flex-flow 設定排列方式 */
.wrapper {
display: flex;
flex-flow: row wrap;
}

設定 breakpoint

  • 600px 以下:堆疊
  • 600px 與 900px 之前:main 與 aside 多欄排列(main: 70%, aside: 30%)
  • 900px 以上:nav, main , aside 多欄排列(20%, 60%, 20%)

Mobile first 所以小尺寸先寫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 不需要調整 width: 100% 的元素,他們會自然地佔滿一排 */
@media screen and (min-width: 600px) {
main {
width: 70%;
}
aside {
width: 30%;
}
}

@media screen and (min-width: 900px) {
main {
width: 60%;
}
nav, aside {
width: 20%;
}
nav {
min-height: 400px;
line-height: 400px; /*讓文字垂直置中 */
}
}

局部就好

在 Mostly Fluid 設計模式中,內容會有最大寬度,不會隨 viewport 無限延展。故設定最大寬度 900px ,超過後就不在延伸。

1
2
3
4
.wrapper {
max-width: 900px;
...
}

參考資料 Readability: The Optimal Line Length



RWD 設計原則 - Tiny Tweaks

不同 viewport 針對局部的 UX 進行微調與優化,適用文字內容多,由文字和影像組成的單列佈局網站。例如字體大小、字體間距、段落間距、行高等微調。

小螢幕

元素之間適度留白

目的:讓視線集中,提高閱讀性

  • 內文不離螢幕邊框太近: container 四周增加 padding 1em
  • 文字間不要太緊密:paragraph 設定 line-height 1.5
  • 增加段落間距:margin-bottom 2em

字體大小

  • 小螢幕上,標題不需要佔太大空間: <h1> font-size 將為 28 px
  • 段落文字縮小,彌補 container 的 padding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.container {
font-family: 'Open Sans';
font-size: 20px;
padding: 1em;
}

h1 {
font-size: 1.4em;
}

p {
font-size: 0.8em;
line-height: 1.5;
margin-bottom: 2em;
}

大螢幕

以 Bootstrap 對大螢幕定義的 992px 為 breakpoint

每行的字元數

為維持易讀性,桌機閱讀理想上每行的字元應在 50 - 75 之間(有些研究可以擴大到 85 字元)

  • 使每行長度維持在 80 的字以內:限制 container max-width 800px

字體大小

桌機的閱讀距離比手機長,故需把字體放大

  • 字體放大:paragraph font-size 1em (= container 20px)
  • 行高增加:paragraph line-height 1.6em
  • 標題字體也放大:<h1> font-size 1.6em
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@media screen and (min-width: 992px) {
.container {
max-width: 800px;
margin: 0 auto;
}

h1 {
font-size: 1.6em;
}

p {
font-size: 1em;
line-height: 1.6em;
}
}