網站永遠響應式
一個頁面只有通過 python3 scripts/check_responsive.py 才算完成(無水平滾動、無內容溢出螢幕、觸控目標夠大),測試涵蓋 6 種參考尺寸。此檢查也會在 CI 中執行:破壞響應式的 PR 無法部署。
參考寬度(全部需測試)
| 寬度 | 情境 |
|---|---|
| 320 px | 小型 Android、iPhone SE 縮放模式 |
| 375 px | 標準 iPhone(目標 #1:受眾來自 TikTok) |
| 414 px | 大螢幕手機 |
| 768 px | 平板直向 |
| 1024 px | 平板橫向 / 小型筆記型電腦 |
| 1440 px | 桌上型電腦 |
腳本測試的尺寸:320×640、375×667、414×896、768×1024、1024×600(低螢幕)、1440×900。
CSS 規則
- 行動裝置優先:基礎樣式針對 320 px,然後使用
@media (min-width: …)擴展。斷點:600px、900px、1200px(其他地方不得使用魔術數字;元件可以使用@container)。 - 無固定寬度大於 280 px 而不搭配
min()/max-width: 100%:使用width: min(520px, 100%)。 - 流暢排版使用
clamp():標題clamp(32px, 7vw, 72px),內文 最小 16 px(行動裝置上不得低於此值,否則 iOS 會放大輸入框)。 - 高度:使用
min-height: 100svh(不要用100vh,後者會穿過行動裝置的網址列)。文字區塊禁止使用固定height。 - 側邊邊距:行動裝置上使用 16 px 的排水溝(
space-4),加上env(safe-area-inset-left/right)處理有瀏海的螢幕(viewport 已設定viewport-fit=cover)。 - 長文字:對 URL、指令和檔案名稱使用
overflow-wrap: anywhere;程式碼區塊在區塊內部使用overflow-x: auto,絕不能用在頁面層級。 - 網格:教學卡片使用
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr))。 - 裝飾性元素(
byte/spark區塊、canvas)若溢出:使用position: fixed或父層設overflow: clip,尺寸使用min(vw, px)。 - 觸控:獨立按鈕和連結 ≥ 44 × 44 px(腳本最低限制 24 px,WCAG 2.2),兩個目標之間至少間隔 8 px。不可僅透過
:hover提供資訊:需提供:focus-visible和觸控狀態。 - 影片與 iframe(YouTube):
aspect-ratio: 16 / 9; width: 100%; height: auto;— TikTok 影片使用9 / 16並加上max-width: 360px。
圖片
- 在 HTML 中務必指定
width和height(避免版面偏移 CLS)+ CSS 中的max-width: 100%; height: auto。 - 格式:Logo 和圖示使用 SVG,截圖使用 WebP/AVIF,並搭配
srcset+sizes(例如 480w、960w、1600w)。 - 折線以下使用
loading="lazy"和decoding="async";絕對不用於主要圖片(LCP),後者需使用fetchpriority="high"。 - 教學縮圖:
aspect-ratio: 16 / 9; object-fit: cover。
Viewport(已設定,請勿移除)
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
禁止使用:maximum-scale=1、user-scalable=no(會封鎖縮放,不利於無障礙性)。
動畫與行動裝置效能
- 遵循
prefers-reduced-motion(專案規範)。 - Canvas:限制
devicePixelRatio為 2,並在寬度小於 600 px 時降低密度(已在app.js中實作,請保持此原則)。 - 行動裝置上避免堆疊過重的
backdrop-filter。
檢查
# 使用已啟動的 check-site 容器在 :8088 上,或不帶參數(使用 site/ 的本機伺服器)
python3 scripts/check_responsive.py # 檢查 site/ 中的所有頁面
python3 scripts/check_responsive.py --shots /tmp/rs # 加上每個寬度的 PNG 截圖
如果 scrollWidth > 寬度、有可見元素超出邊界、觸控目標小於 24 px(句子中的連結除外),或內文小於 16 px,腳本會失敗。在推送前請檢查 320 和 375 px 的截圖。