この記事では、書籍「HTML5/CSS3 モダンコーディング」(吉田真麻 著、翔泳社)に基づいて、スタンダードレイアウトのヘッダー実装を行ってみる。
書籍の内容に基づき、少しオリジナル要素を加えながら実装した過程を公開しているが、用語やコードの詳細な説明についてはこの書籍自体を参照してほしい。私は、プログラミングスクール「ウェブカツ」で学習した内容の復習として、この本を読んでみたのだが、曖昧に理解していた事柄を非常に明快な理屈でもって説明してくれる優れた本だ。既にHTML・CSSの基本的な用語のイメージを持っている人なら、この本を読むことで、理解が一段と深まるだろう。
>> 前の記事:No.01 | スタンダードレイアウト:ベースを実装する
デザインからヘッダーの要素とサイズを確認
前の記事「ベースを実装する」でもそうだったが、構成要素の確認とそれらのサイズ(幅、高さ、余白)を把握することから始めるのが定石なのかもしれない。
スタンダードレイアウトのサンプルページのヘッダーは次のようなデザインだ。
ヘッダーを構成する要素は大きく分けると次の2つ。
- サイトのロゴ
- グローバルナビゲーション
これらの高さ方向の寸法は次の通り。
例えば、実際の業務でデザインデータを渡されたとする。どの様な形式のデータでデザインを受け取るのかは、その時々で異なってくるだろう。とは言え、形式が異なっても、デザインの各要素の幅、高さ、余白などの寸法を知ることはそれほど難しくないと思う。
それよりも、デザインを実現するために、余白を padding で指定するのか、それとも margin で指定するのかで悩みそうだ。サイズはデザインから一意的に定まるが、余白の取り方はやり方が幾通りもあるので、どこから攻めるのがいいかは、実装の経験を積まないと身に付かないように思える。
上で示したサンプルサイトのヘッダーに関しては、 書籍「HTML5/CSS3 モダンコーディング」 の中では、header 要素に padding を指定して余白を取ることから始めている。まずは外側に位置する余白から外堀を埋めるように padding を使用してコーディングしていくのが定石なのだろうか。margin は margin 同士の相殺という初心者も殺してしまいそうなやっかいな性質があるため、padding を優先して使用する方が良いのかもしれない。
一番外側の.header要素にスタイルを指定
.header の padding を指定
上が28px、下が10pxになるように padding を指定する。
/* -------------------------------
* header
* ------------------------------- */
.header {
width: 100%;
padding: 28px 0 10px;
height: calc(28px + 56px + 15px + 30px + 10px); /* 仮の高さ */
}
前の記事「ベースを実装する」で 指定した、確認用の高さ指定は削除し、ここで改めて仮の高さ指定を行なってみた。高さ height の指定にはCSSの calc 関数を使用している。最終的にはヘッダーの高さは、中身のコンテンツの高さが決まれば自ずと決まるものだが、今はまだ中身の要素がないためこの様にした。
これでブラウザをリロードし、開発者ツールで<header>要素を選択して padding を確認。これで良さそうだ。
.header の装飾
<header>要素のサイズに関する指定は終わったが、その他、 書籍「HTML5/CSS3 モダンコーディング」 では、<header>要素に背景画像と影を与えている。
全く同じデザインにするのはつまらないので、少しカスタマイズしてみようと思う。その場合、上記 padding の指定を自分のデザインに合わせて修正する必要があるだろう。
背景画像を作ってみる
書籍 「HTML5/CSS3 モダンコーディング」 のヘッダーでは、背景画像としてストライプ模様を表示している。
書籍の公式サイトからサンプルファイルをダウンロードして、背景画像の元である bg-header.gif ファイルを確認すると、面白いことに、この画像は横1px、縦72pxで構成されている。
拡大してみると、次のように3pxの白と1pxの灰色が交互に縦に並んだ画像になっている。
この画像をヘッダーの横幅いっぱいまで繰り返し敷き詰めることで、ストライプ模様を実現している。これなら画像のファイルサイズが小さくなるし、ブラウザの画面の横幅が変更されてもストライプ模様が途切れることはない。なるほど、よくできてるな。
そこで少しだけオリジナリティを加えるため、次のような画像(横1px、縦72px)を作ってみた。作成にはWindowsのペイントを使用した。
これを<header>要素のbackgroundプロパティに指定し、横方向に繰り返し敷き詰めてみる。
/* -------------------------------
* header
* ------------------------------- */
.header {
width: 100%;
padding: 28px 0 10px;
background: url('../images/my-bg-header.png') repeat-x;
height: calc(28px + 56px + 15px + 30px + 10px); /* 仮の高さ */
}
これでブラウザをリロードしてみると
おおっ、上手く行った。カスタマイズしながら読み進めると理解が深まる。
ヘッダーの下部に影を付ける
後は、box-shadowプロパティを使用して、ヘッダー下部に影を付けてみる。
/* -------------------------------
* header
* ------------------------------- */
.header {
width: 100%;
padding: 28px 0 10px;
background: url('../my-images/my-bg-header.png') repeat-x;
box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.5); /* <-- 追加 */
height: calc(28px + 56px + 15px + 30px + 10px); /* 仮の高さ */
}
ブラウザをリロード。
影を書籍のサンプルコードより大きめにしてみた。ヘッダーが浮き上がって見えるようになった。
.header要素の内側の子要素
ヘッダーの内側には、「サイトロゴ」と「グローバルナビゲーション」を配置する。まずは「サイトロゴ」を配置してみよう。
サイトロゴ
サイトのロゴをこちらのサイトで作成してみた。無料で作れるのがありがたい。
index.html の.header要素内にロゴを表示するための要素を記述する。ウェブカツでもそうだったが、ロゴは<h1>要素としてマークアップすることが多いらしい。
また書籍 「HTML5/CSS3 モダンコーディング」 によると、画像を使用したロゴの表示方法としては次の2通りがあるらしい。
- ロゴの画像を img 要素で表示して、img 要素の alt 属性にロゴが表す情報(テキスト)を書く。
- ロゴが表す情報(テキスト)はページに表示させない形で記述し、ロゴの画像は背景画像として表示させる。
この様にすることで、検索エンジンのクローラーが<h1>要素でマークアップしてあるロゴの情報を読み取れるようにしてあげることができる。SEO対策として非常に重要なことを説明していると思う。
ロゴの画像を img 要素で表示する方法
サイトロゴを img 要素で表示してみる。 ちなみに今回の作成したロゴ画像は 340px × 70px だったので、以下の様になった。.header クラスの padding なども自作画像に合わせて少し変更した。
index.html
<!-- ヘッダー -->
<header class="header">
<h1 class="site-logo">
<a href="#">
<img src="my-images/site-logo.png" alt="CONTINUE" width="340px" height="70px">
</a>
</h1>
</header>
style.css
/* -------------------------------
* header
* ------------------------------- */
.header {
width: 100%;
padding: 10px 0 10px;
background: url('../my-images/my-bg-header.png') repeat-x;
box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.5);
height: calc(10px + 70px + 15px + 30px + 10px); /* 仮の高さ */
}
.site-logo {
text-align: center;
}
上記コードを実装した結果、ブラウザをリロードすると画面の表示は次のようになった。
ロゴの画像を背景画像として表示する方法
書籍ではこちらの方法で実装していた。
<!-- ヘッダー -->
<header class="header">
<h1 class="site-logo">
<a href="#">CONTINUE</a>
</h1>
</header>
今回の作成したロゴ画像は 340px × 70px だったので、style.css は以下の様になった。.header クラスの padding なども自作画像に合わせて少し変更した。
/* -------------------------------
* header
* ------------------------------- */
.header {
width: 100%;
padding: 10px 0 10px;
background: url('../my-images/my-bg-header.png') repeat-x;
box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.5);
height: calc(10px + 70px + 15px + 30px + 10px); /* 仮の高さ */
}
.site-logo {
width: 340px;
height: 70px;
margin: 0 auto;
background: url('../my-images/site-logo.png') no-repeat;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
}
.site-logo a {
display: block;
width: 100%;
height: 100%;
}
サイト名を表すテキスト「CONTINUE」を隠すために、overflow, text-indent, white-space プロパティによる特殊なテクニックを使用している。 書籍 「HTML5/CSS3 モダンコーディング」 の中で分かりやすく説明されているので、そちら (p.36) を参照してほしい。
上記コードを実装した結果、ブラウザをリロードすると画面の表示は次のようになった。 img 要素を使用する方法と結果は同じだった。
ところで、このテクニックは少し特殊な気もしたので、実際に使用しているサイトがあるのかどうかを調べてみたら、有名どころでは「yahoo」で使用されていることが確認できた。yahoo の場合は、さらに font-size: 0; も指定しているようだ。
グローバルナビゲーション
次は、グローバルナビゲーションを実装してみる。グローバルナビゲーションは<nav>要素と<ul>要素で実装できる。これはお決まりのパターンと考えてもいいと思う。
グローバルナビゲーションのHTML
index.html
<!-- ヘッダー -->
<header class="header">
<h1 class="site-logo">
<a href="#">CONTINUE</a>
</h1>
<nav class="nav">
<ul>
<li class="nav-item active"><a href="#">HOME</a></li>
<li class="nav-item"><a href="#">プログラミング入門</a></li>
<li class="nav-item"><a href="#">学習記録</a></li>
<li class="nav-item"><a href="#">サイトマップ</a></li>
<li class="nav-item"><a href="#">お問合せ</a></li>
</ul>
</nav>
</header>
ブラウザをリロードすると次のように表示された。
ロゴとグローバルナビゲーションの間のマージンを指定
スタイルを指定する前に、ヘッダーの寸法を再度確認しておく。自作のロゴ画像に合わせて以下の図も修正してある。
この図で実装が残っている寸法は、サイトロゴとグローバルナビゲーションの間の15pxと、グローバルナビゲーションの高さ30pxだ。
サイトロゴとグローバルナビゲーションの間の15pxは、margin を指定して確保するのが簡単そうだ。問題はサイトロゴに margin-bottom を指定するのか、それともグローバルナビゲーションに margin-top を指定するべきなのか。どちらでもいいのだろうが、この様な場合は常にどちらか一方を指定するという決まり事を決めて実装した方がいいかもしれない。
今回は、書籍にならって、グローバルナビゲーションに margin-top を指定することにする。
style.css
.nav {
margin-top: 15px;
}
また、グローバルナビゲーションの高さ30pxの指定も悩ましい。グローバルナビゲーションはその子要素として、<ul>要素や<li>要素、<a>要素を持つことになるわけだが、この30pxという値の指定は、親子関係の一番外側に位置する<nav>要素に指定するべきなのか、それとも一番内側に位置する<a>要素に指定するべきなのか?
つまり次の2通りの決め方があると思う。
- <nav>要素に「 height: 30px; 」を指定し、内側の要素には「 height: 100%; 」を指定する。
- 親要素に height を指定しない場合は、その子要素の高さで決まる性質を利用して、<a>要素に「 height: 30px; 」を指定する。
書籍 「HTML5/CSS3 モダンコーディング」 の中では、後者の方法を採用している。前者の方法だと全ての子要素に「 height: 100%; 」を指定する必要があるかもしれない。そう考えると後者の方が簡潔になりそうだ。
各項目を横並びにする
ナビゲーションの項目(<li>要素)を横並びにする方法には、floatを利用する方法、flexboxを利用する方法が考えられるが、今回のナビゲーションの横並びに関して、書籍の中ではこのいずれの方法も使わずに、<li>要素に「display: inline-block;」を指定することで横並びを実現している。
style.css
.nav .nav-item {
display: inline-block;
}
各項目を中央に寄せる
<nav>要素、あるいはその子要素である<ul>要素に「text-align: center;」を指定することで中央寄せにできる。<nav>要素に指定した場合は、その子要素の<ul>要素にも指定が継承されるらしい。
style.css
.nav {
margin-top: 15px;
text-align: center;
}
.nav .nav-item {
display: inline-block;
}
各項目の見た目を整える
あとはナビゲーションの各項目<li>要素、あるいはその子要素<a>にスタイルを適用して見た目を調整する。以下の様なスタイルを指定してみた。
style.css
.nav {
margin-top: 15px;
text-align: center;
}
.nav .nav-item {
display: inline-block;
margin: 0 10px;
}
.nav .nav-item a {
display: inline-block;
width: 160px;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #e0e0e0;
border: 2px solid #000;
border-radius: 8px;
box-shadow: 8px 8px 5px 0 rgba(0, 0, 0, 0.7);
color: #333;
font-size: 1.3rem;
letter-spacing: 1px;
}
ブラウザをリロードすると次のような表示になった。
ホバー時の動きをつける
最後に、現在のページに対応する項目(activeクラスが付いている)と、マウスをホバーされた項目を装飾する。
activeクラスが付いた項目は、色を青みがかった色にしてみる。ホバーされた項目も同じ色にする。
.nav .nav-item.active a,
.nav .nav-item a:hover {
background-color: #86dae6;
}
また、ホバー時の色は、0.5秒掛けて変化させることにする。
.nav .nav-item a {
display: inline-block;
width: 160px;
height: 40px;
line-height: 40px;
text-align: center;
background: #e0e0e0;
border: 2px solid #000;
border-radius: 8px;
box-shadow: 8px 8px 5px 0 rgba(0, 0, 0, 0.7);
color: #333;
font-size: 1.3rem;
letter-spacing: 1px;
transition: 0.5s; /* 追加 */
}
ブラウザの表示を確認すると以下の様になった。
ヘッダーのコード完成
これでヘッダーのコーディングが完了した。
index.html
<!-- ヘッダー -->
<header class="header">
<h1 class="site-logo">
<a href="#">CONTINUE</a>
</h1>
<nav class="nav">
<ul>
<li class="nav-item active"><a href="#">HOME</a></li>
<li class="nav-item"><a href="#">プログラミング入門</a></li>
<li class="nav-item"><a href="#">学習記録</a></li>
<li class="nav-item"><a href="#">サイトマップ</a></li>
<li class="nav-item"><a href="#">お問合せ</a></li>
</ul>
</nav>
</header>
style.css
/* -------------------------------
* header
* ------------------------------- */
.header {
width: 100%;
padding: 10px 0 20px;
background: url('../my-images/my-bg-header.png') repeat-x;
box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.5);
}
.site-logo {
width: 340px;
height: 70px;
margin: 0 auto;
background: url('../my-images/site-logo.png') no-repeat;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
}
.site-logo a {
display: block;
width: 100%;
height: 100%;
}
.nav {
margin-top: 15px;
text-align: center;
}
.nav .nav-item {
display: inline-block;
margin: 0 10px;
}
.nav .nav-item a {
display: inline-block;
width: 160px;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #e0e0e0;
border: 2px solid #000;
border-radius: 8px;
box-shadow: 8px 8px 5px 0 rgba(0, 0, 0, 0.7);
color: #333;
font-size: 1.3rem;
letter-spacing: 1px;
transition: 0.5s;
}
.nav .nav-item.active a,
.nav .nav-item a:hover {
background-color: #86dae6;
}