響應式版面配置應該源自內容限制,而不是裝置型號清單。Intrinsic sizing、flexbox、grid、媒體查詢與容器查詢提供互補的控制方式。
建立響應式基礎 #
viewport 宣告會讓 CSS viewport 符合裝置寬度:
<meta name="viewport" content="width=device-width, initial-scale=1">不要加入 user-scalable=no 或過低的 maximum-scale;頁面縮放是一種無障礙機制。在螢幕鍵盤周圍定位控制項的應用程式,可能也需要 visual viewport API,因為可見區域可能改變,而 layout viewport 不一定會改變。
使用 border-box sizing,並限制替換內容的尺寸:
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
img,
video,
svg {
display: block;
max-inline-size: 100%;
block-size: auto;
}沒有這些規則時,padding 可能意外增加元件寬度,而具有較寬 intrinsic 尺寸的媒體可能從狹窄的 viewport 溢出。
將閱讀內容置中並加以限制 #
可讀的欄位需要最大行長,以及適用於小螢幕的內側間距:
main {
inline-size: min(100%, 72ch);
margin-inline: auto;
padding-inline: 1rem;
}ch 會近似 0 字形的 advance width。它適合用於正文行長;對於尺寸不應依賴所選字型的控制項,rem 和像素能更適切地表達尺寸。在全域 border-box 政策下,padding-inline 會在受限寬度內建立符合書寫模式的內側間距;無須選擇實體左、右屬性,即可支援由左至右、由右至左與直排文字。
避免在頁面的主要內容上設定固定的 min-width。例如 min-width: 480px 的宣告,會在窄於 480 CSS 像素的 viewport 上強制水平捲動。min()、max() 與 clamp() 可以在不對 viewport 作出不受支援的假設下維持限制:
h1 {
font-size: clamp(2rem, 1.25rem + 3vw, 4rem);
}選擇 Flexbox 或 Grid #
Flexbox 沿著主軸排列一維序列。Grid 定義列與欄,並可跨兩個軸對齊項目。
.toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem;
}flex-direction 決定主軸。justify-* 屬性沿主軸分配空間;align-* 屬性控制交叉軸。align-items 為子項目設定預設值,而 align-self 會覆寫單一項目的設定。flex-flow 結合 flex-direction 與 flex-wrap。
Grid 適合用於欄位應自動形成的卡片:
.cards {
display: grid;
grid-template-columns: repeat(
auto-fit,
minmax(min(18rem, 100%), 1fr)
);
gap: 1rem;
}內部的 min() 可避免 18 rem 的最小值溢出窄於 18 rem 的容器。auto-fit 會折疊空的軌道,讓有內容的卡片使用可用寬度。
當 Grid 內容必須允許縮小到其 intrinsic minimum 以下時,使用 minmax(0, 1fr):
.sidebar-layout {
display: grid;
grid-template-columns: minmax(12rem, 1fr) minmax(0, 3fr);
}針對環境限制加入媒體查詢 #
媒體查詢應在內容不再適合時引入版面配置變更:
@media (width < 48rem) {
.sidebar-layout {
grid-template-columns: 1fr;
}
}Range syntax 可直接表達邊界。常見的媒體特性包括 width、height、orientation、aspect-ratio、resolution、prefers-color-scheme、prefers-reduced-motion、hover 與 pointer。
輸入特性很重要,因為狹窄的觸控螢幕與狹窄的桌面視窗並不提供相同的互動方式:
@media (hover: hover) and (pointer: fine) {
.menu-item:hover {
text-decoration: underline;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto;
animation-duration: 1ms;
animation-iteration-count: 1;
transition-duration: 1ms;
}
}不要使用 hover: none 證明裝置是手機。混合式裝置可能具備多種輸入機制。
使用容器查詢實作可重複使用的元件 #
元件可能出現在寬的頁面欄位中,也可能出現在狹窄的側邊欄中。因此,相較於 viewport,元件自身可用的空間更有用:
.card-region {
container-type: inline-size;
}
.card {
display: grid;
gap: 1rem;
}
@container (width >= 32rem) {
.card {
grid-template-columns: 10rem minmax(0, 1fr);
}
}Containment 應放在查詢元件的祖先元素上。避免查詢同一元素的尺寸,同時又讓查詢所改變的樣式作用於該元素,因為這會建立循環 sizing logic。
容器查詢會設定後代元素的樣式,而不是查詢容器本身。子項目仍可能因其 intrinsic minimum sizes 而溢出,因此在內容必須縮小的位置套用 min-inline-size: 0 或適當的 wrapping policy。
測試版面配置行為 #
應在內容開始換行、溢出或留下過多空間的寬度下測試,而不只是測試命名的裝置預設值。請包含:
- 長單字、URL、翻譯文字與較大的字型設定。
- 鍵盤焦點,以及至少放大至 200% 的縮放。
- 減少動態效果與兩種色彩配置。
- 粗略與精細指標。
- 空、最小與最大資料集。
響應式版面配置會在連續的寬度範圍內保持有效,而不是在少數幾張螢幕擷取畫面之間切換。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)