2019.07.21

CSSコーディングレシピ集(レイアウト編)


この記事では、CSS を学び始めの方を対象に、よくあるレイアウトのコーディング方法を紹介します。

CSS の基本的な文法や Flexbox などの書き方そのものについては、この記事では扱いません。あくまでそれらの基礎を組み合わせた、コーディングパターンについて書いていきます。レイアウトの基礎については、記事の最後にいくつか載せたリンクを参考になると思います。

以下のシリーズ記事のレイアウト編です。

中央寄せ

まずは中央寄せのテクニックです。CSSを学び始めた方は誰しも挑戦しますよね。

左右中央寄せ

左右の中央寄せは、基本的に2パターンです。

中央寄せにしたい要素の display プロパティが、

  • block の場合 → その要素の左右のマージンに auto
  • inline または inline-block の場合 → 親要素に text-align: center

と記述します。以下の CodePen で確認しましょう。

See the Pen 左右中央寄せ by Masahiro Harada (@MasahiroHarada) on CodePen.

ブロック要素

ブロック要素を左右に中央寄せしたい場合は、その要素の左右の marginauto を指定します。このように指定した場合、自動的に左右に同じだけの余白が取られるので、結果として中央に配置されます。

ちなみに、上下のマージンに auto を指定しても、上下中央寄せにはなりません。左右に加えて上下にも中央寄せしたい場合は、次で紹介する方法を採りましょう。

インライン要素

インライン要素(または inline-block)を中央寄せにするためには、その要素を囲う親要素に text-align: center を指定します。

インライン要素の左右マージンに auto を指定しても中央寄せにはなりません。これは、マージンの auto は「占有可能な」領域に対して計算されるからです。

ブロック要素の場合は、幅が固定されていても(親要素の)横いっぱいが占有可能とみなされます。一方インライン要素の場合は、自身のコンテンツ幅のみが占有可能とされるので、そもそも auto で計算できる余白がありません。

上下左右中央寄せ(絶対位置)

上下の中央寄せは、初学者にとってチャレンジングなレイアウトの典型ではないでしょうか。

ここでは2パターンのやり方を紹介します。絶対位置を用いた手法と、Flexbox を用いた手法です。まず以下の CodePen が絶対位置を使ったテクニック例です。

See the Pen 中央寄せ by Masahiro Harada (@MasahiroHarada) on CodePen.

中央寄せする基準となる親要素に position: relative を指定したうえで、中央寄せしたい要素を position: absolute を指定します。

ここからがテクニックですが、まず topleft50% を指定します。これにより、親要素のちょうど真ん中(対角線の交点)の地点に、子要素が配置されます。

ただし、この時点ではまだ上下左右に中央寄せはされていません。親要素の中央点と、子要素の左上の角が重なっている状態です(試しに上の CodePen で transform の指定を取り除いてみてください)。

ここで transform を使い、X軸に-50%(つまり左に子要素の幅の半分)移動させ、さらにY軸に-50%(つまり上に子要素の高さの半分)移動させることで、綺麗に中央に配置されます。

絶対位置は状況によらず使えることが多いので、この手法もイディオムとして覚えてしまうと便利です。

上下左右中央寄せ(Flexbox)

2つめの上下左右中央寄せの手法は、Flexbox を使ったテクニックです。

See the Pen 中央寄せ(Flexbox) by Masahiro Harada (@MasahiroHarada) on CodePen.

テクニックというか、Flexbox の基本的な記述方法に従うだけですね。align-itemsjustify-betweencenter を指定します。

上下の中央寄せについては、他にも display: table を用いた手法など色々あるようですが、個人的には上で紹介した2パターンだけで十分だと思います。

(私は table はレイアウトが独特で手に負えなくなるリスクがあるので、明らかに見た目がテーブルである場合にしか用いません。)

1カラムレイアウト

典型的な1カラムレイアウトです。冒頭で紹介した左右のマージンに auto を指定して中央寄せする手法を応用して実現します。

CodePen の CSS(または HTML)タブを閉じて Result を広げてみてください。Main 領域は一定の横幅(ここでは600px)以上には広がらないはずです。簡単ではありますがレスポンシブデザインを意識しています。

See the Pen レイアウト(1カラム) by Masahiro Harada (@MasahiroHarada) on CodePen.

ポイントは以下の3つの指定です。

.main {
  /* 中略 */
  margin: 0 auto;
  max-width: 600px;
  width: 100%;
}

横幅が 100% なので、基本的には横いっぱいの領域を占めます。ただし、最大でも 600px までしか広がりません。そして、左右のマージンを auto にすることで、親要素の横幅が 600px 以上ある場合でも、中央寄せで綺麗に見せることができます。

実装方法は他にもあるかもしれませんが、見え方に関しては、多くの1カラムサイトは上記のようになっているはずです。

Flexbox レイアウト

Flexbox を利用したレイアウトパターンです。

2カラム

コンテンツが左右の2カラムで構成されるレイアウトです。

左(Main)にメインコンテンツ、右(Aside)に付加的なコンテンツが配置されるイメージで作ってみました。

See the Pen レイアウト(2カラム) by Masahiro Harada (@MasahiroHarada) on CodePen.

左右のコンテンツを囲う .wrapper は1カラムレイアウトと同じ手法で最大幅と左右中央寄せを実現していますが、さらに Flexbox にもなっています。

右は固定の幅(160px)を持たせています。左は flex: 1 1 auto を指定しているので、親要素の幅から右コンテンツの幅を引いた余りの幅を占めます。つまり可変幅ということです。

2カラム(レスポンシブ)

次は、上記のレイアウトをよりレスポンシブにしたバージョンです。

CodePen の CSS(または HTML)タブを開閉して Result を広げてたり縮めたりしてみてください。

See the Pen レイアウト(2カラムレスポンシブ) by Masahiro Harada (@MasahiroHarada) on CodePen.

基本は上と同じですが、メディアクエリを用いて、画面幅が 600px 以下のとき、.wrapper の Flexbox 指定を解除し、さらに Aside 部分の横幅を100%に変更(つまり固定幅から可変幅に変更)しています。

これにより、一定の幅までは2カラムで、小さい画面幅では1カラムで縦に重なる、レスポンシブなレイアウトが実現できます。

スティッキーフッター

Flexbox を用いた、スティッキー(固定)フッターです。

メインのコンテンツが少ない、つまりメインコンテンツ領域が短い場合でも、フッターを浮かせず、画面下に固定するテクニックです。Flexbox を使えば簡単に実装できます。

See the Pen レイアウト(スティッキーフッター) by Masahiro Harada (@MasahiroHarada) on CodePen.

縦方向(flex-direction: column)の Flexbox を使います。

全体の領域(CodePen の例では .wrapper)が少なくとも 100vh であると定義したうえで、縦方向の Flexbox で Header / Main / Footer を並べます。

さらに Main に flex: 1 1 auto を指定することで、Main は、中身が少ない場合でも、100vh から Header と Footer の高さを引いた分の高さを占めることになります。

CSS Grid レイアウト

CSS Grid でも、レイアウトを表現することが可能です。

2カラム(レスポンシブ)

管理画面などで使えそうな2カラムレスポンシブレイアウトを、CSS Grid で実装します。

  • 一定幅(600px)より大きい画面幅では、Header の下が2カラムで、左を Sidebar が占め、右に Main と Footer が並ぶ
  • 一定幅より小さい画面幅では、Header / Main / Sidebar / Footer の順番で縦に配置

See the Pen Gridレイアウト by Masahiro Harada (@MasahiroHarada) on CodePen.

一見複雑なレイアウトですが、CSS Grid を用いると意外と簡単に記述できてしまいます。

一定幅(600px)より大きい画面幅では、2列 × 3行のグリッドを定義し…

  • Header は1列めから最後までを占める。
    行については省略しているので、1行と解釈される。
  • Sidebar は2行めから最後までを占める。
    列については省略しているので、1列と解釈される。
  • Main と Footer に関しては記述を省略しているので、明示的に指定のある Header と Sidebar を配置した結果余った行列に、自動的に配置される。

という具合です。

一定幅より小さい画面幅では単純に 1列 × 4行のグリッドに各要素を配置しています。行を定義する grid-template-rows4rem 1fr auto 4rem と指定している点がポイントでしょうか。1fr が余った領域を占めるのに対し、auto は内容の持つ高さに留まります。

CSS Grid は、基本的な仕様は Flexbox よりも単純明快だと感じます。行と列を定義して、子要素がそれぞれ何行めと何列めに配置されるかを指定すればOK、ということですから。

注意点として、IE11には、記述を省略した場合の自動配置機能は無いそうです。CSS Grid の IE 対応については、本記事末尾にも掲載したこちらの記事に詳しく書かれています。

タイルレイアウト

次は CSS Grid で実装する、実用的なタイルレイアウトです。
(見た目は某ファッションECサイトから拝借しました。実装は独自のものです。)

ちなみに、ここではレスポンシブ対応までは施していません。

See the Pen Gridレイアウト 2 by Masahiro Harada (@MasahiroHarada) on CodePen.

HTML / CSS は長いですが、レイアウトを表現する CSS Grid の記述は .card-list のみに書かれています。

.card-list {
  display: grid;
  /* 4列のグリッド */
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, auto);
  grid-column-gap: 1rem;
  grid-row-gap: 2.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.card-list.top-3 {
  /* 1〜3位までは、3列のグリッド */
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
  margin-bottom: 2.5rem;
}

行と列、そして行間および列間の余白(gap)を定義するだけで、あとは子要素を並べていけば、折り返しも含めて自動的に行×列に合わせて配置されていきます。


以上、よくあるレイアウトのコーディング方法をいくつか紹介しました。

【参考リンク】レイアウトの基本手法

float

Flexbox

CSS Grid