プロンプトとコンテキスト
デザインツールでツールバーのレイアウトを維持しながらキャンバスを拡大縮小する必要があります。レイアウト、オーバーフロー、イベント座標、アクセシビリティの観点から CSS zoom と transform: scale() を比較し、ネストされたズームをどのようにデバッグするかを説明してください。
面接官がテストしていること
- レイアウトに影響するズームと、描画(paint)のみに影響するトランスフォームの違いを理解しているか。
- スクロールコンテナ、ポインタ座標、フォーカス、ブラウザのズーム、ネストされたズームの処理能力。
- スクリーンショットから感覚で選ぶのではなく、実際のシナリオに基づいて選択を検証できるか。
最初に明確にすべき質問
- 対象は通常のページコンテンツ、編集可能なキャンバス、それとも読み取り専用のプレビューですか?
- ズームはレイアウト空間、スクロール範囲、ヒット領域を変更する必要がありますか?
- キーボードナビゲーション、スクリーンリーダー、ブラウザズーム、ハイコントラストに対応する必要がありますか?
30秒で答える要約
ズームがレイアウトやスクロール空間を変更する必要がある場合は、CSS zoom を検討します。視覚的な変更のみで兄弟要素の位置を固定する必要がある場合は、transform: scale() を検討し、transform-origin、ヒットテスト、スクロールを明示的に処理します。zoom はレイアウトに影響しますが、scale() はレイアウトの再計算をトリガーしません。currentCSSZoom はネストされた CSS zoom 値の実効積(effective product)を取得できますが、ブラウザのズームやトランスフォームとは別々に計測されます。
ステップごとの詳細解説
1. ズームのセマンティクスを定義する
ページの可読性のためのズームは、CSS でユーザー設定を上書きするのではなく、ブラウザやシステムのコントロールを使用すべきです。キャンバスエディタには、アプリケーション固有のスケールと、キャンバス座標とビューポート座標の間の明示的な変換が必要です。これら2つの状態を混同してはいけません。
2. zoom のレイアウトへの影響を理解する
CSS zoom は対象を拡大し、ページレイアウトに影響を与えるため、兄弟要素の位置、サイズ計算、オーバーフロー範囲が変化する可能性があります。対応するレイアウト空間を占有すべきコンテンツには適していますが、最小幅やスクロールバーの挙動をテストする必要があります。
3. transform: scale の描画への影響を理解する
transform: scale() は兄弟要素のリフローを引き起こすことなく、描画と変形後の視覚的境界のみを変更します。プレビューや安定した外部レイアウトには適していますが、transform-origin や視覚座標とイベント座標の間の変換を明示的に処理する必要があります。
4. コードの境界を明確に保つ
.preview-zoom {
zoom: var(--preview-zoom, 1);
}
.canvas-visual {
transform: scale(var(--canvas-scale, 1));
transform-origin: top left;
}1つのコンポーネントに誤って両方の拡大比率を重ねて適用しないようにしてください。スケール状態はキャンバスコントローラーの近くに保持し、ツールバーまたはキャンバスコンテンツがそれを継承するかどうかを個別に決定します。ルートでの zoom によってナビゲーションやダイアログのサイズが予期せず変わらないようにする必要があります。
5. 座標、フォーカス、スクロールを処理する
getBoundingClientRect()、ポインタ座標、スクロールオフセットを使用してトランスフォームを算出し、対象のブラウザで検証します。フォーカスリング、ドラッグハンドル、キーボードナビゲーションは常に視認可能である必要があります。視覚的なトランスフォームスケーリングによってコンテナのスクロール領域が自動的に拡大されることはありません。
6. ネストされたズームをデバッグする
Element.currentCSSZoom は、要素およびその祖先要素における CSS zoom の実効積を報告します。これにより、ログやデバッグツールでコンテンツが複数回拡大されて表示される理由を特定しやすくなります。これはブラウザのページズームやトランスフォームスケールを合算した値ではないため、それらは個別に記録してください。
7. アクセシビリティとパフォーマンスのチェックを実行する
ブラウザのズーム、システムのフォント設定、キーボード操作、スクリーンリーダーの読み上げ順序、ハイコントラスト、視覚効果の抑制(reduced motion)をテストします。大規模または頻繁なズーム変更は、レイアウトおよび描画コストを増大させる可能性があります。スライダーのプレビューをスロットル処理し、操作完了時に確定値を保存するようにします。
模範解答
まず、ズームがレイアウト空間を変更する必要があるかどうかを判断します。スクロールや兄弟要素の位置を変更する必要がある場合は zoom を検討します。ツールバーを固定したままキャンバスのみを視覚的に拡大したい場合は transform: scale() を使用し、原点、スクロール、ポインタ座標を処理します。キャンバスの状態がブラウザのページズームを変更したり、ダイアログが誤ったスケールを継承したりしないようにすべきです。ネストされた CSS zoom のデバッグには currentCSSZoom を使用しますが、トランスフォームやページズームは個別に記録します。その上でキーボードフォーカス、スクリーンリーダー、スクロール、DPI、パフォーマンス、モバイルデバイスでの挙動をテストします。
よくある間違い
zoomとscale()は視覚的なサイズを変更するだけであると思い込むこと。- トランスフォームスケーリングによってレイアウトとスクロール範囲が自動的に拡張されると期待すること。
- キャンバスの拡大比率をルート要素に適用してしまい、ツールバー、ダイアログ、ナビゲーションまでスケーリングしてしまうこと。
- スケーリング後のポインタ座標変換やフォーカスの視認性を無視すること。
- currentCSSZoom を、トランスフォームやブラウザのページズームまで含んだ合計値として扱ってしまうこと。
追加の質問と回答
どのような場合に CSS zoom を避けるべきですか?
ユーザーの可読性のためには、ブラウザやシステムのコントロールを使用してください。ブラウザ間の挙動の違い(マトリクス)やレイアウトへの副作用が許容できない場合は、通常のレイアウト、コンテナクエリ、またはアプリケーション座標変換を使用します。
変形後の視覚的境界がコンテナを超えた場合はどうしますか?
クリッピングとスクロールを意図的に定義し、変形後の境界を計測して、フォーカスやドラッグハンドルが常に視認できるようにします。overflow: hidden だけで問題を隠蔽しないようにしてください。
なぜポインタ座標がずれるのですか?
イベント座標は通常ビューポート基準ですが、キャンバス座標ではスクロールと移動(translation)を減算し、アプリケーションのスケール値で除算する必要があります。この変換をテスト済みの単一の関数にまとめ、さまざまな transform-origin に対応させます。
ネストされたズームをどのように制御しますか?
適用範囲を制限し、スケール状態を一元管理し、各レイヤーと currentCSSZoom をログに記録し、祖先の状態を認識せずにコンポーネントが比率を乗算しないようにします。
ブラウザのページズームはどのようにテストしますか?
100%、125%、200% でリフロー、キーボード順序、テキストの欠落、横スクロールをチェックします。ページズームとアプリケーションのキャンバスズームは、別々の受け入れ基準として管理します。
面接でこの選択をどのように定量化して説明しますか?
対象デバイス上でレイアウトの移動、スクロール範囲、ヒットテストの誤差、フォーカスの視認性、フレームタイム、入力レイテンシを比較し、製品のセマンティクスに合致するプロパティを選択します。