ウェブサイトのヒーローカルーセル:写真が順番に表示され、それを正直に保つテスト群
ページ上部の写真スペースで、2枚以上の写真が数秒ごとに交代で表示され、それぞれにドットが付いています。簡単そうに見えて実はそうでもありません。ある写真のキャプションが変更のたびにページをジャンプさせたり、淡い写真の上では白いドットが見えなくなったり、スマートフォンではマウスより大きなターゲットが必要だったり、動きのあるコンテンツには独自のアクセシビリティルールがあります。このスキルはコンポーネントを提供し、さらに重要なことに、これらすべてを捕捉するテストも提供します。
なぜこのように構築されているのか(ご自身の言葉でオーナーに伝えてください)
- ページがジャンプしません。 すべての写真が1つの場所を共有し、1つの形状に切り抜かれているため、最初の写真も最後の写真もページの高さは同じです。写真にキャプションやクレジットはありません。それらは、このスキルの元になったサイトでページを動かしていた原因です。クレジットはサイトの画像クレジットページに属します。
- どの写真でもドットを読み取ることができます。 ドットは小さな暗いピルの上に配置されているため、明るい空でも暗い壁でも表示されます。テストは、明るい写真と暗い写真のピクセル上でこれを測定します。
- JavaScriptがなくても動作します。 その場合、写真は縦に並んで表示され、ボタンは表示されません。
- 丁寧に動作します。 マウスが上にあるとき、タブが非表示のとき、キーボードフォーカスが入ったとき、そしてアクセス設定で動きを減らすよう要求している訪問者に対しては最初から停止します。
- 何も保存したり送信したりしません。 Cookie、ストレージ、他サイトへのリクエストは一切ありません。
そして正直な弱点も挙げておきます。オーナーが最初にあなたから聞くべきことです:
- 回転する写真が常に優れたデザインとは限りません。 1枚の強い写真の方が落ち着きがあり、読み込みが速く、誰もイライラさせることがありません。そう伝えてください。決めるのはオーナーです。
- 写真を1枚追加するごとに、スマートフォンでのダウンロード時間が訪問者の負担になります。 各サイズ4種類で3枚の写真は問題ありませんが、10枚は多すぎます。数枚に抑えてください。
- 「ドット」一時停止モードは、見えるコントロールを犠牲にして写真をよりクリーンに表示します(以下の「一時停止」セクションを参照)。
0. これが適切なツールですか?(インストール前に質問してください)
- オーナーは本当に回転表示を希望していますか? 写真が1枚なら、これは不要です。一度、率直に確認してください。
- 写真は何枚で、同じ形ですか? 2〜5枚。形は問いません(それぞれカルーセルの形に切り抜かれます)が、被写体が端にある写真は切り抜きで失われる可能性があります。各写真をカルーセルの形(デフォルトは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 | スクリプト:スライドを1か所に配置、回転、コントロールの処理 |
tests/hero-carousel.spec.ts | hero-carousel.spec.ts | 訪問者が遭遇するカルーセルのテスト(以下のリスト) |
4つすべてをインストールしてください。テンプレートには画像ファイルは含まれていません。写真はサイト独自のもので、プロパティとして渡されます。
仕組みを1段落で説明します。 サーバーはすべてのスライドを縦に並べて送信し、コントロールは非表示にします。スクリプトはインラインスクリプトではなく、サイト独自の public/js/ 下のファイル(これにより、厳格な script-src 'self' でも実行できます)で、スライドを1つのグリッドセルに配置し、コントロールを表示し、表示中のスライドをマークします。どのスライドが表示されているかはデータ属性で示され、CSSが残りの処理(1秒のフェードを含む)を行います。スライドは画像の読み込みが完了したときにのみ表示されるため、遅延や失敗した写真によって空白が生じることはありません。
スペックがチェックする内容(訪問者の視点で、構築されたページ上で):マークアップと各ドットの名前;停止した時計でのミリ秒単位のインターバル;Pauseボタンまたはドットによる停止(ラベルとライブリージョンも含む);キーボードフォーカス(停止、停止維持、Resume);ポインターによるホールドと離脱後の新しいインターバル;reduced motion;非表示のタブ;遅延および失敗した2枚目の画像;JavaScriptなしのページ;1280px、768px、390pxでの高さのジャンプがないこと;表示されていないスライドがキーボードやアクセシビリティツリーから到達できないこと;写真のリンクが機能し、ドットがそれを開かないこと;32pxのターゲット(タッチスクリーンでは44px);すべての写真上のピルに対するドットのコントラストをレンダリングされたピクセルから読み取ること;forced colours;両方のテーマでのaxe;保存や送信がないこと;スクリプトがインラインではなくファイルであること;フェードが途中のフレームで実行され、落ち着くこと、またreduced motionでは実行されないこと。
2. インストール(ブランチ上で、プルリクエストとして:AGENTS.md §2)
- 4つのファイルを§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: 'Short name', href: '/projects/one' }, { image: second, alt: '2番目の写真が示す内容', label: 'Another name' }, ]} />label:カルーセルが何であるかをスクリーンリーダーに伝えます。必須。- 各スライド:
image(インポートされた写真)、alt(写真の内容を説明する文、最低10文字:それ未満だとビルドが停止します)、label(ドットの短い名前)、href(オプション)。 pause:"button"(デフォルト)または"dots"。swap:"instant"(デフォルト)または"fade"。intervalMs:デフォルト6000、2000未満は不可。ratio:デフォルト"16 / 9"。lang:ページ自体の言語。 写真:JPEGまたはPNG、約2400px幅、ページに必要なものに限定(ビルドは各写真の4サイズをAVIF形式で生成し、WebPをフォールバックとします)。最初の写真が最初に読み込まれます(高優先度)。その他は低優先度で読み込まれ、元の位置を保持します。
- 言語。 英語とドイツ語が組み込まれており、コンポーネントはページ自体の言語を使用します(
Base.astroがAstro.locals.langとして渡します)。他の言語の場合:以下の「言語の追加」を最初に参照してください。 tests/hero-carousel.spec.tsで、PAGE(カルーセルがあるページ)、PAUSE、SWAPをページが渡す値に設定します(コンポーネントのデフォルトはbuttonとinstantです。スペックはこれらが明示的に記述されている必要があります)。1つが空の間、スペックは失敗します。LANGは、ページがlangを渡す場合のみ設定します。 コントラストテスト用の写真: スペックはカルーセルの実際の写真を読み取るため、オーナー自身の写真に対してテストされます。すべての写真が暗い場合、「ピル上の白いドット」テストは失敗しません。失敗を確認するには、明るい写真を1枚手動でチェックしてください(§3のミューテーションチェックで行います)。npm run check && npm testを実行します。
一時停止(オーナーが選択する前に読んであげてください)
自動的に開始し、5秒以上継続し、他のコンテンツの横に配置される動きのあるコンテンツは、WCAG 2.2.2、レベルAに該当し、「ユーザーが一時停止、停止、または非表示にするためのメカニズム」を要求します(https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html で参照)。同じページでは、一時停止を「ユーザーの要求によって停止され、ユーザーが要求するまで再開されない」と定義しており、メカニズムが可視である必要があるとは述べていません。また、スライドインジケーターについては議論していません。
pause="button"(デフォルト)。 ドットの横にPauseボタン(停止中はResume)があります。可視で、名前が付けられており、誰も異議を唱えない読み方であり、訪問者が見つけるものです。代償:写真上に小さな単語が表示されます。pause="dots"。 ボタンはありません。ドットを選択するとその写真が表示され、訪問者がリロードするまで回転が停止します。キーボードからフォーカスが入った場合も停止し、reduced motionでは最初から停止状態で開始します。これはおそらく2.2.2の意味でのメカニズムと言えますが、ドットが回転を停止することを訪問者に伝えるものは何もなく、再開する方法もありません。このモードを最初に使用したサイトは、写真をよりクリーンに表示するために、そのことを理解した上でこのモードを選択しました。
このスキルは適合性の結論を導き出しません。「ドット」モードが受け入れられるかどうかは、サイト独自の監査人に委ねられます。オーナーがこのモードを選択した場合は、サイトのドキュメントにその旨と日付を1行記載してください。
言語の追加
その言語の新しいサイトで、またはサイトが後でその言語を追加する場合に使用します。
- 最初にサイトのボイスを読んでください(
CONTENT_GUIDE.md;ドイツ語では呼称の「du」または「Sie」)。テキストはわずかな単語です。言語が許す限り、特定の誰かに語りかけないようにします。 src/components/hero-carousel-text.tsで、TEXTのenエントリを言語の2文字コード(fr-CAではなくfr)でコピーし、すべての値を翻訳します。1つでも欠けているとnpm run checkは失敗します。- §2のステップ3と4に従って、ページとそのテストを設定します。
3. 試してみる(オーナーが)、そしてこのスキルの背後にあるチェック
npm run build && npm run preview の後、またはプルリクエストのプレビューアドレスで、オーナーは:
- 待つ:写真が自動的に変わり、表示中のドットが追従します。
- マウスを上に移動する:停止します。マウスを離す:1インターバル後に再開します。
- スマートフォンで:ドットをタップします(その写真が表示されます)。横スクロールは発生しません。ドットはタップしやすいです。
- ボタンモードで:Pauseを押し、Resumeと表示されるのを確認し、もう一度押します。
このスキルが構築されたチェック。これにより、テンプレートの変更を評価できます。スペックはこれらの各項目に対して1つのテストを保持し、ガードしているものが削除されると各テストは失敗します。テンプレートが変更されたときに手動で1回実行します(CIジョブは新しいサイトにテンプレートをインストールし、使用する設定の3つの組み合わせすべてでスペックを実行します):
HeroCarousel.astro からこれを削除 | このテストが失敗 |
|---|---|
グリッドルール(display: grid、grid-area) | 「スライドは1か所を共有…」 |
写真の aspect-ratio | 同じテスト(4:3の写真は高くなる) |
ピルの background | 「すべての写真上でレンダリング…」(淡い写真上の白は約1:1) |
表示中のドットの border-width: 5px | forced-coloursテスト |
transition ルール | フェードテスト(「途中のフレーム」) |
表示されていないスライドの pointer-events: none | 「写真のリンクが機能する…」(フェード中のスライドがクリックを受け取る) |
表示されていないスライドにスクリプトが設定する inert と aria-hidden(hero-carousel.js) | Tabキーとアクセシビリティツリーのテスト(フェードアウト中のスライドのリンクは、フェード中も到達可能で読み取り可能なまま) |
スクリプトの recover()(表示中の失敗した写真は、存在する(現在または到着時)最初の別の写真に置き換えられる) | 「最初の画像が失敗した場合…」 |
4. プライバシーページと削除方法
カルーセルは何も保存せず、何も送信しません。プライバシーページに追加するものはありません。
削除するには:4つのファイル、<HeroCarousel> ブロック、**およびページから import HeroCarousel の行(それのみが使用していた写真のインポートも含む)を削除します。1枚の写真を戻します。他にこれを参照しているものはなく、PAGES 駆動のスイートも該当ページのみを参照します。
5. このスキルに含まれないもの(誰も想定しないように)
前/次の矢印、スワイプジェスチャー、写真のキャプション、写真のクレジット、ビデオスライド、ページ上の複数のカルーセル(IDが固定されています)、後続写真の遅延読み込み。これらは後で追加可能ですが、最初のバージョンには必要ありません。