網站英雄輪播:輪流展示的照片,以及確保它們誠實運作的測試
放在頁面頂部的照片區,兩張或更多照片每隔幾秒輪流顯示,每張照片都有一個圓點。看起來簡單,但實際上並不簡單:一張照片上的說明文字會讓頁面在每次切換時跳動;白色圓點在淺色照片上會消失;手機需要比滑鼠更大的觸控目標;而且動態內容本身就有無障礙規範。這個技能提供了元件,更重要的是,提供了能捕獲所有這些問題的測試。
為何這樣設計(用你自己的話告訴業主)
- 頁面永不跳動。 所有照片共用一個位置,裁切為同一形狀,因此第一張照片和最後一張照片的高度相同。照片上沒有說明文字或版權標示:它們正是導致原始網站頁面跳動的原因。版權資訊應該放在網站的圖片版權頁。
- 圓點在任何照片上都能辨識。 它們位於一個小小的深色藥丸形狀上,無論在淺色天空還是深色牆壁上都能顯示。測試會透過像素測量淺色和深色照片上的對比度。
- 沒有 JavaScript 也能運作。 照片會上下排列,且不顯示任何按鈕。
- 行為有禮貌。 當滑鼠懸停、分頁隱藏、鍵盤焦點進入時會停止輪播,並且對要求減少動畫效果的訪客,從一開始就停止輪播。
- 不儲存也不發送任何資料。 沒有 Cookie、沒有儲存空間、沒有對其他網站的請求。
以及誠實的弱點,讓業主先從你口中聽到:
- 旋轉的照片不一定總是更好的設計。 一張強而有力的靜態照片更平靜、載入更快,也不會惹惱任何人。請明確告知;由業主決定。
- 每多一張照片,都會增加訪客在手機上的下載時間。 三張照片各四種尺寸還可以;十張就不行了。請限制在少數幾張。
- 「圓點」暫停模式是用可見的控制項換取更乾淨的照片(參見下方的「暫停」章節)。
0. 這是正確的工具嗎?(安裝前先詢問)
- 業主確定要旋轉嗎? 一張照片完全不需要這些。清楚詢問一次。
- 有幾張照片?它們的形狀相同嗎? 兩到五張。任何形狀都可以(每張照片都會被裁切成輪播的形狀),但主體在邊緣的照片可能會在裁切中遺失:請以輪播的形狀(預設為 16 / 9)和手機的形狀檢查每張照片。
- 照片有連結到任何地方嗎? 任何幻燈片都可以連結到一個頁面(例如一個專案);混合有連結和無連結的幻燈片是可以的(CI 頁面就是這樣做的)。
- 要使用哪種暫停模式? 向業主閱讀下方的「暫停」章節,讓他們選擇。預設值:按鈕。
1. 它為網站添加了什麼
| 檔案 | 來自此技能的 templates/ | 它是什麼 |
|---|---|---|
src/components/HeroCarousel.astro | HeroCarousel.astro | 標記、圓點、樣式 |
src/components/hero-carousel-text.ts | hero-carousel-text.ts | 它說的文字,英文和德文 |
public/js/hero-carousel.js | hero-carousel.js | 指令碼:將幻燈片放置在一個位置、輪播、處理控制項 |
tests/hero-carousel.spec.ts | hero-carousel.spec.ts | 訪客所見的輪播(下方列表) |
安裝所有四個檔案。範本中不包含任何圖片檔案:照片是網站自己的,作為 props 傳入。
一句話說明運作方式。 伺服器發送所有幻燈片,一張疊在另一張下方,並且控制項是隱藏的。指令碼(網站自己的檔案,位於 public/js/ 而不是內嵌指令碼,這樣嚴格的 script-src 'self' 才能讓它執行)隨後將所有幻燈片放置在一個網格儲存格中,顯示控制項,並標記當前顯示的幻燈片。哪張幻燈片正在顯示由一個 data 屬性決定;CSS 負責其餘部分,包括一秒鐘的淡入效果。幻燈片僅在其圖片完全載入後才顯示,因此載入延遲或失敗的照片永遠不會留下空白位置。
規格測試的內容(以訪客視角,在已建置的頁面上):標記和每個圓點的名稱;以凍結時鐘測試毫秒級的間隔;暫停按鈕或圓點停止輪播,以及標籤和即時區域;鍵盤焦點(停止輪播、保持停止、繼續);指標懸停以及離開後重新開始倒數計時;減少動畫效果;隱藏的分頁;延遲載入和載入失敗的第二張圖片;沒有 JavaScript 的頁面;在 1280、768 和 390 px 寬度下沒有高度跳動;未顯示的幻燈片無法透過鍵盤或無障礙樹訪問;照片的連結有效,且圓點永遠不會打開它;32 像素的目標(觸控螢幕上為 44 像素);圓點在藥丸形狀上,覆蓋每張照片,從渲染的像素讀取;強制色彩模式;兩種主題下的 axe 無障礙檢測;沒有儲存或發送任何資料;指令碼是一個檔案,不是內嵌的;淡入效果在動畫中途的影格上執行並穩定下來,並且在減少動畫效果下不會執行。
2. 安裝(在分支上,作為合併請求:AGENTS.md §2)
- 將這四個檔案複製到 §1 中指定的位置(先執行
mkdir -p public/js)。 - 將輪播放在頁面上,位於該頁面的
<Base>元件內,靠近頂部:--- import HeroCarousel from '../components/HeroCarousel.astro'; import first from '../assets/hero-1.jpg'; import second from '../assets/hero-2.jpg'; --- <HeroCarousel label="我們作品的相片" slides={[ { image: first, alt: '第一張照片顯示的內容', label: '簡短名稱', href: '/projects/one' }, { image: second, alt: '第二張照片顯示的內容', label: '另一個名稱' }, ]} />label:輪播是什麼,給螢幕報讀軟體使用。必填。- 每個幻燈片:
image(導入的照片)、alt(描述照片內容的句子,至少 10 個字元:少於此長度建置會失敗)、label(圓點的簡短名稱)、href(可選)。 pause:"button"(預設)或"dots"。swap:"instant"(預設)或"fade"。intervalMs:預設 6000,不得低於 2000。ratio:預設"16 / 9"。lang:頁面自己的語言。 照片:JPEG 或 PNG,寬度約 2,400 px,保持在頁面所需的數量(建置會為每張照片製作四種尺寸,AVIF 格式,WebP 作為備用)。第一張照片優先載入(高優先級);其他照片以低優先級載入並保留其位置。
- 語言。 內建英文和德文,元件會使用頁面自己的語言(
Base.astro將其作為Astro.locals.lang傳遞)。其他語言:請先參閱下方的「新增語言」。 - 在
tests/hero-carousel.spec.ts中,將PAGE(包含輪播的頁面)、PAUSE和SWAP設定為頁面傳遞的值(元件的預設值是button和instant;測試需要明確寫出)。如果其中一個是空的,測試會失敗。僅在頁面傳遞lang時才設定LANG。 對比度測試的照片: 測試會讀取輪播的真實照片,因此它使用的是業主自己的照片。如果所有照片都是暗色系,則「白色圓點在藥丸形狀上」的測試無法失敗;若要查看它失敗,請手動加入一張淺色照片進行檢查(§3 中的突變檢查會執行此操作)。 npm run check && npm test。
暫停(在業主選擇之前,向他們閱讀此內容)
自動啟動、持續超過五秒且與其他內容相鄰的動態內容,屬於 WCAG 2.2.2,A 級,該規範要求「使用者能夠暫停、停止或隱藏它的機制」(請閱讀 https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html)。同一頁面將 暫停 定義為「由使用者請求停止,並且在使用者請求之前不會恢復」,並且沒有說明該機制必須是可見的。它沒有討論幻燈片指示器。
pause="button"(預設)。 在圓點旁邊有一個暫停按鈕(停止時顯示繼續按鈕)。可見、有命名、是沒有人會爭論的解讀,也是訪客會找到的方式。它的代價:照片上的一個小文字。pause="dots"。 沒有按鈕。選擇一個圓點會顯示該張照片並停止輪播,直到訪客重新載入頁面;鍵盤焦點進入輪播也會停止它,並且在減少動畫效果模式下,輪播一開始就是停止的。這很可能符合 2.2.2 意義上的機制,但沒有任何東西告訴訪客圓點可以停止輪播,而且也沒有辦法恢復輪播。第一個使用此模式的網站選擇它是為了更乾淨的照片,並且充分了解這一點。
此技能不做出任何合規性結論:是否接受「圓點」模式由網站自己的稽核員決定。如果業主選擇它,請在網站的文件中寫下一行,並附上日期。
新增語言
當網站使用新語言時,或者當網站後續增加語言時。
- 首先閱讀網站的語調指南(
CONTENT_GUIDE.md;在德文中要注意正式/非正式用語)。這些文字只有幾個單詞:在語言允許的情況下,使用非特定人稱。 - 在
src/components/hero-carousel-text.ts中,複製TEXT物件的en條目,放在語言的兩位字母代碼(例如fr,而不是fr-CA)下,並翻譯每個值;如果缺少任何值,npm run check會失敗。 - 頁面及其測試,如 §2 步驟 3 和 4 所述。
3. 親自試用一次(業主),以及此技能背後的檢查
在執行 npm run build && npm run preview 之後,或者在合併請求的預覽網址上,業主可以:
- 等待:照片會自動切換,當前顯示的幻燈片對應的圓點會亮起。
- 將滑鼠移到輪播上:輪播會暫停。移開滑鼠:輪播會在一個完整的間隔時間後繼續。
- 在手機上:點擊圓點(會顯示該圓點對應的照片);沒有橫向滾動;圓點易於點擊。
- 在按鈕模式下:按下暫停,看到它顯示繼續,再次按下。
此技能建置時使用的檢查,以便評估對範本的變更:測試套件為每一項都包含一個測試,當其保護的功能被移除時,每個測試都會失敗。當範本變更時,請手動執行一次(CI 任務會將它們安裝在一個全新的網站中,並以其使用的所有三種設定組合執行測試套件):
從 HeroCarousel.astro 中移除此項目 | 此測試會失敗 |
|---|---|
網格規則(display: grid, grid-area) | "幻燈片共用一個位置..." |
照片上的 aspect-ratio | 同一個測試(4:3 的照片會更高) |
藥丸形狀的 background | "在每張照片上渲染..."(白色在淺色照片上大約是 1:1) |
當前顯示圓點上的 border-width: 5px | 強制色彩模式測試 |
transition 規則 | 淡入效果測試("動畫中途的影格") |
未顯示幻燈片上的 pointer-events: none | "照片連結到其頁面..."(淡出的幻燈片會攔截點擊) |
指令碼在未顯示幻燈片上設定的 inert 和 aria-hidden(hero-carousel.js) | Tab 鍵和無障礙樹測試(正在淡出的幻燈片的連結在淡出期間仍然可達且可讀) |
指令碼的 recover()(當前顯示的照片載入失敗時,由第一張已存在的其他照片取代,無論是現在還是將來載入完成) | "第一張圖片載入失敗..." |
4. 隱私頁面,以及移除方式
輪播不儲存也不發送任何資訊:無需在隱私頁面添加任何內容。
要移除它:刪除這四個檔案,從頁面中刪除 <HeroCarousel> 區塊以及 import HeroCarousel 這行程式碼(以及僅由它使用的圖片導入);放回一張照片。沒有其他東西會參照它,除了由 PAGES 驅動的、僅看到該頁面的測試套件。
5. 此技能不包含的內容(以免有人假設)
上一張/下一張箭頭、滑動手勢、照片上的說明文字、照片上的版權標示、影片幻燈片、頁面上超過一個輪播(其 id 是固定的)、後續照片的延遲載入。每一項都可以在之後添加;但第一個版本都不需要。