HTML / CSS公開 約9分

カード幅でレイアウトを切り替える:コンテナークエリーの測る箱を決める

広い本文欄と細いサイドバーに同じカードを置くとき、画面幅だけでは配置を選べません。外側の幅を測り、内側のレイアウトを切り替える完成例で、境界と基本の一列表示を確かめます。

この記事の目次
  1. 画面幅ではなく、置き場所の幅に質問する
  2. 同じ案内を、480pxと280pxの枠に置く
  3. 外側で測り、内側の配置だけを変更する
  4. 切り替わらないときは、測る箱を探す
  5. ページ全体の変更には、別の判断を残す
  6. 親だけを399px、400pxへ変える

広い画面ではカードを横並びにしたい。しかし同じページの細いサイドバーにも、同じカードが入る。画面幅だけで切り替えると、サイドバーの中まで横並びになり、本文が細くなります。カード幅でレイアウトを切り替えるなら、その部品が置かれた親の幅を条件にします。

HTMLの親子関係とCSS Gridを少し書ける人向けに、架空の資料室の案内カードを二つ配置します。画面全体の幅を固定したまま、広い置き場所と狭い置き場所で異なる配置になる例です。文字やリンクは共通にし、内容の省略で幅を合わせないようにします。

画面幅ではなく、置き場所の幅に質問する

メディアクエリーのwidthはビューポート、つまりページの表示領域を条件にします。画面が1200pxなら、本文欄の中でもサイドバーの中でも同じ条件です。一覧の列数を変える記事では画面幅が判断材料でしたが、再利用する部品にはそれだけでは足りない場合があります。

コンテナーのサイズクエリーでは、祖先の要素を測る対象として宣言し、その寸法に応じて子のスタイルを変えます。この例では外側のslotが測る箱、内側のcardが配置を変える箱です。カード自身の幅を条件にして、同じカード自身を変更する構成にはしません。

MDNのコンテナークエリーの説明に従い、inline-sizeで横書きのインライン方向のサイズを対象にします。高さを含むsizeを何となく選ぶと、高さの決め方にも影響するため、この用途では必要な方向だけを宣言します。

同じ案内を、480pxと280pxの枠に置く

次の図は広い枠と狭い枠の比較です。どちらも「資料室の利用案内」という同じ情報を持ちます。広い枠だけが二列になり、狭い枠では説明とリンクを縦に読む形を残します。

同じ画面内で、広い親では説明とリンクが横並びになり、狭い親では縦に並ぶ比較図

cards.htmlとして次を保存し、ブラウザーで開いてください。リンク先は同じページ内の利用条件です。外部サイトや画像を用意せず、配置と読む順番だけを確認できます。

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>置き場所の違うカード|練習</title>
<style>
* { box-sizing: border-box; }
body { margin: 16px; font-family: sans-serif; line-height: 1.8; color: #222; }
main { max-width: 800px; margin: auto; }
.slot { container-type: inline-size; container-name: guide; margin-block: 24px; }
.wide { width: 100%; max-width: 480px; }
.narrow { width: 100%; max-width: 280px; }
.card { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px;
        border: 2px solid #555; padding: 16px; overflow-wrap: anywhere; }
h2, p { margin: 0; }
a { align-self: start; color: #174ea6; }
a:focus-visible { outline: 3px solid #174ea6; outline-offset: 3px; }
@container guide (min-width: 400px) {
  .card { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
}
</style>
</head>
<body>
<main>
<h1>資料室の案内(架空の練習)</h1>
<div class="slot wide">
  <article class="card">
    <div><h2>資料室の利用案内</h2><p>閲覧できる資料と利用条件を確認できます。</p></div>
    <a href="#conditions">利用条件を読む</a>
  </article>
</div>
<div class="slot narrow">
  <article class="card">
    <div><h2>資料室の利用案内</h2><p>閲覧できる資料と利用条件を確認できます。</p></div>
    <a href="#conditions">利用条件を読む</a>
  </article>
</div>
<section id="conditions">
  <h2>利用条件</h2><p>この練習では、資料は室内で閲覧する設定です。</p>
</section>
</main>
</body>
</html>

slotに付けたguideは、クエリーで参照するコンテナー名です。途中に別のコンテナーが追加されても、どの種類の祖先を測りたいかを示せます。同名の祖先が重なる構造では、対象になる祖先も調べ直します。名前を付ければ常に最外側の箱を選ぶわけではありません。

400pxは、今回の見出し・説明・リンクが二列でも読めるかを確かめるための境界です。スマートフォンとパソコンの境目ではありません。リンクが長くなるなら、その長さでも境界直後に収まるか確認し、必要に応じて切り替え幅を上げます。

外側で測り、内側の配置だけを変更する

基本のcardは一列で、条件を満たしたときだけ二列へ上書きします。コンテナークエリーに対応しない環境でも、基本の縦並びで本文を読める設計です。新しい指定が使えることを、情報へ到達する前提にしません。

wideとnarrowは、測る箱の幅を決めています。cardへ直接480pxを指定すると、狭い親へ置いた際にもその幅を要求してしまいます。この例では外側が配置幅を提供し、内側はその中に収まる、という役割を分けています。

また、二列になってもHTMLの順番は説明、リンクのままです。Gridで見た目を整えるために、リンクを先に読み上げる構造へ変える必要はありません。狭くなったら縦へ戻すだけで、利用条件を読むという操作は両方に残します。

切り替わらないときは、測る箱を探す

一つ目の失敗は、container-typeをcard自身へ付け、同じcardをクエリー内で変えようとすることです。自分自身を測って自分のスタイルを切り替える想定になっています。修正では完成例のslotを測る対象に戻し、その子のcardを変更します。広い枠だけが二列になるか再確認します。

二つ目は、サイズを測る宣言を置かず、@containerだけを追加することです。意図した祖先がサイズクエリーの対象にならず、画面を広げても縦並びのままになります。slotの計算済みスタイルでcontainer-typeがinline-sizeになっているかを調べ、宣言の有無や上書きを直してください。

宣言があるのに効かない場合は、CSSの適用元を調べる記事の手順で、別の規則が上書きしていないかも切り分けます。幅を際限なく広げるより、条件に使われる箱と、変更する要素を先に特定する方が調査の対象を絞れます。

三つ目は、クエリーを@mediaへ戻して問題を隠すことです。広い画面のサイドバーでは再び横並びになります。完成例の二つを同時に表示し、一方だけ変わることを合格条件にします。ページごとに例外のクラスを増やす方法と、置き場所を条件にする方法の違いが見える確認です。

ページ全体の変更には、別の判断を残す

ナビゲーションを折りたたむなど、画面全体の空間に合わせる変更なら、メディアクエリーが自然な場合もあります。コンテナークエリーを使う理由は、同じ部品が複数の幅で使われることです。既存の画面幅条件をすべて置き換える必要はありません。

内容が長くてはみ出す問題も、切り替え幅だけでは解決しません。この例では固定の高さを付けず、長い説明を折り返します。Flexboxの最小幅の記事で扱うような内容の最小幅と、今回の切り替え条件は分けて調べます。表示されない文章を増やして箱だけをそろえないでください。

親だけを399px、400pxへ変える

15分程度を目安に、ブラウザーの幅を800px以上に保ち、wideのmax-widthだけを399pxと400pxへ変えます。399pxでは一列、400pxでは二列、narrowはどちらでも一列になるのが解答です。切り替えの原因が画面幅ではないと確かめられます。

その後、画面を320pxへ狭めます。二つとも一列となり、説明の末尾とリンクを読めること、Tabで二つのリンクから先へ進めることを確認します。さらにcontainer-typeを一時的に外して、基本の一列でも情報が残るかを見てから戻します。レスポンシブCSSの無料レッスンで部品を追加するときも、画面の条件と置き場所の条件を別々に記録してください。

TRY A LESSON

記事の内容を、課題で確かめる

レスポンシブCSSの練習 →

CSSの学習内容 →

記事についてのお問い合わせ

記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。

← 記事一覧に戻る