課題とコンテキスト
マーケティング用カードにおいて、コンテナ幅に応じて変化する曲線のエッジが必要です。デザインにはパスが用意されていますが、その装飾によってコンテンツ、キーボードフォーカス、または古いブラウザでのレイアウトが壊れてはなりません。shape()をclip-pathとともに使用する方法を説明し、path()およびpolygon()と比較した上で、プログレッシブエンハンスメントの計画を提示してください。
面接官が見ているポイント
shape()がSVGパス文字列ではなく、CSSの基本形状(basic-shape)関数であることを理解しているか。- 単位、CSS演算、コンテナサイズ、およびブラウザのサポート状況の違いを適切に扱えるか。
- セマンティックなコンテンツ、フォーカス、および読み取り可能なフォールバックを維持しながら、クリッピングを装飾として扱えるか。
最初に確認すべき質問
- この形状は純粋な装飾ですか、それとも情報、ヒット領域、あるいは読み上げ順序を伴うものですか?
- 対象とするブラウザ環境では、広く普及していないCSS Shapes Level 2の機能を使用することが許可されていますか?
- 非対応の場合、長方形、
polygon()による近似、または画像アセットのいずれが許容されますか?
30秒での回答
通常のボックスモデルでコンテンツをレイアウトし、視覚的なエンハンスメントとしてclip-path: shape(...)を追加します。shape()はCSSの単位や演算を受け付けるため、レスポンシブなジオメトリに適しています。一方、path()はSVGパス文字列を使用し、polygon()はフォールバックが容易なものの曲線を近似することしかできません。@supportsや機能検出によってエンハンスメントを適用し、読み取り可能な長方形を維持した上で、クリッピングによってフォーカス、ヒットターゲット、セマンティックなコンテンツが隠れないことをテストします。
ステップごとの詳細解説
1. コンテンツとクリッピングを分離する
見出し、本文、ボタンを通常のDOM順序で維持します。clip-pathは描画領域を変更するものであり、コンテンツを隠したり読み上げ順序を変更したりするべきではありません。背景、エッジ、イラストを装飾レイヤーに配置し、コンテンツレイヤーはスクロール可能かつフォーカス可能な状態を保ちます。
2. なぜ shape() を選ぶのか
shape()はCSSスタイルのコマンドを使用し、パーセンテージ、長さ、CSS演算を組み合わせることができます。SVGのpath()文字列と比較して、コンテナの寸法やデザイントークンに合わせて調整するのが容易です。polygon()と比較して、曲線やより高度なパスコマンドを表現できます。
3. スコープを絞ったエンハンスメントを記述する
.card {
background: var(--surface);
overflow: clip;
}
@supports (clip-path: shape(from 0 0, line to 100% 0, close)) {
.card {
clip-path: shape(
from 0 0,
line to 100% 0,
line to 100% 82%,
curve to 0 100% with 52% 88%,
close
);
}
}コードブロック内のコマンドは説明用のものです。本番の構文は対象ブラウザと仕様に合わせて確認する必要があります。基本ルールで実用的な色、スペーシング、テキストを提供しているため、エンハンスメントが適用されなくてもカードが空白になることはありません。
4. フォールバックレイヤーを設計する
最も安全なフォールバックは長方形です。polygon()がサポートされている環境では、エッジを近似できます。曲線が不可欠な場合は、CSSの色とテキストのコントラストを維持しながら圧縮された背景アセットを使用します。未テストの複雑なパスのみに依存したレイアウトにはしないでください。
5. レスポンシブなサイズとオーバーフローに対処する
主要なポイントをパーセンテージとコンテナ寸法で表現し、極端に狭い/広いコンテナ、横向き表示、高ズーム状態でテストします。clip-pathは描画領域を小さくすることはできますが、追加のレイアウトスペースを確保するわけではありません。コンテンツには依然としてパディング、最小の高さ、スクロール戦略が必要です。
6. アクセシビリティの境界を検証する
クリッピングによってDOMのセマンティクス、スクリーンリーダーの順序、キーボードの順序が変更されることはありませんが、フォーカスリング、エラーメッセージ、またはポインタターゲットを視覚的に覆ってしまう可能性があります。キーボードナビゲーション、ズーム、スクリーンリーダー、ハイコントラストをテストし、必要に応じてクリッピングされていないラッパーにフォーカススタイルを適用します。
7. モーションとパフォーマンスコストを管理する
形状をアニメーション化する場合は、不快感を与えたりコンテンツを覆い隠したりしないようにし、prefers-reduced-motionを尊重します。低スペック端末や長いリストでの描画コストに注意してください。継続的な複雑な再描画よりも静的な装飾の方が好まれます。
模範回答
まずカードに通常のボックスモデルのレイアウトを完了させ、見出し、本文、ボタンのセマンティクスを維持した上で、clip-pathを装飾としてのみ使用します。shape()はCSSの単位や演算を受け付けるためレスポンシブなジオメトリに適しています。path()はSVG文字列に近く、polygon()は保守的な近似に適しています。@supportsでエンハンスメントを制御し、非対応時には長方形や検証済みの近似を維持し、極端な幅、ズーム、キーボードフォーカス、スクリーンリーダー、ハイコントラスト、視覚効果の抑制(reduced motion)をテストします。クリップされたエッジがフォーカスリングやヒットターゲットを覆い隠してはなりません。
よくある間違い
shape()を、SVGのpath()文字列をそのまま受け付ける構文として扱ってしまうこと。- エンハンスメントのみを記述し、読み取り可能な長方形の基本スタイルを用意しないこと。
- クリップエッジがボタン、エラーメッセージ、またはフォーカスインジケーターを覆ってしまうこと。
- すべてのコンテナ幅やテキスト長に対して固定ピクセルのジオメトリを使用すること。
- 対象環境の策定や機能検出を行わずに、普遍的なサポートを謳うこと。
フォローアップ質問と回答
なぜ1つのSVG画像を使用しないのですか?
固定のブランドアセットであれば、SVGの方が安定している場合があります。CSSの単位、コンテナのレスポンシブ性、テーマのトークンが重要な場合にshape()を選択し、その上でサポート状況、保守性、パフォーマンスを比較検討します。
@supports を通過したのに形状が崩れている場合はどうしますか?
機能検出は構文上のゲートに過ぎず、すべてのパスコマンドが同一に動作することを保証するものではないと捉えます。主要なコマンドに対して実ブラウザのスクリーンショットやインタラクションテストを実施し、よりシンプルなフォールバックパスを用意します。
クリッピングはヒット領域に影響を与えますか?
視覚的なクリッピングは体感上のヒット挙動に影響を与える可能性があるため、対象ブラウザで検証してください。コントロールを大きく保ちフォーカスが目立つようにし、必要に応じてインタラクションレイヤーをクリッピングされていないラッパーに移動します。
テキストを曲線に沿わせる必要がある場合はどうしますか?
clip-pathは領域をクリップするだけであり、パスに沿ってテキストを配置するものではありません。クリッピングをタイポグラフィAPIとして扱うのではなく、別のテキストレイアウト手法を使用するか、コンテンツ構造を変更してください。
ローカライズされたコンテンツはどのようにテストしますか?
最も長い翻訳テキスト、異なるフォントウェイト、アラビア語やCJKの混在、ユーザーによるズームをテストします。形状は装飾であるため、短い英語の文字列がたまたま収まったからといって十分な根拠にはなりません。
どのような場合に shape() の採用を断念すべきですか?
サポート状況、アニメーションのコスト、または視覚的な一貫性が要件を満たせない場合は、polygon()、グラデーション、SVG、または長方形を採用します。新機能を何が何でも擁護するのではなく、採用を見送る条件を明確にしておきます。