モダンCSSでよく使用されるレイアウトを実装するまとめ

ヘッダ・フッタ・コンテンツ・サイドバー、フルページのレイアウト、最下部のフッタ、中央配置、カードなど、一般的なWebサイトやスマホアプリのUIをモダンCSSで実装する方法を紹介します。

CSSの実装はデバイスベースからコンテンツベースに移行しているのが現状です。これからのプロジェクトに役立つCSSのテクニックを解説します。

モダンCSSでよく使用されるレイアウトを実装するまとめ

Layout patterns

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

モダンCSSで実装するレイアウト

Layout patternsはGoogle DevelopersによるモダンCSSで実装されたレイアウトのパターン集です。カード、ダイナミックなグリッド、フルページのレイアウトなど、一般的なWebサイトやスマホアプリのUIを構築するのに役立ちます。

サイトのキャプチャ

Layout patterns

ここで紹介するレイアウトのほとんどは、CSS GridとFlexboxが使用されています。Webサイトやスマホアプリでよく使用されるUIパターンを実装するのに役立ち、すべてのエバーグリーンブラウザでサポートされています。
※エバーグリーンとは、最新版に自動アップデートされるブラウザのことです。

注意: コンテナクエリを使用した実験的なものも含まれています。現在、安定したブラウザではサポートされていません。

アスペクト比が維持される画像カード

カード内の画像のアスペクト比を維持したまま、カードのサイズを変更できます。

アスペクト比が維持される画像カード

デモページ

aspect-ratioプロパティを使用すると、カードのサイズを変更しても、緑の画像ブロックは16 / 9で定義された16:9のアスペクト比が維持されます。

aspect-ratioを使用せずに16:9のアスペクト比を維持するには、padding-top: 56.25%;のハックで上端と幅の比率を定義する必要がありました。このハックとパーセントを計算する必要をなくすために、このプロパティが存在します。

1 / 1で正方形を作ったり、2 / 1で2対1の比率を作ったり、画像が設定された比率で拡大縮小するために必要なことは何でもできます。

参考:

最大値と最小値を決め、伸縮するカード

カードの幅の最小値・最大値を決め、レスポンシブ対応のサイズを定義します。

最大値と最小値を決め、伸縮するカード

デモページ

width: clamp(<min>, <actual>, <max>);でカードの幅を定義しています。clamp()最小値と最大値、そして実際のサイズを定義するものです。値を使用すると、次のようになります。

幅の最小値は23chで、最大値は46chです。chは文字幅の単位で、要素のフォントサイズ(具体的には0グリフの幅)に基づいています。実際のサイズは50%で、これはこの要素の親の幅の50%を表しています。

clamp()関数が行っているのは、50%の幅が46chより大きくなる(広いビューポートの場合)か、23chより小さくなる(小さいビューポートの場合)まで、この要素が50%の幅を維持させることです。親の伸縮に合わせて、カードの幅がクランプされた最大値まで増加し、クランプされた最小値まで減少します。

また、追加のプロパティ(place-items: center;)で、親の中央に配置されたままになります。これにより、テキストの幅が広すぎたり(46ch以上)、つぶれて狭くなったり(23ch以下)することがないので、より読みやすいレイアウトが可能になります。

clamp()を使用して、レスポンシブなタイポグラフィを実装することもできます。たとえば、font-size: clamp(1.5rem, 20vw, 3rem);と記述すると、フォントサイズは常に1.5rem3remの間に固定され、ビューポートの幅に合わせて20vwの実際の値に基づいて大きくなったり小さくなったりします。

これは、最小と最大の値で読みやすさを確保するための素晴らしいテクニックですが、すべてのモダンブラウザでサポートされているわけではないので、フォールバックを用意してテストすることを忘れないでください。

参考:

コンテナに合わせて最適化されるカード

独立したスタイルロジックを持ち、親のインラインの幅に基づいてスタイルが定義されているカード。
コンテナクエリを使用するには、ChromeCanaryで#enable-container-queriesのフラグをオンにしてください。

コンテナに合わせて最適化されるカード

デモページ

コンテナクエリを使用して、レスポンシブなカードを実装しています。このカードは、幅の狭いサイズでは1カラムになり、幅の広いサイズでは2カラムになります。

コンテナを作成するには、最初にcontainerプロパティを親に設定します。

次に、基本のスタイルを定義します。

親コンテナの幅に応じて、基本スタイルをアップデートします。

コンテナクエリはまったく同じコンポーネントをUIのさまざまな場所に配置した場合、独自のロジックを使用してサイズを変更し、最適に配置させることができます。カードのレイアウトは、グローバルのビューポートだけに頼っていたときよりも、適切にコントロールできます。

参考:

スペースに合わせて伸縮するパンケーキ

スペースに合わせて伸縮し、最小値のサイズで次の行にスナップするレイアウトを作成します。

スペースに合わせて伸縮するパンケーキ

デモページ

マーケティングサイトなどでよく見られるレイアウトで、画像、タイトル、プロダクトの特徴を説明するテキストの3つのアイテムが並んでいるのが一般的です。小さなスクリーンでは積み重なり、大きなスクリーンでは横並びになります。

この実装にメディアクエリは不要です。flexboxを使用するだけで、スクリーンサイズが変更されたときにこれらの要素の配置を調整できます。

flexプロパティはflex: <flex-grow> <flex-shrink> <flex-basis>のショートハンドです。要素を伸縮させてスペースを埋めたい場合は、<flex-grow>の値を1にします。

ボックスを<flex-basis>サイズに合わせて表示し、小さいサイズでは縮小し、さらにスペースを埋めないようにするには、flex: 0 1 <flex-basis>と記述します。150pxにしたい場合は、下記のようにします。

参考:

聖杯レイアウト

聖杯レイアウトとは、ヘッダ、フッタ、2つのサイドバーがメインのコンテンツを挟むクラシックなレイアウトです。

聖杯レイアウト

デモページ

このクラシックな聖杯レイアウトには、ヘッダ、フッタ、左サイドバー、右サイドバー、メインコンテンツがあります。後述する「積み重なるパンケーキ」と少し似ていますが、こちらにはサイドバーがあります。

このグリッド全体を1行のコードで記述するには、grid-templateプロパティを使用します。これにより、行と列の両方を同時に定義することができます。

grid-template: auto 1fr auto / auto 1fr auto;は、スペースで区切られた1つ目と2つ目のリストの間のスラッシュが、行と列の間の区切りです。

「積み重なるパンケーキ」は、ヘッダとフッタが自動的にサイズ調整されていましたが、ここでは子の固有サイズに基づいて左と右のサイドバーが自動的にサイズ調整されます。ただし、今回は垂直(高さ)ではなく、水平(幅)のサイズです。

参考:

ラインナップ

ラインナップは、サイドバーに最小と最大のセーフエリアのサイズが指定され、残りのコンテンツが利用可能なスペースを埋めるレイアウトです。

ラインナップ

デモページ

この実装のポイントは、justify-content: space-between;を使用して、最初と最後の子要素をバウンディングボックスの端に配置し、残りのスペースを要素間に均等に配置することです。これらのカードはdisplay: flex;で配置されており、flex-direction: column;で方向が列に設定されています。

これにより、タイトル、説明文、画像ブロックが親カード内の縦列に配置されます。次に、justify-content: space-between;を適用すると、最初の要素(タイトル)と最後の要素(画像ブロック)がflexコンテナの端に固定され、それらの間にある説明文が各端に等間隔で配置されます。

参考:

積み重なるパンケーキ

一般的にスティッキーフッタと呼ばれるこのレイアウトは、Webサイトやアプリでよく使用されています。

積み重なるパンケーキ

デモページ

前述の「伸縮するパンケーキ」とは異なり、このレイアウトはスクリーンサイズが変更されても子を折り返しません。一般的にスティッキーフッタと呼ばれるこのレイアウトは、Webサイトとアプリの両方で使用され、スマホアプリ(フッタは一般的にツールバー)とWebサイト(特にシングルページアプリ)で使用されています。

コンポーネントにdisplay: grid;を追加すると、1カラムのグリッドが作成されますが、メインエリアの高さはその下にフッタがあるコンテンツと同じになります。
フッターを下部に固定するには、次のように記述します。

このCSSでヘッダとフッタのコンテンツが自動的にその子のサイズを取得するように設定され、残りのスペース(1fr)がメインエリアに適用されます。また、サイズがautoに設定されたカラムは最小サイズを適用されるので、コンテンツのサイズが大きくなると、カラム自体もそれに合わせて大きくなります。

参考:

RAM (Repeat, Auto, Minmax)

自動的に配置されたフレキシブルな子を備えたレスポンシブ対応のレイアウトです。

RAM (Repeat, Auto, Minmax)

デモページ

このレイアウトはここまでのテクニックを組み合わせて、自動的に配置されたフレキシブルな子を持つレスポンシブ対応のレイアウトを作成します。ここで覚えておくべき重要な用語はrepeatauto-(fit|fill)minmax()で、頭文字をとってRAMと呼ばれています。

この3つをまとめて使用すると、次のようになります。

repeat()を使用していますが、明示的な数値の代わりにauto-fitキーワードを使用しています。これにより子要素の自動配置が可能になります。これらの子要素の基本的な最小値は150pxで、最大値は1frです。つまり、小さなスクリーンでは1frの幅いっぱいに表示され、それぞれの幅が150pxになると、同じラインに配置されます。

auto-fitは完全に空のトラックは0に折りたたまれ、いっぱいになったトラックはスペースを占めるように成長します。ただし、これをauto-fillに変更すると、空のトラックは埋められた場合と同じ量のスペースを占めるようになります。

参考:

メディアクエリなしのサイドバー

サイドバーに最小と最大のセーフエリアサイズが与えられ、残りのコンテンツが利用可能なスペースを埋めるレイアウトです。

メディアクエリなしのサイドバー

デモページ

このレイアウトでは、グリッドレイアウトにminmax()関数を利用します。この関数を使用して、サイドバーの最小サイズを100pxに、最大サイズを25%にしています。サイドバーは、その25%100pxより小さくなるまで、常に親の水平方向のスペースの25%を占有します。

grid-template-columnsプロパティにminmax(100px, 25%) 1frという値を定義しています。1カラム目(ここではサイドバー)には100pxminmax25%に設定し、2カラム目(ここではメインセクション)は残りのスペースを1frのトラックとして占有します。

参考:

これからの中央配置

1行のCSSで、子のdivを中央に配置します。

これからの中央配置

デモページ

place-items: center;で、要素を親要素の中央に配置します。

最初にdisplay: grid;を定義してから、place-items: center;を定義します。place-itemsは、align-itemsjustify-itemsの両方を一度に定義するための省略形です。centerとすることで、align-itemsjustify-itemsの両方がcenterに設定されます。

参考:

12spanのグリッド

12分割されたグリッドで、トラック上にエリアを均等に配置できます。

12spanのグリッド

デモページ

もうひとつの定番レイアウトが、12spanのグリッドです。CSSでは、repeat()関数で簡単にグリッドを作成できます。repeat(12, 1fr);を使用すると、グリッドのテンプレートの列に1frずつの12カラムになります。

これで12カラムのグリッドができたので、グリッドに子要素を配置できます。1つの方法として、グリッドラインを使用して配置できます。

たとえば、grid-column: 1 / 13とすれば、最初の行から最後(13番目)の行まで12カラムにまたがります。grid-column: 1 / 5;とすれば、最初の4カラムにまたがります。

もう一つの書き方は、spanキーワードを使用することです。spanは開始点を設定し、その開始点から何列目に渡るかを設定します。grid-column: 1 / span 12;grid-column: 1 / 13;となり、grid-column: 2 / span 6;grid-column: 2 / 8;と同じになります。

sponsors

top of page

©2021 coliss