網站設計系統 是做什麼的?
負責視覺外觀與效能層級:行動圖形、深色模式與主題代碼。輸出/維護 BRAND.md(範本:new-website 技能的 templates/brand.md)以及該技能 templates/astro/src/styles/global.css 中的代碼區塊。圖片規則如下(透過 Astro 的 astro:assets 使用 WebP/AVIF);images.spec.ts 測試會強制執行這些規則。如需產生圖片資產,請使用 image 技能。
深色模式(一等公民)
- 使用代碼,而非硬編碼顏色。 所有顏色都透過 CSS 自訂屬性流動;淺色模式是
:root的預設值,深色模式則在:root[data-theme="dark"]下覆寫,另外還有一個@media (prefers-color-scheme: dark)區塊給不使用 JavaScript 的訪客。起始模板已包含此確切結構。 - 無 FOUC 腳本 位於
<head>中,會在首次繪製之前從localStorage.theme或系統偏好設定data-theme(已在Base.astro中連接)。切換開關會寫入localStorage.theme(起始模板未附帶任何切換開關;如果你新增一個,請在隱私頁面的第 3 節中說明)。 - 檢查兩種主題的對比度: 每個文字/背景組合都必須通過 WCAG AA 標準(主體文字 4.5:1,大型/UI 元素 3:1)。在淺色模式下通過的顏色在深色模式下通常會失敗——無障礙測試會執行完整的淺色+深色矩陣,因此請務必檢查兩者。
行動與響應式圖形
- 行動優先: 從 360px 開始設計;觸控目標 ≥ 44px;無水平捲軸。請在 360 / 768 / 1280 解析度下驗證(
preview_resize)。 - 使用現代格式: 對於照片,使用 WebP(或 AVIF)而非 JPEG/PNG。
- 尺寸應符合顯示區域,而非原始尺寸。 切勿將 2000px 的圖片用於 80px 的插槽;應產生寬度變體並使用
srcset/sizes(或<picture>)。 - 避免版面位移: 設定明確的
width/height屬性,以便在圖片載入前保留其區域(保護 CLS / LCP)。Astro 的<Image>會自動設定這些屬性;images.spec.ts要求這些屬性(僅使用 CSS 的 aspect-ratio 無法滿足測試要求)。 - 延遲載入 vs 積極載入: 在摺頁以下使用
loading="lazy";LCP/主要圖片(hero image)則使用loading="eager"且搭配fetchpriority="high"(不要對它使用延遲載入)。 - 每張圖片都需要替代文字(僅在純裝飾用途時使用
alt="")。 - 字型: 自託管 woff2 格式,搭配
font-display: swap;僅預載入摺頁以上使用的 1-2 種字型。避免因字型延遲交換而導致的版面位移。
文字長度響應性(翻譯文案)
- 翻譯後文字通常會變長。 德文(以及許多其他語言)通常會比對應的英文文案長 20–35%。一個按鈕、導覽連結或卡片若僅根據英文佔位文字設定大小,當實際翻譯的文案取代它時,便會默默地溢出、難看地換行,或直接截斷。
- 偏愛彈性寬度。 對於任何包含翻譯文字的元件,應使用
min-width/ flex / grid 的auto/fr尺寸設定,而不是根據英文字串設定固定width。 - 溢出 ≠ 寬度: 彈性尺寸設定無法阻止一個單一的長複合名詞(例如
Datenschutzerklärung)衝破狹窄的欄位——這時需要hyphens: auto(透過Base.astro已設定的lang屬性,為每種語言提供正確的斷字規則),再加上overflow-wrap: break-word作為備援方案;起始模板的global.css已將兩者都應用於body上。表格儲存格會關閉斷字功能(請參閱表格章節)。 - 不要僅依賴
white-space: nowrap+text-overflow: ellipsis來處理導覽連結或按鈕標籤——截斷導覽連結通常會造成不良的使用者體驗(訪客無法再辨識連結目的地)。這在截斷是可接受的取捨時(例如表格儲存格)是可行的,但不適用於導覽功能。 - 使用實際的翻譯標籤進行驗證,而非英文佔位文字。 當網站部署了
astro-i18n-setup的LanguageSwitcher.astro或任何雙語/多語言導覽時,請在 360/768/1280 解析度下(使用preview_resize)檢查每種語言實際部署的文案佈局,而不僅僅是英文佔位文字。
表格
所有表格共用一種樣式;頁面上不會有針對表格的佈局 CSS。該樣式存在於起始模板的 src/styles/tables.css 中(由 Base.astro 在 global.css 之後匯入),而 tests/tables.spec.ts 會對其進行檢查。在此章節建立之前製作的網站,需要先複製 tables.css,在其版面中加入匯入行,然後移除每個頁面自己的表格 CSS。
有兩種表格類型,根據儲存格內容區分:
stack(句子):寬度超過 40rem 時為表格;低於此寬度時,每一行會堆疊顯示,行標題作為標題,每個儲存格在其欄位名稱下方。四欄的文字無法在 320px 內共享空間。figures(短數字,在數字儲存格上加上class="num"):在手機上仍保持表格形式,且必須能容納在 320px 內。如果無法容納,請改為stack類型;使用滾動條並非正確的解決方案。stack figures一起使用則是以堆疊佈局顯示數字。
每張表格的標記:
<div class="table-wrap stack" role="region" aria-label="表格顯示的內容" tabindex="0">
<table role="table">
<thead role="rowgroup"><tr role="row">
<th scope="col" role="columnheader">{cols[0]}</th><th scope="col" role="columnheader">{cols[1]}</th>
</tr></thead>
<tbody role="rowgroup">{rows.map((r) => (
<tr role="row"><th scope="row" role="rowheader">{r.item}</th><td role="cell" data-label={cols[1]}>{r.text}</td></tr>
))}</tbody>
</table>
</div>
- 將欄位名稱撰寫一次,放在一個清單中,並將其用於表頭和每個
data-label:堆疊儲存格的標籤必須等於其欄位表頭,測試會比較兩者。figures表格不需要每個儲存格的角色,也不需要data-label。 - 堆疊表格不再是
display: table。角色是對瀏覽器在版面變更時可能失去表格的備援方案;並不會檢查它們在該情況下是否能正常運作。在 Chromium 中,曾經對一個真實表格進行過測量,無障礙樹在沒有這些角色的情況下仍保留了表格結構。 - 在一個儲存格中獨立存在的連結上使用
class="tap",可使其在手機上成為 44px 的觸控目標。nowrap可將短值(例如1, 3, 6)保持在同一行。long-head(與stack一起使用)會在行標題是句子時加寬第一欄。 - 表格儲存格中的單字不會斷字。主體樣式的
hyphens: auto可能會將狹窄的第一欄擠壓成片段(例如 "An-thropic"),因此區塊會在那裡設定hyphens: manual。 - 如果某個頁面的表格來自外部且無法攜帶上述標記,則應將其加入測試規格中的
TABLE_EXEMPT,並附上原因。PAGES則保持完整:網站地圖和llms.txt檢查需要其中的每個有效路由。
tables.spec.ts 檢查的內容:每張表格都位於某一種類型的 .table-wrap 中,並具有其 region、label 和 tabindex;每個表頭儲存格都有 scope="col",每行第一個儲存格是 <th scope="row">,其餘為 <td>;堆疊表格具有其角色,且每個儲存格都有一個與表頭相等的 label;在 360 和 320px 螢幕寬度下,沒有頁面和表格會橫向捲動;在 641px 及以上的寬度下,堆疊表格會再次顯示為表格,顯示其表頭行,且沒有單字被中斷(這會捕捉到像 overflow-wrap: anywhere 這類讓欄位擠壓單字的規則);沒有儲存格具有 hyphens: auto。它還會在首頁上新增的測試用 fixture 上測試 CSS,並同時在兩種主題下使用 axe 進行無障礙檢測,因此即使沒有表格的網站也能證明該區塊是有效的。無頭 Chromium 不會進行斷字,因此斷字保護會讀取計算後的樣式,而非版面。Safari 和 VoiceOver 則不在檢查範圍內。
電子郵件混淆(對爬蟲隱藏地址)
切勿在 HTML 原始碼中放置純文字電子郵件或 mailto:your@addr——爬蟲會在數小時內將其擷取用於發送垃圾郵件。請透過 EmailLink.astro 元件(位於 new-website 技能的 templates/astro/src/components/EmailLink.astro,以及其 lib/obfuscate.ts 輔助程式)來渲染所有地址:地址在建置時會反轉並進行 base64 編碼,然後在瀏覽器中重新組合,因此提供的 HTML 中不包含任何可讀取的地址。不使用 JavaScript 的訪客會看到一個仍可使用的 "name [at] domain [dot] com" 提示。
<EmailLink address="[email protected]" subject="專案諮詢" text="寄信給我們" />
規則:建置後的 HTML 中零個原始 mailto: 連結和零個字面 @ 地址——website-qa 會檢查此項。任何不希望被擷取的電話號碼也適用相同概念。
品牌代碼
將 BRAND.md 的色板對應到代碼區塊中,並保持它們同步。定義:品牌色(固定),以及每個主題的 heading/ink/muted/accent/link/line/bg/bg-soft/surface。強調色和連結顏色必須在兩種主題的背景下都通過 AA 標準,這也是為什麼每個主題都有自己的色值。可選的 website-brand-kit 會進行帶檢查的對應程序:它會讀取 BRAND.md 的表格,將每個文字顏色在兩種主題的每個背景上保持在 4.5:1 的對比度,並將這些值寫入 global.css 的所有三個顏色區塊(淺色、深色,以及給沒有 JavaScript 訪客的深色區塊)。若手動操作,請同時修改這三個區塊。
完成標準
BRAND.md 已填寫完成且與代碼區塊一致;圖片為 WebP 格式、尺寸正確、延遲/積極載入設定正確、具有替代文字;無障礙測試(淺色+深色)通過;版面在 360/768/1280 解析度下保持穩定無位移;每張表格都是 stack 或 figures 類型,且 tables.spec.ts 測試通過。效能數據(FCP/LCP)已在 website-qa 中驗證。版面也需在所有部署語言的實際(非佔位)文案下,於 360/768/1280 解析度下保持穩定,而不僅僅是預設語系。