グリッドレイアウト

グリッドレイアウトを極める 17

2022年3月19日

メディアクエリを使用する必要があるのか?

メディアクエリを使用してブレークポイントを追加し、それらを定義するのがこれまでのレスポンシブ対策。しかし、パーセンテージで作業する場合、他のオプションはない。コンテナが広いか狭いかに関係なく、それらは常にコンテナの同じパーセンテージになる。

これらのレイアウト方法に組み込まれている柔軟性を利用することで、メディアクエリを使用せずに、画面スペースに応じて異なるレイアウトの柔軟なコンポーネントを作成できる。たとえば以下のようなレイアウト方法がある。

メディアクエリを使用せずにレスポンシブ
モバイルでは列で表示
メディアクエリを使用せずにレスポンシブ
PCでの表示

スペースが限られている場合は列として表示し、スペースが多い場合は行として表示するメディアオブジェクト。これは、次のように数行のCSSで実現できる。

/* html */
<div class="media">
  <div class="asset"><img src="images/xxx.jpg" alt=""></div>
  <div class="content"></div>
</div>
/* css */
.media {
  display: flex;
  flex-wrap: wrap;
  background: #f7f7f7;
}
.media > * {
  flex: 1 1 250px;
  margin: 10px;
}

ここで使うのが CSS Flexbox。水平または垂直に要素を配置し、柔軟なレイアウトを実現できるCSSのレイアウトモジュールである。.media がflex コンテナ。直下の .asset と .content が flex アイテム。要はスクリーン幅に応じてこのふたつのアイテムがレイアウトを変えるのだ。

使用するフレックスアイテムは250pxだ。2つの250ピクセルアイテム用のスペースがない場合、それらはラップされる。それらは成長する可能性がflex-growあるため(正の値)、折り返されると成長して線を埋める。

ひとつひとつ理解を深めよう。

flex-wrap: wrap;

CSS Flexboxで作成したレイアウトでは、Flexアイテムの横幅の合計がFlexコンテナの幅を超えても横並びのまま連なる。そのため、Flexコンテナに flex-wrap: wrap; を指定して、幅がオーバーした分のFlexアイテムを改行させることができる。

flex: 1 1 250px;

flex: [flex-grow] [flex-shrink] [flex-basis]; という一括指定のプロパティについてここでは、flex: 1 1 250px; と記述した。

flex: 1 1 250px イメージ無しを指定した検証

flex: 1 1 250px 幅250pxのイメージを入れて検証

flex: 1 1 250px 幅100%のイメージを入れて検証

1つ目の値で、flex-grow に1を指定することで、Flexコンテナの横幅に合わせFlexアイテムの幅が均等に伸びるようになる。親要素にアイテムが足りない場合、ここで調整する。

2つ目の値では、flex-shrink に1(初期値)を指定しているので縮む倍率は1倍になる。もし親要素からはみ出る場合はここで調整。

3つ目の値では、flex-basis でFlexアイテムの基準となる幅を250pxに指定している。

因って、イメージの幅は以下のように設定。

img {
  max-width: 100%;
  display: block;
}

flex-basis

flex-basis プロパティは、自動拡大縮小設定を行うための content キーワードまたは <'width'> で幅を指定する。各Flexアイテムの幅を同じにしたい場合は、flex-basisを使用する。

Flexboxとグリッドレイアウト、および複数列のレイアウトは、デフォルトでレスポンシブだ。これらの仕様は、レスポンシブデザインと複数のデバイスのサポートがすでに重要視されていた世界で作成された。これは、多くの常識的な機能が含まれていることを意味する。これにより、多くのことをしなくてもレスポンシブデザインが可能になる。

Using Media Queries For Responsive Design In 2018 より引用

背景イメージを固定してスクロールで文字を表示させるグリッドレイアウトを使ったサンプル

:not() と :empty が実に効率良く働いてくれる。

このサンプルのギミックを実現するには、以下に挙げたプロパティと擬似クラスを用いる。全てのグリッドアイテムには display: flex; を設定して中央配置している。

background-attachment: fixed;

background-attachment: fixed; は CSS のプロパティで、背景はビューポートに対する相対位置で固定される。要素がスクロール機構を持っていたとしても、背景画像は要素とともには動かない。

position: sticky;

position: sticky; は CSS のプロパティで、要素は文書の通常のフローに従って配置され、直近のスクロールする祖先および包含ブロック (直近のブロックレベル祖先、表関連要素を含む) に対して top, right, bottom, left の値に基づいて相対配置される。オフセットは他の要素の配置には影響を与えない。

:not()

:not() は CSS の擬似クラスで、列挙されたセレクターに一致しない要素を表す。例えば…

/* 段落以外の要素を選択 */
:not(p) {
  color: blue;
}

:empty

:empty は CSS の 擬似クラスで、子を持たない要素を表す。子とは要素のノードまたは文字列 (ホワイトスペースを含む) だ。コメント、処理指示、 CSS の content は要素が空であるかどうかの判断には影響しない。例えば…

/* 内容を含まない <div> 要素を選択したい場合 */
div:empty {
  background: lime;
}

以上。