ymdman.com

Media Queryを使わずにレスポンシブな2カラムレイアウトを作る

EVERY LAYOUTという書籍にMedia Queryを使わなくてもレスポンシブな2カラムレイアウトを実現する方法が紹介されてたので忘れないようにメモ。

Media Queryを使ってレスポンシブな2カラムレイアウトを作った場合

モバイルかデスクトップのどちらかをベースにレイアウトを作って、その後にMedia Queryを使ってどちらかのデバイスの値を上書くみたいな作りが一般的。
この方法だと端末ごとに上書きが発生してコードの可読性も悪くなる。

@custom-media --mq-desktop (min-width: 1024px);

.main {
  width: 100%;
}

.aside {
  width: 100%;
}

@media (--mq-desktop) {
  .main {
    width: calc(100% - 300px);
  }

  .aside {
    width: 300px;
  }
}

Media Queryを使わずに2カラムレイアウトを作る

flex-basis、flex-grow、flex-shrinkを組み合わせることでビューポート幅ではなくてコンテンツの利用可能なスペースに応じた折り返しを作れる。

flex-basis

width: 20rem この宣言の場合はどんな状況でも幅は常に20remとなる。
flex-basis: 20rem この場合、20remが 目標の幅 としてブラウザに提示することになる。20remにどれだけ近づけるかはコンテンツの内容によってブラウザが自由に計算してくれる。

flex-grow

flexアイテムの伸長率を整数で指定できる。
flexコンテナの幅からflexアイテムの幅を引いたスペースに対して割り当てられる。

flex-shrink

flexアイテムの縮小率を整数で指定できる。
flexアイテムの幅がflexコンテナの幅よりも大きくなってはみ出した場合のスペースに割り当てられる。

.container {
  display: flex;
  flex-wrap: wrap;
  /* 左右同一の高さにする */
  align-items: flex-start;
  gap: 24px;
}

.main {
  flex-basis: 0;
  flex-grow: 999;
  /* .asideと同じ幅になったら折り返す */
  min-width: 50%;
}

.aside {
  /* 広告が入るサイズで指定してみる */
  flex-basis: 300px;
  flex-grow: 1;
}

  • .mainのflex-growの値を非常に大きく設定して利用可能なスペースを全て占領させる
  • .asideのflex-basisの値は↑のスペースには含まれず、合計から差し引かれるので水平にレイアウトされる
  • 閾値としてmin-widthを使用する。例の場合.mainが50%未満になると強制的に伸長して折り返す
  • .asideにもflex-growが指定してあるので下に折り返した時に伸長する

Codepen