Post on:2020年9月24日
sponsorsr
CSS Flexboxで、Webサイトのヘッダを実装する最近のテクニックを紹介します。
ロゴやナビゲーションの配置、各要素間のスペースの与え方、使用可能なスペースに検索フォームを広げて配置など、Flexboxを効果的に使用した実装方法です。
Building Website Headers with CSS Flexbox
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
私が初めてHTMLとCSSの基礎を学んだとき、Webサイトのヘッダを実装することは非常に難しい作業の1つでした。2014年頃のことで、Flexboxはまだ新しく、floatやclearfixという古いテクニックを使用せざるを得ませんでした。現在では使用するテクニックが全く異なります。Flexboxは広くサポートされており、わたし達に多くの可能性をもたらしてくれます。
CSSの最近のレイアウトテクニックがあるので、ヘッダを実装するのは簡単だと言う人がいるかもしれません。しかし、取り組むべき課題がいくつかあるため、そうではありません。私はそれらを強調したいと思います。
この記事では、CSS Flexboxを使用してWebサイトのヘッダを実装する方法を解説し、その際に必要な知識とテクニックを紹介します。
この記事ではFlexboxに関する基本的な知識があることを前提としています。不安がある方は、Flexboxの基本的な知識を学べる記事をご覧ください。
まずは、Webサイトのヘッダの構造を確認しておきましょう。
ヘッダはユーザーがWebサイトにアクセスした際に最初に目にするものの1つで、通常はロゴまたはWebサイト名とナビゲーションが含まれています。
一般的なヘッダの例
ヘッダの視覚的なデザインに関係なく、重要な要素はロゴとナビゲーションです。
header要素にFlexboxを適用(display: flex;)すると、子アイテムのすべてが同じ行に配置されます。あとは、justify-contentを適用して子アイテム間のスペースを分散させるだけです。
1 2 3 4 | <headerclass="site-header"> <ahref="#"class="brand">Brand</a> <navclass="nav"></nav> </header> |
1 2 3 4 5 | .site-header{ display:flex; justify-content:space-between; align-items:center; } |
これだけなら簡単ですよね?
デザインによってはCSSが複雑になることを覚えておいてください。
上記のヘッダには、ロゴとナビゲーション要素を含むインナーラッパーがありません。これは大きなスクリーンで問題を起こす可能性があります。
大きなスクリーンだと広がりすぎる
上のヘッダはインナーラッパーがないので、幅が広がりすぎていることに注目してください。下のヘッダの方がはるかに良く見えます。
HTMLでインナーラッパーを加えます。
1 2 3 4 5 6 | <headerclass="site-header"> <divclass="wrapper site-header__wrapper"> <ahref="#"class="brand"><imgsrc="logo.svg"alt="brand"/></a> <navclass="nav"></nav> </div> </header> |
インナーラッパーを加えたので、Flexbxoの定義も.site-header__wrapperに移動します。
1 2 3 4 5 | .site-header__wrapper{ display:flex; justify-content:space-between; align-items:center; } |
flex-wrapは防御的なCSSメソッドとして機能します。ヘッダは小さなスクリーンだと横スクロールする可能性があります。
小さなスクリーンだと横スクロールする
flex-wrap: wrap;が定義されていないと横スクロールしてしまいます。必ず含めておきましょう!
CSSの実装は、想定外のコンテンツが使用された場合に対応できるよう、念のために備えておくことが大切です。
参考:よくあるデザインで起こる想定外のコンテンツに備える、CSSの実装方法のまとめ
Flexboxの利点は、ヘッダで複数のデザインのバリエーションを簡単に実装できることです。前述のデザインに基づいて、ボタンの追加、検索フォーム、子アイテムの順番変更など、いくつかのオプションを検討してみました。
Flexboxでこれらを実装する方法を見てましょう。
ヘッダの右端にボタンを追加
ヘッダの右端、ナビゲーションの横にボタンを追加してみます。
これはどのように処理すべきでしょうか?
ナビゲーション内にリンクとして追加しますか? それともナビゲーションから分離させた方がよいでしょうか?
私なら下記のように実装します。
1 2 3 4 5 6 7 | <headerclass="site-header"> <divclass="wrapper site-header__wrapper"> <ahref="#"class="brand"><imgsrc="logo.svg"alt="brand"/></a> <navclass="nav"></nav> <ahref="/track-shipment"class="button">Track</a> </div> </header> |
この場合、justify-content: space-between;ではスペースを空けることができません。その代わりに、ナビゲーションにmargin-left: auto;を使用します。これでナビゲーションとボタンは右に押し出されて配置されます。
margin-left: auto;で右に押し出す
ナビゲーションとTrackボタンを分離して実装した理由は、スマホで表示した際にボタンはそのままで、ナビゲーションをトグルボタンにすることがあるからです。
スマホではナビゲーションはトグルボタンになる
ヘッダに検索フォームを追加
次はさらに、残りの使用可能なスペースに検索フォームを追加してみます。これはFlexboxを使用すると、flexプロパティで簡単に実現できます。
1 2 3 4 5 6 7 8 | <headerclass="site-header"> <divclass="wrapper site-header__wrapper"> <ahref="#"class="brand"><imgsrc="logo.svg"alt="brand"/></a> <divclass="search"></div> <navclass="nav"></nav> <ahref="/track-shipment"class="button">Track</a> </div> </header> |
1 2 3 | .search{ flex:1; } |
これで完了です。
検索フォームは、ロゴとナビゲーションの間の使用可能なスペースを埋めることができます。しかし、これにはいくつかの制限があります。スクリーンサイズが小さい場合を見てましょう。
スクリーンサイズが小さい場合の見え方
検索フォームの入力欄の幅が短じかくなってしまいます。これにはいくつかの解決策があります。
スクリーンサイズが小さい場合の解決方法
私は、2の解決方法の方がナビゲーションがすぐに隠れないので気に入っています。一般的には、レイアウトに影響を与えないのであれば、要素を隠すことは避けたいと思っています。
子アイテムの順番変更
この場合、HTMLのマークアップは同じですが、ヘッダの子アイテムの視覚的な順番が異なります。どうすれば実現できるでしょうか?
順番を変えるには、orderを使えば実現できると思うかもしれませんね。
1 2 3 4 5 6 7 | <headerclass="site-header"> <divclass="wrapper site-header__wrapper"> <ahref="#"class="brand"><imgsrc="logo.svg"alt="brand"/></a> <navclass="nav"></nav> <ahref="/track-shipment"class="button">Track</a> </div> </header> |
1 2 3 4 5 6 7 8 | .site-header{ display:flex; justify-content:space-between; } .nav{ order:-1; } |
順番は変えられましたが、スペースが等しいため、ロゴが中央に表示されません。
順番は変えられたけど、ロゴが中央じゃない
これを解決するには、各子アイテムにflex: 1;を与えることです。利用可能なスペースを均等に分配します。
1 2 3 4 5 | .brand, .nav, .button{ flex:1; } |
各子アイテムのスペースを均等にする
Trackボタンに奇妙なことが起こりました。flex: 1;のせいで大きくなっています。これを修正するには、別の要素で内包するしかありません。
1 2 3 4 5 6 7 8 9 | <headerclass="site-header"> <divclass="wrapper site-header__wrapper"> <ahref="#"class="brand"><imgsrc="logo.svg"alt="brand"/></a> <navclass="nav"></nav> <divclass="button-wrapper"> <ahref="/track-shipment"class="button">Track</a> </div> </div> </header> |
あとは、ロゴとボタンの両方を中央に配置します。
1 2 3 4 5 6 7 8 | .logo{ text-align:center; } /* 名前は気にしないでください。これは説明用です。 */ .button-wrapper{ text-align:end;/* endはLTR言語のrightに相当します。 */ } |
これで下記のように表示されます。
修正を適用
この方法はナビゲーションのアイテムがたくさん追加された場合に失敗する可能性があります。そのため、特定の数を超えないようにする必要があります。ちなみに、アイテムが増えると、下記のようにロゴは中央から外れます。
ナビゲーションのアイテムが増えた場合の表示
上記ではロゴは中央に配置されていません。ということは、そのような予期せぬ問題を避けるために留意する必要があります。
異なるデザインのヘッダを実装する方法を解説したので、次はヘッダを構築する際に役立つ重要なコンセプトを解説します。
私はflex-basis: 100%;を使用するのが好きです。例えば、非表示にできない重要なナビゲーションなど、スマホで全幅を取る必要がある場合に使用します。
非表示にできない重要な要素に使用する
上記のモックアップを見る限りでは、簡単に思うかもしれません。しかし、実際はそうではありません。通常、ヘッダには内側のスペース(パディング)があるかもしれないし、アイテムを強制的に全幅にした場合にはそのパディングを取り除かない限りうまくいきません。しかし、パディングを削除するとデザイン上、他の要素に影響を与えてしまうので現実的ではありません。
これを実現する実装方法は次のとおりです。
1 2 3 4 5 6 7 8 | .nav{ flex:10100%;/* [1] */ order:2;/* [2] */ margin:1rem-1rem-1rem-1rem;/* [3] */ padding:1rem;/* [4] */ display:flex;/* [5] */ justify-content:center;/* [5] */ } |
各CSSがどのような役割を果たしているかビジュアル化しました。
各CSSの役割
ChromeとFirefoxでFlexboxのgapプロパティがサポートされたので、Flexアイテム間のスペースを簡単に与えることができるようになりました。
gapプロパティでスペースを与える
オレンジにハイライトされたスペースを追加するには、flexの親にgap: 1rem;を追加するだけです。gapプロパティをサポートしていないブラウザには、旧来の方法でスペースを与える必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* 旧来の方法 */ .brand{ margin-right:1rem; } .sign-in{ margin-right:1rem; } /* 新しい方法 */ .site-header{ gap:1rem; } |
gapプロパティを使用する場合、フォールバックを行う必要があることに注意してください。
参考:How to detect browser support for Flexbox Gap
最後に私がこの記事を書くに合わせて作成した、Flexboxで実装したヘッダのテンプレートを紹介します。
WebサイトやスマホアプリのFlexboxで実装したヘッダのテンプレートで、新しいプロジェクトにすぐに使用できるようシンプルに実装しました。
下記ページからダウンロードできます。
headers-css.vercel.app
headers-css.vercel.app -GitHub
CSSのデバッグに関する電子書籍を書いていることをお知らせします。
興味がある場合は、debuggingcss.comにアクセスして、本に関する最新情報を購読してください。
コメントや提案があれば、@shadeed9までお願いします。
sponsors