ナローなビューポートでのポップオーバーのはみ出しを修正

shoelace-style/webawesome

<wa-popover> が狭いビューポートで水平方向にはみ出し、意図しないスクロールを引き起こすバグを修正しました。.body 要素の幅と最大幅の計算式を見直し、ビューポート幅を上限とする制約を追加しています。

背景

<wa-popover>.body 要素にはこれまで width: max-content が適用されており、コンテンツが要求する幅をそのまま採用していました。ビューポートが十分に広い場合は問題ありませんが、#2333 で報告されたように、幅の狭いモバイル表示(例: 392px)ではポップオーバーがビューポートを超えて拡張し、水平スクロールが発生していました。

問題の根本は max-content が親コンテナやビューポートの制約を無視してコンテンツの自然な幅を優先するCSSキーワードであることにあります。ポップオーバーが表示されると <body> の幅が広げられ、閉じるまでスクロール状態が継続するという挙動が確認されています。Windows・Android を問わず、Chrome・Firefox・Brave のすべてで再現していました。

技術的な変更

.body 要素のCSS定義を2箇所修正することで、ビューポートを超えないよう上限を設けました。

変更前:

.body {
  display: flex;
  flex-direction: column;
  width: max-content;
  max-width: var(--max-width);
  ...
}

変更後:

.body {
  display: flex;
  flex-direction: column;
  width: auto;
  max-width: min(var(--max-width), 100vw);
  ...
}

widthmax-content から auto に変更したことで、要素は利用可能なスペースの範囲内で自然に広がるようになりました。max-width には min() 関数を使い、var(--max-width)100vw のうち小さい方が適用されます。これにより、ビューポートが十分に広い場合は既存の --max-width カスタムプロパティが機能し続け、狭い画面ではビューポート幅が自動的に上限として機能します。

ドキュメントのサンプルコードにも修正が加えられています。placement の例で使われていたフレックスコンテナに flex-wrap: wrap が追加され、モバイル幅でボタン群が折り返されるようになりました。また、autofocusの例の <wa-textarea>rows3 から 2 に調整されています。

設計判断

min() CSS関数による二重制約が採用された点が本修正の核心です。--max-width カスタムプロパティを廃止したり、JavaScriptでビューポート幅を動的に計算したりするのではなく、CSSの min() 関数を使って既存の設計を維持しつつビューポート制約を追加する形を選んでいます。

ただし、現状の修正では margin 分が考慮されていません。PR本文には「ポップオーバーのマージン分を差し引いた幅に合わせる」という意図が記されており、100vw から余白を引いた値(例: calc(100vw - 2 * var(--margin)))を使う形が理想ですが、今回のdiffでは 100vw がそのまま採用されています。マージンを考慮した場合でも、CSSカスタムプロパティを通じて同様の式で対応できる余地は残っています。

まとめると、CSSのみで完結する変更であるため、JavaScriptのロジックや既存のカスタムプロパティインターフェースへの影響はなく、--max-width を独自に設定しているユーザーにとっても後方互換性が保たれています。

まとめ

width: max-content というビューポートを無視する定義を width: auto に変更し、min() でビューポート幅を上限として追加したことで、ナローな画面でのポップオーバーのオーバーフローが解消されました。CSSの標準機能のみで既存のカスタマイズ性を維持しながら不具合を修正した、シンプルかつ影響範囲の小さい判断です。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
d5fee4d4

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)の3部構成が明確に守られています。必須要素がすべて含まれており、理想的な構成です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```typescript:filepath)とGitHubのIssue/PRリンク記法([#2333](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

CSSの専門用語(max-content, min(), vw)を前提としており、冗長な説明がなく、専門知識を持つエンジニアという対象読者に適合しています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論で構成され、各段落はトピックセンテンスで始まっています。1段落1トピックの原則と適切な段落長が守られており、非常に読みやすいです。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事で引用されている`popover.styles.ts`のCSS変更点、および`popover.md`のサンプルコードの変更点(`flex-wrap`, `rows`)は、提供されたDiff情報と完全に一致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`width: max-content`, `min()`, `100vw`, `CSSカスタムプロパティ`などの技術用語が正確かつ文脈に即して適切に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

`width: auto`と`max-width: min(...)`への変更がもたらす効果(ビューポート幅を上限とする制約)について、技術的に正確かつ論理的に説明されています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内の主張はすべてPRのタイトル、Description、Diff内容によって裏付けられています。特に「設計判断」でPRのDescriptionと実際のdiffの差異(marginの考慮)に触れており、ハルシネーションではなく深い分析がなされています。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#2375)、Issue番号(#2333)、`textarea`の`rows`属性値など、記事中の数値や固有名詞はすべて正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「ナローなビューポートでのポップオーバーのはみ出しを修正」は、元のPRのタイトル「Fix popover on narrow screens」の内容を正確に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

バージョン情報やリリース予定など、PR情報に基づかない外部知識の捏造は見られません。技術的な解説は、PRの変更内容を理解するために必要な範囲に留まっています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「これまで〜だった」「〜を修正しました」など、過去の状況と今回の変更を区別する時間表現が適切に使用されており、歪曲はありません。