これぞプロの実装テクニック!フロントエンドのデベロッパーはCSSで実装する時に何を考えるか
Post on:2020年12月8日
ページのレイアウトやUIコンポーネントを実装する時に、フロントエンドのデベロッパーはいろいろなことを考えます。スクリーンのサイズが小さい時はどうなるのか、デザインでは中央配置に見えるけど実装はどうすべきか、要素が少ない場合や多い場合があるのか、max-やmin-を定義した方がよいのか、、、
フロントエンドのデベロッパーはCSSでレイアウトを実装する時に何を考えるか、その思考プロセスを言語化した解説記事を紹介します。
下記は、頭の中のメガネで見える実装のイメージです。

Thinking Like a Front-end Developer
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
先日、TwitterでCSSのどんな話題に興味がありますか?と尋ねました。その中で目を引いた提案の1つは、CSSでレイアウトを実装する時に何を考えるかについてです。実装する前にどのような可能性を考慮し、それを実現するためにどのようなことをするかなどです。
この記事では、CSSでのレイアウトについて考えるためのアプローチとそれらの作業手順について解説します。
それでは、さっそく始めましょう!
デザインのディテールは脇に置いておく
私が普段から実践していることは、まずデザインのディテールは脇に置いておくことです。つまり、レイアウトの主要な部分にスポットを当てて、そこから考え始めます。ディテールが重要であることは知っていますが、これは一時的なものであるため、最初はハイレベルなディテールに集中します。
下記のUIを例に解説します。

一般的なWebページのUI
このデザインには、下記があります。
- ヘッダ・ナビゲーション
- ヒーローセクション
- How it worksのセクション
ハイレベルを考えるよりも、ディテールを先に考え始めたくなるかもしれません。視覚化するように頼まれた場合、フロントエンドのデベロッパーはレイアウトのハイレベルなアイテムのみを表示できるメガネをかける必要があると想像します。

レイアウトのハイレベルなアイテムのみを表示できるメガネで見た場合
このメガネをかけると、UIで重要なハイレベルのコンポーネントしか見えなくなります。これは各コンポーネントごとに少しずつ考えるのではなく、コンポーネントをどのようにレイアウトするかを考えるのに役立ちます。
その思考の過程を見てましょう。
- Full-width header: ヘッダがビューポートの全幅を占めているように見え、コンテンツはラッパー内に制約されていない。
- ヒーローセクションのコンテンツは水平方向の中央に配置されており、max-widthを定義する必要がある(テキストは2行)。
- どのように機能するか: 4カラムのレイアウトにし、セクション全体はラッパーで内包する。
これをコードで作業したいときは、簡単なプロトタイプを作成して、進捗状況を素早く確認できます。
1 2 3 4 5 6 7 8 9 10 11 |
<header></header> <section class="hero"> <!-- コンテンツを制約するdiv --> <div class="hero__content"></div> </section> <div class="wrapper"> <!-- 4カラムのレイアウト --> <section class="grid-4"></section> </div> |
4カラムのセクションがあるので、CSS Gridで実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
.wrapper { margin-left: auto; margin-right: auto; padding-left: 1rem; padding-right: 1rem; max-width: 1140px; } .hero__content { max-width: 700px; margin-left: auto; margin-right: auto; } .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); } |
これはメガネをかけた状態でのハイレベルな思考です。レスポンシブについてはまだ考えていません。一部のコンポーネントのディテールについて疑問点がありましたが、この時点ではまだ掘り下げません。ディテールは記事の次のセクションで解説します。
これで今、あなたはアイデアを得たので、私はあなたがより良くすることができるように、他のハイレベルな思考の例も解説します。
配下ページのレイアウトを実装する時に考えること
配下ページとして、記事ページのレイアウトを見てましょう。
記事ページには、以下のUIが含まれています。
- ヘッダ
- ページヘッダ
- 記事のサムネイル画像
- 記事のコンテンツ
- サイドバー

記事ページのUI
デザインがどのように見えるのかが分かったので、今度はメガネをかけてディテールだけを見てみます。

レイアウトのハイレベルなアイテムのみを表示できるメガネで見た場合
メガネをかけると、以下のハイレベルなコンポーネントがあることが分かります。
- ヘッダは全幅を占めている。
- ページヘッダには記事のタイトルと説明文が含まれ、そのコンテンツは左揃え、max-widthも必要。
- メインとサイドバー要素を含む2カラムのレイアウト。
- 記事の内部コンテンツは水平方向の中央に配置され、max-widthが必要。
ページヘッダ

ページヘッダ -記事ページのUI
このレイアウトの実装にはメソッドは必要ありません。シンプルにmax-widthで十分です。ビューポートが小さい場合に端がくっつかないように、両端にpaddingを定義しておきます。
1 2 3 4 |
.page-header { max-width: 50rem; padding: 2rem 1rem; } |
メインとサイドバー

メインとサイドバー -記事ページのUI
メイン要素はビューポートの全幅からサイドバーの幅を引いたものです。通常、サイドバーの幅は固定されていると予想されます。この実装には、CSS Gridが最適です。
1 2 3 4 5 6 7 8 |
.page-wrapper { display: grid; grid-template-columns: 1fr; } @media (min-width: 800px) { grid-template-columns: 1fr 250px; } |
記事の内部コンテンツは、ラッパー内に制限する必要があります。
1 2 3 4 5 6 7 |
.inner-content { max-width: 50rem; margin-left: auto; margin-right: auto; padding-left: 1rem; padding-right: 1rem; } |
これでレイアウトを構築する上で必要のあるハイレベルの判断が分かったと思います。次は、デザインの各セクションの扱いについて解説します。
ディテールを掘り下げる、どのように機能するか
上記で後述するとした通り、ディテールを掘り下げ、どのように機能するかについて解説します。

一般的なWebページのUI
カラム
- Stepの数が少なくなったり多くなったりする場合があるか? 数が変化する場合はどのように処理すればよいか?
- カード内のテキストが長い場合は、高さを同じにする必要があるか?
見出し
- 各セクションの見出しの文字数は?文字数が多い場合は横長か複数行か?
レスポンシブ
- セクションの子要素を積み重ねにするタイミングは?そのためのトリガーは?
このセクションで考えられるシナリオをいくつか下記に示します。
あなたはどう考えますか? フロントエンドデベロッパーであれば、さまざまな問題を想定することが求められます。問題を想定せずにUIを実装するだけではダメです。

このセクションで考えられるシナリオ
この記事では思考プロセスにフォーカスしているため、実装方法を解説しませんが、少しだけクールなものをお見せしたいと思います。
上記のモックアップの1番目と3番目のバリエーションでは、ステップ数が3と2になっています。これを処理するためにCSSを動的にすることはできるでしょうか?
つまり、2つしかないアイテムを拡張するということです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<div class="wrapper"> <section class="steps"> <div> <h2>How it works</h2> <p>Easy and simple steps</p> </div> <div class="layout"> <div class="layout__item"> <div class="card"></div> </div> <div class="layout__item"> <div class="card"></div> </div> <div class="layout__item"> <div class="card"></div> </div> </div> </section> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
.steps { display: grid; grid-template-columns: 1fr; grid-gap: 1rem; } @media (min-width: 700px) { .steps { grid-template-columns: 250px 1fr; } } .layout { display: grid; grid-template-columns: 1fr; grid-gap: 1rem; } @media (min-width: 200px) { .layout { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } } |
先日の記事で解説した、minmax()関数とauto-fitを使用すると簡単に実装できます。カードの枚数が増減する場合に役立ちます。
参考: しっかり理解しておくと便利なCSSのテクニック、minmax()関数の使い方

minmax()関数とauto-fitを使用すると簡単に実装できる
ヒーローセクションを実装する時に考えること
セクションやコンポーネントを新しく実装するときに最初にすることは、たくさんの質問をすることです。ヒーローセクションを例に、私が考えることを解説します。

ヒーローセクションのUI
画像について
- 画像はどのように表現する必要があるか? 日または時間によって変わるのか? もしくはCMSからの更新が必要なのか?
- 画像の実装は<img>を使用するべきか、もしくはCSSの背景として?
- 画像の想定されるアスペクト比は?
- ビューポートサイズに応じて複数の画像サイズを使用する必要があるか?
- 画像が動画になる可能性はあるか?(私は実際にクライアントから、画像の実装を終えた後に動画が必要だと言われたことがあります)
ヒーローの高さ
- 最小の高さはどれくらいか?
コンテンツの長さ
- タイトルと説明文に最大の長さを設定する必要があるか? 必要な場合、デザインが扱うことが期待される最小値と最大値は?
要素間のスペース
- 垂直方向のスペースをどう扱うか?
コンテンツの中央揃え
- コンテンツを水平と垂直方向の中央に配置するにはどうすればよいか? 幅しかわからず、高さは不明。
コンテンツの制約
- より読みやすくするためには、コンテンツを制約したほうがよい。理想的な幅はいくつ?
レスポンシブデザイン
- ビューポートの幅に基づいてフォントサイズを変更する必要があるか? ある場合、pxベースの単位?ビューポート単位?clamp()関数?
これらの質問は取り組んでいるプロジェクトの性質に応じて、答えが見つかるはずです。ヒーローコンポーネントをどのように構築する必要があるのかを判断するのに役立ちます。時には、それぞれの質問に対する答えを得るのが難しいことがあるかもしれませんが、質問が多ければ多いほど、バグのない良い結果が得られる可能性が高くなります。
このコンポーネントの子要素間のスペースに取り組んでみます。
私はflow-spaceユーティリティを使用するのを好みます。Piccalilのブログで知りました。目的は、兄弟要素間のスペースを確保することです。

子要素間のスペースを実装
HTMLとCSSは下記のようになります。
1 2 3 4 5 6 7 8 |
<section class="hero"> <!-- A div to constraint the content --> <div class="hero__content flow"> <h2>Food is amazing</h2> <p>Learn how to cook amazing meals with easy and simple to follow steps</p> <a href="/learn">Learn now</a> </div> </section> |
1 2 3 |
.flow > * + * { margin-top: var(--flow-space, 1em); } |
終わりに
コンポーネントを実装するプロセスは、コンポーネントをデザインと完全に一致させるだけでなく、仕様や機能について質問して考える必要があります。この記事から、あなたが1つでも多くのことが得られればと願っています。
リソース
- A Deep Dive Into CSS Grid minmax()
- The Just in Case Mindset in CSS
- The Process of Implementing A UI Design From Scratch
- Spacing in CSS
- Min and Max Width/Height in CSS
- Centering in CSS
CSSのデバッグに関する電子書籍を書いていることをお知らせします。

興味がある場合は、debuggingcss.comにアクセスして、本に関する最新情報を購読してください。
コメントや提案があれば、@shadeed9までお願いします。
sponsors