すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

ヘッダーを作ろう!

この記事で出来るようになること

前書き

FLOCSSはCSSを効率的に管理するCSS設計の手法だと前回のカリキュラムで学びましたね。

「一つのscssファイルで1ページの見た目を作る」のではなく、定義したscssファイルをいろいろなページで再利用できるように各ディレクトリで役割分担をしてscssファイルを管理するのがFLOCSSの特徴でした。

そんなFLOCSSの特徴を理解するために今回のカリキュラムでは、headerを一からコーディングしてスタイリングしていきます。

このカリキュラムでFLOCSSを使ったWeb開発のイメージを掴みましょう!

headerのコーディングをしていく前に不要な記述の削除と、rootのルーティングを設定しましょう。

以下のファイルの記述を全て削除して下さい。

tops/index.html.erb
1

以下のようにrootの設定をしましょう。

config/routes.rb
1
2
3
Rails.application.routes.draw do
  root 'tops#index'
end

headerのhtmlをコーディングしよう

初めにWakatterのheader完成系を確認してから、headerのhtmlの枠組みをコーディングしていきましょう。

以下の画像を確認すると、headerの左側にはサイトのロゴと著者があり、右側にはログインと新規登録ボタンがあることがわかります。以下の画像のように見た目を作っていきましょう。

headerの完成形画像

application.html.erbに全ページ共通の処理を加えよう

headerは <%= yield %> の前に追加します。 <%= yield %> は各アクションのviewファイルによって内容が変わり、headerは全てのページで共通にしたいため <%= yield %>の前に記述する必要があります。

以下のように <%= yield %>の手前に headerに関するhtmlの記述を追加しましょう。

application.html.erb | headerの右側にログインリンクと無料会員登録ボタンを追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
    <meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0" name="viewport">

    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&amp;family=Roboto:wght@400;700&amp;display=swap" rel="stylesheet">
    <title>Wakatter</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
<header class="l-header" id="header">
<div class="l-header__site-title">
<div class="l-header__logo">
<h1>
<%= link_to root_path do %>
<%= image_pack_tag 'logo.svg', alt: 'Wakatter' %>
<% end %>
</h1>
</div>
<div class="l-header__author">
<span class="l-header__site-author">Made by Pikawaka</span>
<span class="l-header__site-author">Challenge Lesson</span>
</div>
</div>
<div class="l-header__navigation">
<nav class="l-gnav">
<div class="l-gnav__contents--before-login">
<ul class="l-gnav__list">
<li class="l-gnav__link">
<%= link_to 'ログイン', '#' %>
</li>
<li class="l-gnav__button">
<%= link_to '無料会員登録', '#' %>
</li>
</ul>
</div>
</nav>
</div>
</header>
<%= yield %> </body> </html>

上記のhtmlファイルを作成する過程について解説します。

まずLayoutのheaderファイルなので、l-headerクラスを起点として記述していきます。

application.html.erb | headerの枠の記述を追加
1
2
3
<header class="l-header" id="header">
</header>
<%= yield %>

そして l-header のELEMENTとして __ を付けてheaderの左側部分である l-header__site-title クラスを作成します。またl-header__site-titleの様にサイト、タイトルと二つ以上の単語で表すときは、ハイフン1つで区切る命名規則にしています。

application.html.erb | headerの左側部分で表示するロゴと著者のhtmlを囲うdivを追加
1
2
3
4
5
6
7
8
9
10
11
<header class="l-header" id="header">
<div class="l-header__site-title">
<%# 左側のl-header__site-titleには、ロゴと %>
<div class="l-header__logo">
</div>
<%# 著者のhtmlを囲うdivを作成しておきます。 %>
<div class="l-header__author">
</div>
</div>
</header> <%= yield %>

右側に記述するログインと新規登録ボタンについては、headerのグローバルナビゲーションの中に作成していきます。まずグローバルナビゲーションを囲うl-header__navigationというdiv要素を作成します。

application.html.erb | header右側部分の記述を追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<header class="l-header" id="header">
  <div class="l-header__site-title">
    <div class="l-header__logo">
    </div>
    <div class="l-header__author">
    </div>
  </div>
<div class="l-header__navigation">
<nav class="l-gnav">
<div class="l-gnav__contents--before-login">
<ul class="l-gnav__list">
<li class="l-gnav__link"></li>
<li class="l-gnav__button"></li>
</ul>
</div>
</nav>
</div>
</header> <%= yield %>

これで大枠のhtmlファイルはできました。大枠の中に必要な要素を詰めていきます。
l-gnav__link のクラスは文字通りグローバルナビゲーションのリンクを表すときに使用するクラスです。 l-gnav__buttonは、グローバルナビゲーションのボタンを表すときに使うクラスになります。

l-gnav__link のクラスの中に「無料会員登録」と「ログイン」のリンク要素を入れます。

application.html.erb | headerの右側にログインリンクと無料会員登録ボタンを追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<header class="l-header" id="header">
  <div class="l-header__site-title">
    <div class="l-header__logo">
      <h1>
        <%= link_to root_path do %>
          <%= image_pack_tag 'logo.svg', alt: 'Wakatter' %>
        <% end %>
      </h1>
    </div>
    <div class="l-header__author">
      <span class="l-header__site-author">Made by Pikawaka</span>
      <span class="l-header__site-author">Challenge Lesson</span>
    </div>
  </div>

  <div class="l-header__navigation">
<nav class="l-gnav">
<div class="l-gnav__contents--before-login">
<ul class="l-gnav__list">
<li class="l-gnav__link">
<%= link_to 'ログイン', '#' %>
</li>
<li class="l-gnav__button">
<%= link_to '無料会員登録', '#' %>
</li>
</ul>
</div>
</nav>
</div> </header>
htmlでコーディングした画面を確認しよう

画面を確認してみましょう。以下の画像を確認してみると、画面いっぱいに映ったロゴ、著者のMade by Pikawaka Challenge Lesson、ログインリンク、無料会員登録のボタンが表示されたと思います。

HTMLのマークアップした画像

まだスタイル定義をしていないので、縦並びになってますね。
ロゴとMade by Pikawaka Challenge Lessonを左側に、ログインリンクと無料会員登録のボタンを右側に配置したいと思います。

flexboxを使って要素を横並びにしよう

縦に並んでいるheaderの各要素を横並びにしましょう。headerのスタイルを定義するためのファイルを作成します。headerはLayout部分に該当するので、Layoutディレクトリ直下に_l-header.scssファイルを作成します。

application.scss_l-header.scss ファイルをimportしましょう。

application.scss | _l-header.scssファイルをimportを使って追加
1
2
3
4
5
6
7
8
// Foundation
@import './Foundation/reset';
@import './Foundation/variable';
@import './Foundation/base';
@import './Foundation/mixin';

// Layout
@import './Layout/l-header';

それでは、_l-header.scssにスタイルを追加します。

_l-header.scss | flex関数を呼び出し
1
2
3
4
5
@import '../Foundation/mixin';
.l-header {
@include flex(between, center);
}

この一行の記述だけでロゴと著者を左端に、グローバルナビゲーションメニューを右端に配置できます。ブラウザでリロードした結果を確認してみましょう。

横並びの画像

ロゴと著者が左端に、グローバルナビゲーションメニューが右端に配置されております。

ではどの様にして両端に配置できたのか、先ほど追加したflex関数が定義されているapp/javascript/styles/Foundation/_mixin.scssをみます。

flex関数の初めに以下の三つのdispalyプロパティが定義されていることが分かります。
以下のプロパティは flex関数 を実行しただけで自動的に読み込まれます。

_mixin.scss | デフォルトで読み込まれるスタイル
1
2
3
  display: -webkit-flex;
display: -ms-flexbox;
display: flex;

そして、 @include flex(between, center); という記述で関数を呼び出していました。第一引数の between 第二引数の center はそれぞれ以下のハイライト部分を読み込みます。引数の値によってif文でどのプロパティを読み込むか条件分岐して読み込まれるプロパティが変わると覚えておきましょう。

_mixin.scss | flex関数の条件分岐
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// flexbox
@mixin flex($justify:0, $align:0, $wrap:0, $wrap_align:0, $column:0) {
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;

    // justify-content水平方向揃え(第一引数)
    @if $justify == start { // 左揃え
        -webkit-justify-content: flex-start;
        -ms-flex-pack: start;
        justify-content: flex-start;
    } @else if $justify == end { // 右揃え
        -webkit-justify-content: flex-end;
        -ms-flex-pack: end;
        justify-content: flex-end;
    } @else if $justify == center { // 中央揃え
        -webkit-justify-content: center;
        -ms-flex-pack: center;
        justify-content: center;
} @else if $justify == between { // 両端配置
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
} @else if $justify == around { // 均等配置 -webkit-justify-content: space-around; -ms-flex-pack: distribute; justify-content: space-around; } // align-items垂直方向揃え(第二引数) @if $align == start { // 上揃え -webkit-align-items: flex-start; -ms-flex-align: start; align-items: flex-start; } @else if $align == end { // 下揃え -webkit-align-items: flex-end; -ms-flex-align: end; align-items: flex-end;
} @else if $align == center { // 中央揃え
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
} @else if $align == baseline { // ベースライン -webkit-align-items: baseline; -ms-flex-align: baseline; align-items: baseline; } @else if $align == stretch { // 高さ揃え -webkit-align-items: stretch; -ms-flex-align: stretch; align-items: stretch; }

最終的には、@include flex(between, center); の記述で以下のプロパティが読み込まれ

_mixin.scss | flex関数で最終的に読み込まれるスタイル
1
2
3
4
5
6
7
8
9
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-justify-content: space-between;
  -ms-flex-pack: justify;
  justify-content: space-between;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;

以下の画像のような横並びが実現します。

横並びの画像

両橋に配置はされましたが、左側のWakatterのロゴと著者は縦並び、右側のログインと新規登録ボタンは縦並びになってます。

先ほど横並びしたのと同じ様に .l-header___site-title@include flex(start, center); を定義する事で、ロゴと著者の縦並びを横並びに変更しましょう。

_l-header.scss | ロゴと著者の縦並びを横並び
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@import '../Foundation/mixin';
@import '../Foundation/variable';
.l-header { @include flex(between, center);
&__site {
&-title {
@include flex(start, center);
}
&-author {
display: block;
color: $grey;
font-size: 12px;
line-height: 1.4em;
}
}
&__logo {
width: 180px;
height: 40px;
a:hover {
// 小数点の場合は、0を省略してもOK。実質0.7と同じ意味になります。
opacity: .7;
}
}
}

以下の動画のようになっているか画面を確認してみましょう。

横並び確認動画

ロゴと著者が横並びになっている事が分かります。
ロゴをhoverすると薄くなり、ロゴがリンクらしくなってますね。
今のままだとロゴと著者が近すぎるので、marginを当てましょう。

_l-header.scss | ロゴと著者のmarginをあける
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-header {
  @include flex(between, center);

&__author {
margin-left: 10px;
padding-top: 6px;
}
&__site { &-title { @include flex(start, center); } &-author { display: block; color: $grey; font-size: 12px; line-height: 1.4em; @include smartphone { font-size: 10px; line-height: 1.2em; } } } &__logo { width: 180px; height: 40px; a:hover { opacity: .7; } } }

著者を囲っているdivタグのクラスの.l-header__authorにmarginとpaddingを当ててスタイルを微調整しました。

次に右側のログインと新規登録ボタンが縦並びになっているのを、横並びに変更します。

右側のログインと新規登録ボタンを横並び

ログインと新規登録ボタンはグローバルナビゲーションメニューでした。

グローバルナビゲーションのスタイルを定義する _l-gnav.scssファイルを作成します。

Layoutディレクトリに _l-gnav.scss ファイルを作成します。

作成すれば続いて application.scss_l-gnav.scss ファイルをimportします。

application.scss | _l-gnav.scssファイルをインポート
1
2
3
4
5
6
7
8
9
// Foundation
@import './Foundation/reset';
@import './Foundation/variable';
@import './Foundation/base';
@import './Foundation/mixin';

// Layout
@import './Layout/l-header';
@import './Layout/l-gnav';

importすれば、_l-gnav.scssにスタイルを追加して、横並びにしていきましょう。
以下の記述でログインと無料会員登録が横並びにできます。

_l-gnav.scss | ファイルを新規作成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@import '../Foundation/mixin';
.l-gnav {
&__contents {
&--before-login {
@include flex();
padding: 15px 30px 15px 0;
}
}
&__list {
font-size: 14px;
position: relative;
@include flex(between, center);
}
}

次にログインリンクにスタイルを定義します。普段の色はグレーでhoverすると青くなるようにし、ログインリンクと無料会員登録ボタンが近すぎたので、paddingで離して見やすくしましょう。

以下の記述を加えて下さい。

_l-gnav.scss | ログインリンクと無料会員登録ボタンをpaddingで間隔を開ける
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@import '../Foundation/mixin';
@import '../Foundation/variable';
.l-gnav { &__contents { &--before-login { padding: 15px 30px 15px 0; } } &__list { font-size: 14px; position: relative; @include flex(between, center); }
&__link {
padding: 0 30px 0 0;
a {
color: $dark-grey;
&:hover {
color: $blue;
}
}
}
}

以下の動画のように指定したスタイルが反映できているか確認しましょう。

ログインリンクをホバーしている画像

ボタンのComponentを作ろう

以下の完成画像を見てみると、無料会員登録ボタンは黄色のボタンになっています。

headerの完成形画像

この黄色ボタンに関しては、いろいろなところで使い回すので、Componentのボタンとして定義しましょう。

Componentの中に _c-button.scss ファイルを作成しましょう。

_c-button.scssファイルを application.scss にimportします。

application.scss | _c-button.scssファイルをimport
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Foundation
@import './Foundation/reset';
@import './Foundation/variable';
@import './Foundation/base';
@import './Foundation/mixin';

// Layout
@import './Layout/l-header';
@import './Layout/l-gnav';

//
// Object
//
// Component
@import './Object/Component/c-button';

それでは、 _c-button.scss ファイルのスタイルを定義します。
まず全てのボタンで共通するボタンのデフォルトのスタイルを定義します。

_c-button.scss | ファイルを新規作成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ボタンのコンポーネント

@import '../../Foundation/variable';
.c-button {
padding: 16px 24px;
font-size: 16px;
color: $white !important;
text-decoration: none;
&:hover {
text-decoration: none;
}
}

この .c-button のスタイルが全てのボタンで使用する基本のスタイルになります。

基本的に新しいボタンを作るときは、 .c-button を継承したボタンのクラスを作る様にします。

.c-button を継承した無料会員登録の様な黄色いボタンのクラスを作成してみましょう。

_c-button.scss | 無料会員登録の様な黄色いボタンのクラスを作成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ボタンのコンポーネント

@import '../../Foundation/variable';

.c-button {
  padding: 16px 24px;
  font-size: 16px;
  color: $white !important;
  text-decoration: none;

  &:hover {
    text-decoration: none;
  }

// 基本の四角い黄色いボタン
&--square-yellow {
@extend .c-button;
border-radius: 4px;
background-color: $yellow;
&:hover {
background-color: $dark-yellow;
}
}
}

ベースのボタンを継承した基本の四角い黄色いボタンのクラスを作成しました。

この黄色いボタンを無料会員登録に反映してみましょう。

application.html.erb | 無料会員登録ボタンにc-button--square-yellowクラスを追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<header class="l-header" id="header">
  <div class="l-header__site-title">
    <div class="l-header__logo">
      <h1>
        <%= link_to root_path do %>
          <%= image_pack_tag 'logo.svg', alt: 'Wakatter' %>
        <% end %>
      </h1>
    </div>
    <div class="l-header__author">
      <span class="l-header__site-author">Made by Pikawaka</span>
      <span class="l-header__site-author">Challenge Lesson</span>
    </div>
  </div>

  <div class="l-header__navigation">
    <nav class="l-gnav">
      <div class="l-gnav__contents--before-login">
        <ul class="l-gnav__list">
          <li class="l-gnav__link">
            <%= link_to 'ログイン', '#' %>
          </li>
          <li class="l-gnav__button">
            <%# 無料会員登録のボタンにc-button--square-yellowクラスを追加 %>
<%= link_to '無料会員登録', '#', class: 'c-button--square-yellow' %>
<%# 無料会員登録のボタンにc-button--square-yellowクラスを追加 %> </li> </ul> </div> </nav> </div> </header>

リロードして反映を確認してみましょう。以下の画像を確認すると、無料会員登録ボタンが黄色いボタンになって一見うまく行ってる様に見えますが

無料会員登録の画像

Wakatterの完成版と見比べてみると、黄色いボタンがかなり大きく見えます。

headerの完成形画像

基本の四角い黄色いボタンは定義しましたが、次はこのヘッダーのサイズに合う黄色い四角いボタンを定義する必要があります。

_c-button.scss | 黄色い四角いボタンを定義
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// ボタンのコンポーネント

@import '../../Foundation/variable';

.c-button {
  padding: 16px 24px;
  font-size: 16px;
  color: $white !important;
  text-decoration: none;

  &:hover {
    text-decoration: none;
  }

  // 基本の四角い黄色いボタン
  &--square-yellow {
    @extend .c-button;
    border-radius: 4px;
    background-color: $yellow;

    &:hover {
      background-color: $dark-yellow;
    }
  }

// ヘッダーの無料会員登録ボタン
&--header {
@extend .c-button--square-yellow;
padding: 11px 25px;
font-size: 12px;
font-weight: bold;
}
}

黄色い四角いボタンを継承したheader専用の無料会員登録ボタン、c-button--header クラスを作成しました。

無料会員登録ボタンはいろいろな所で出現しますが、ボタンの大きさや文字の大きさなどは無料会員登録ボタンが出現する場所によって異なります。

例えば、pikawakaサイトに訪問してみるとpikawakaのヘッダーの無料会員登録ボタンと投稿の中のfooter部分の無料会員登録ボタンでは、分かりづらいですがボタンの大きさ・文字の大きさが実は異なります。

header

headerの無料会員登録ボタン

footer

footerの無料会員登録ボタン

この様に黄色い四角いボタンは基本のベースとして定義してあって、ボタンの大きさや文字の大きさなどは無料会員登録ボタンを挿入する場所によって柔軟に変える必要があります。

そのため黄色い四角いボタンを継承して、ボタンの大きさや文字の大きさの差分だけを変更して定義した c-button--header というヘッダーの無料会員登録ボタンのクラスを作成しました。

そうすれば、背景色が黄色だったり角を少し丸くしているスタイルは重複して定義する必要もなく、差分だけのスタイルを定義したヘッダー専用の黄色い四角いボタンのクラスを定義することができます。

それでは、無料会員登録ボタンに c-button--square-yellow ではなく、 c-button--header クラスを与えましょう。

application.html.erb | 無料会員登録ボタンにc-button--headerクラスを追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<header class="l-header" id="header">
  <div class="l-header__site-title">
    <div class="l-header__logo">
      <h1>
        <%= link_to root_path do %>
          <%= image_pack_tag 'logo.svg', alt: 'Wakatter' %>
        <% end %>
      </h1>
    </div>
    <div class="l-header__author">
      <span class="l-header__site-author">Made by Pikawaka</span>
      <span class="l-header__site-author">Challenge Lesson</span>
    </div>
  </div>
  <div class="l-header__navigation">
    <nav class="l-gnav">
      <div class="l-gnav__contents--before-login">
        <ul class="l-gnav__list">
          <li class="l-gnav__link">
            <%= link_to 'ログイン', '#' %>
          </li>
          <li class="l-gnav__button">
            # 無料会員登録のボタンに与えるクラスをc-button--square-yellowからc-button--headerに変更
<%= link_to '無料会員登録', '#', class: 'c-button--header' %>
# 無料会員登録のボタンに与えるクラスをc-button--square-yellowからc-button--headerに変更 </li> </ul> </div> </nav> </div> </header>

c-button--headerは黄色い四角いボタンを継承しているので、無料会員登録ボタンに指定するクラスも一つだけで済みます。

<%= link_to '無料会員登録', '#', class: 'c-button c-button--square-yellow c-button--header' %>の様に複数のクラスを当てなくても、継承を使えば一つのクラスの指定だけで済むので、すっきりしますね。

ヘッダーを確認してみましょう!以下の画像のように無料会員登録ボタンがヘッダー専用の無料会員登録ボタンになってますね。

PC版完成間近のheader画像

かなり完成に近付いてきました。

最後に簡単なヘッダーの調整をしましょう。

ロゴが左に寄りすぎているので、左側にpaddingを開けましょう。そしてheaderと分かり易いように影を入れましょう。

_l-header.scss | headerに影を追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-header {
box-shadow: 0 0 15px $box-shadow;
background-color: $white;
padding: 0 0 0 20px;
@include flex(between, center); &__author { margin-left: 10px; padding-top: 6px; } &__site { &-title { @include flex(start, center); } &-author { display: block; color: $grey; font-size: 12px; line-height: 1.4em; @include smartphone { font-size: 10px; line-height: 1.2em; } } } &__logo { width: 180px; height: 40px; a:hover { opacity: .7; } } }

リロードしてみると、影によりheaderであることが際立ちましたね。
これでPC版の画面は完成です。

ヘッダーをレスポンシブ対応にしよう

これでWakatterのヘッダーが完成した様に思えますが、完成したのはPC版です。
レスポンシブに関しては、未対応です。

レスポンシブが一体どういうものか、Pikawakaサイトを参考に説明します。

以下の動画のようにPikawakaサイトの画面幅を小さくしていくと、大きいサイズのタブレットの画面、小さいサイズのタブレットの画面、スマートフォンの画面と画面の横幅によって画面の表示が切り替わっていることが分かります。

Pikawakaのレスポンシブに関する動画

pikawakaの様に同じURL・HTMLで、大きいサイズのタブレット・小さいサイズのタブレット・スマートフォンと異なる画面のサイズでそれぞれのデバイスに最適な表示をすることをレスポンシブデザインと言います。

以下のWakatter完成版のレスポンシブに関する動画を見てみると、パソコン画面にはなかったタブレットの画面・スマートフォンの画面だけで表示されるハンバーガーメニューがあります。ハンバーガーメニューをタップすると、サイドメニューが展開されログインや無料会員登録ボタンを表示できます。

wakatterのレスポンシブに関する挙動の動画

パソコン画面のヘッダーのレイアウトはできているので、次はスマートフォンで同じURL・HTMLでハンバーガーメニューなどを表示できる様にHTMLやスタイルを定義していきます。

まずハンバーガーメニューを表示するhtmlを追記していきます。

application.html.erb | ハンバーガーメニューを表示するhtmlを追記
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<header class="l-header" id="header">
  <div class="l-header__site-title">
    <div class="l-header__logo">
      <h1>
        <%= link_to root_path do %>
          <%= image_pack_tag 'logo.svg', alt: 'Wakatter' %>
        <% end %>
      </h1>
    </div>
    <div class="l-header__author">
      <span class="l-header__site-author">Made by Pikawaka</span>
      <span class="l-header__site-author">Challenge Lesson</span>
    </div>
  </div>
  <div class="l-header__navigation">
    <nav class="l-gnav">
      <%# hambergerメニューのスタイルとクリックした時クローズしたときのhtmlを定義します。 %>
<input class="l-gnav__hum-menu" id="gnav-input" type="checkbox"></input>
<label class="l-gnav__open-menu" for="gnav-input">
<span></span>
</label>
<label class="l-gnav__close-menu" for="gnav-input"></label>
<div class="l-gnav__contents--before-login"> <ul class="l-gnav__list"> <li class="l-gnav__link"> <%= link_to 'ログイン', '#' %> </li> <li class="l-gnav__button"> <%= link_to '無料会員登録', '#', class: 'c-button--header' %> </li> </ul> </div> </nav> </div> </header>

以下の画像のようにブラウザで確認してみると、チェックボックスが追加されていることが確認できます。

チェックボックスが追加された画像

まだスタイルを追加してないので、チェックボックスが表示されているだけですが、この部分がスマートフォン表示のハンバーガーメニューに相当します。

それではスマートフォンの画面サイズの時に、追記したハンバーガーメニューを表示できる様にスタイルを追加します。

_mixin.scss ファイルの6~19行目に注目しましょう。

_mixin.scss | メディアクエリの説明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// メディアクエリ
// タブレットのレイアウト
@mixin tablet {
  @media screen and (max-width: 1023px) {
    @content;
  }
}

// スマホレイアウト
@mixin smartphone {
  @media screen and (max-width: 480px) {
    @content;
  }
}

関数の中身を見てみると、
@media screen and (max-width: 1023px) {
@media screen and (max-width: 480px) {

と書いています。

@media screen and (max-width: 1023px) {と書かれている@media screen〜はどういう意味でしょうか?

@media screen and (max-width: 1023px) {} を使えば、以下に書かれている通りに横幅に応じて、適用するスタイルを変えることができます。

1
2
3
@media screen and (max-width: 1023px) {
  // ここに定義されたスタイルはウィンドウの横幅が1023pxまでのスタイルを適用
}

先ほどのpikawakaサイトでデバイスごとに表示が切り替わる部分をもう一度しっかり見てみましょう。

pikawaka breakpoint

Pikawakaでは、1023pxと768pxと480pxの部分で表示が切り替わっていることが分かります。

ブレイクポイントを1023px(最大幅のタブレット), 768px(最小幅のタブレット), 480px(スマートフォン)に指定して表示を切り替えていることが分かりますね。

wakatterでは、最小幅のタブレット(768px)と最大幅のタブレット(1023px)でスタイルを変える必要はあまりなかったので、tabletのブレイクポイントを使って同じスタイルで定義しています。

このそれぞれの関数を適用したいレスポンシブのデバイスの部分で以下の関数を呼び出してあげることにより、各デバイスごとにスタイルを定義することができます。

  • @include tablet;
  • @include smartphone;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// メディアクエリ
// タブレットのレイアウト
@mixin tablet {
  @media screen and (max-width: 1023px) {
    @content;
  }
}

// スマホレイアウト
@mixin smartphone {
  @media screen and (max-width: 480px) {
    @content;
  }
}

それでは、スマートフォンのデバイスでハンバーガーメニューを表示できる様にスタイルを追加します。
ハンバーガーメニューで使うチェックボックスも非表示にしましょう。

_l-gnav.scss | ハンバーガーメニューのスタイルを追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-gnav {
  &__contents {
    &--before-login {
      @include flex();
      padding: 15px 30px 15px 0;
    }
  }

  &__list {
    font-size: 14px;
    position: relative;
    @include flex(between, center);
  }

  &__link {
    padding: 0 30px 0 0;
    a {
      color: $dark-grey;
      &:hover {
        color: $blue;
      }
    }
  }

&__hum-menu {
display: none;
}
// 1023px以下のときハンバーガーメニューにする(このコメントは残す)
@include tablet {
// 1023px以下の時はこのスタイルが適用されます。spanとspanのbefore, afterの擬似要素にグレーラインのスタイルを定義します。
&__open-menu {
display: inline-block;
width: 30px;
height: 22px;
vertical-align: middle;
span,
span:before,
span:after {
position: absolute;
height: 3px;
width: 25px;
border-radius: 2px;
background: $grey;
display: block;
content: '';
}
// 重なった三本線に対してbottomの指定で高さを調整してハンバーガーメニューにします。
span:before {
bottom: -8px;
}
span:after {
bottom: -16px;
}
}
}
}

リロードしてスタイルが適用されているかを確認しましょう。

以下の画像のようにチェックボックスが消えて、ハンバーガーメニューが表示されることを確認できました。

ハンバーガーメニューの表示画像

ログインと無料会員登録ボタンを表示せずにハンバーガーメニューをクリックしたときに表示されるサイドバーにログインと無料会員登録ボタンを表示したいですね。

サイドバーを作ろう

ハンバーガーメニューをクリックした時にサイドバーを表示し、サイドバーの中にあるログインボタンと無料会員登録ボタンを表示する様に修正します。

_l-gnav.scss | サイドバーの中にあるログインボタンと無料会員登録ボタンを表示する様に修正
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
@import '../Foundation/mixin';
@import '../Foundation/variable';

// グローバルナビゲーションのスタイル

.l-gnav {
  &__contents {
    &--before-login {
      @include flex();
      padding: 15px 30px 15px 0;
    }
  }

  &__list {
    font-size: 14px;
    position: relative;
    @include flex(between, center);
  }

  &__link {
    padding: 0 30px 0 0;

    a {
      color: $dark-grey;

      &:hover {
        color: $blue;
      }
    }
  }

  &__hum-menu {
    display: none;
  }
  // 1023px以下のときハンバーガーメニューにする(このコメントは残す)
  @include tablet {
    &__open-menu {
      display: inline-block;
      width: 30px;
      height: 22px;
      vertical-align: middle;

      span,
      span:before,
      span:after {
        position: absolute;
        height: 3px;
        width: 25px;
        border-radius: 2px;
        background: $grey;
        display: block;
        content: '';
      }

      span:before {
        bottom: -8px;
      }

      span:after {
        bottom: -16px;
      }
    }

    // こちらのクラスはログインする前の状態を表しています。--は状態を表すので、--before-loginでloginする前のスタイルを定義し、レスポンシブでサイドバーのログインと無料会員登録ボタンのスタイルを定義してます。
&__contents--before-login {
overflow: auto;
position: fixed;
top: 0;
right: 0;
z-index: 9999;
width: 80%;
height: 100%;
background: #fff;
transition: .3s ease-in-out;
transform: translateX(110%);
font-size: 16px;
}
// html側でハンバーガーメニューを押した時に、非表示にしたcheckboxにチェックが付く様にしています。(この時application.html.erbの33・34行目にフォーカスを当てて、checkboxのinputタグのidがハンバーガーメニューを表示しているl-gnav__open-menuとforで指定することにより紐づいて、ハンバーガーメニューを押しただけでチェックボックスのチェックと外すことができる様になっていることを動画で伝える。)つまりハンバーガーメニューを押す(チェックされた場合は)と、htmlのl-gnav__hum-menuからl-gnav__close-menuまでのスタイルをdisplay blockにし、opacityを指定してます。スタイルの内容については、閉じるスタイルをまだ記述していないので、後に説明します。
&__hum-menu:checked ~ &__close-menu {
display: block;
opacity: .5;
}
// こちらもハンバーガーメニューを押した場合のスタイルを記述していて、l-gnav__contents--before-loginに指定している80%分のサイドバーの横幅(375pxであれば300px)をtransform: translateX(0);の記述で出現させている。この引数に例えば100pxなどを指定すると、200px分しか出現しない。0を指定することにより80%いっぱいまでサイドバーを表示できる。box-shadowで簡単に影もつけている。
&__hum-menu:checked ~ &__contents--before-login {
transform: translateX(0);
box-shadow: 6px 0 25px rgba(0,0,0,.15);
}
} }

以下の動画を見ると、ログインと無料会員登録ボタンが表示されていないことが確認できますね。

クリックした時にサイドバーが表示されて、サイドバーの中にログインと無料会員登録ボタンが表示されるようになっています。

サイドバーの表示動画

しかし、今のままだとサイドバーを閉じることができません。また、サイドバーをクリックした時の全体的な背景色が白でサイドバーを開いていることも目立ちません。

サイドバーをクローズできるようにするのと、サイドバーをを目立たせる様に背景色を調整しましょう。

_l-gnav.scss | サイドバーをを目立たせる様に背景色を調整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// グローバルナビゲーションのスタイル

@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-gnav {
  &__contents {
    &--before-login {
      @include flex();
      padding: 15px 30px 15px 0;
    }
  }

  &__list {
    font-size: 14px;
    position: relative;
    @include flex(between, center);
  }

  &__link {
    padding: 0 30px 0 0;

    a {
      color: $dark-grey;

      &:hover {
        color: $blue;
      }
    }
  }

  &__hum-menu {
    display: none;
  }
  // 1023px以下のときハンバーガーメニューにする(このコメントは残す)
  @include tablet {
    &__open-menu {
      display: inline-block;
      width: 30px;
      height: 22px;
      vertical-align: middle;

      span,
      span:before,
      span:after {
        position: absolute;
        height: 3px;
        width: 25px;
        border-radius: 2px;
        background: $grey;
        display: block;
        content: '';
      }

      span:before {
        bottom: -8px;
      }

      span:after {
        bottom: -16px;
      }
    }

    // ここを追加、checkboxをクリックしてサイドメニューを開くときのモーダル感のような暗さのスタイルを定義してます。周りを暗くすることによって今サイドメニューを開いているとはっきりさせます。$dark-greyだと暗すぎるので、先ほど定義したopacity: 0.5の部分で色の強さを半透明にしてます。

&__close-menu {
display: none;
position: fixed;
z-index: 99;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: $dark-grey;
opacity: 0;
transition: .3s ease-in-out;
}
&__contents--before-login { overflow: auto; position: fixed; top: 0; right: 0; z-index: 9999; width: 80%; height: 100%; background: #fff; transition: .3s ease-in-out; transform: translateX(110%); font-size: 16px; } &__hum-menu:checked ~ &__close-menu { display: block; opacity: .5; } &__hum-menu:checked ~ &__contents--before-login { transform: translateX(0); box-shadow: 6px 0 25px rgba(0,0,0,.15); } } }

リロードして確認すると、以下の画像のようにサイドバーが目立ち、またクローズできる様になりました。

サイドバーを開けたり閉じたりする動画

サイドバーを開いたときのデザインが崩れているので、調整しましょう。

_l-gnav.scss | サイドバーのスタイルの調整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// グローバルナビゲーションのスタイル

@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-gnav {
  &__contents {
    &--before-login {
      @include flex();
      padding: 15px 30px 15px 0;

@include tablet {
display: block;
padding: 20px 30px;
}
} } &__list { font-size: 14px; position: relative; @include flex(between, center);
@include tablet {
display: block;
}
} &__link { padding: 0 30px 0 0; a { color: $dark-grey; &:hover { color: $blue; } }
@include tablet {
padding: 0 0px 20px 0px;
font-size: 16px;
}
} // ヘッダーのボタン
&__button {
@include tablet {
width: 100%;
}
}
// ハンバーガーメニュー &__hum-menu { display: none; } // 1023px以下のときハンバーガーメニューにする @include tablet { &__open-menu { display: inline-block; width: 30px; height: 22px; vertical-align: middle; span, span:before, span:after { position: absolute; height: 3px; width: 25px; border-radius: 2px; background: $grey; display: block; content: ''; } span:before { bottom: -8px; } span:after { bottom: -16px; } } &__close-menu { display: none; position: fixed; z-index: 99; top: 0; left: 0; width: 100%; height: 100%; background: $dark-grey; opacity: 0; transition: .3s ease-in-out; } &__contents--before-login { overflow: auto; position: fixed; top: 0; right: 0; z-index: 9999; width: 80%; height: 100%; background: #fff; transition: .3s ease-in-out; transform: translateX(110%); font-size: 16px; } &__hum-menu:checked ~ &__close-menu { display: block; opacity: .5; } &__hum-menu:checked ~ &__contents--before-login { transform: translateX(0); box-shadow: 6px 0 25px rgba(0,0,0,.15); } } }

以下の画像の通りになっていれば、サイドバーのデザインを修正できています。

サイドバーの崩れているデザインを修正

サイドバーのデザインの崩れは修正できました。次は無料会員登録のボタンのテキストを真ん中寄せにするように修正しましょう。

app/javascript/styles/Object/Component/_c-button.scssを開いて以下のように修正しましょう。

_c-button.scss | 無料会員登録のボタンのテキストを真ん中寄せにするように修正
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// ボタンのコンポーネント

@import '../../Foundation/variable';

.c-button {
  padding: 16px 24px;
  font-size: 16px;
  color: $white !important;
  text-decoration: none;

  &:hover {
    text-decoration: none;
  }

  // 基本の四角い黄色いボタン
  &--square-yellow {
    @extend .c-button;
    border-radius: 4px;
    background-color: $yellow;

    &:hover {
      background-color: $dark-yellow;
    }
  }

  // ヘッダーの無料会員登録ボタン
  &--header {
    @extend .c-button--square-yellow;
    padding: 11px 25px;
    font-size: 12px;
    font-weight: bold;

@include tablet {
display: block;
font-size: 16px;
text-align: center;
}
} }

以下の画像のように無料会員登録のボタンのテキストが真ん中によっていれば、ハンバーガーメニュー・サイドバーの実装は完了です。

無料会員登録のボタンのテキストを真ん中寄せにしている画像

続いてロゴや著者の上下の幅が詰め詰めになっているので、次は左側のロゴや著者の1023px以下(tablet)のデバイスのスタイルを定義していきます。

app/javascript/styles/Layout/_l-header.scssを開いてみましょう。

_l-header.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-header {
  box-shadow: 0 0 15px $box-shadow;
  background-color: $white;
  padding: 0 0 0 20px;
  @include flex(between, center);

@include tablet {
padding: 15px 20px;
}
&__author { margin-left: 10px; padding-top: 6px; @include smartphone { padding-top: 4px; } } &__site { &-title { @include flex(start, center); } &-author { display: block; color: $grey; font-size: 12px; line-height: 1.4em; } } &__logo { width: 180px; height: 40px; a:hover { opacity: .7; } } }

tabletサイズの時のスタイルを確かめてみましょう。上下の幅に余裕ができました。ただスマートフォンのサイズで見てみると、上下が開き過ぎに思えるのでスマートフォンのサイズの場合は文字を小さくして上下の感覚も狭くしましょう。

スマートフォンのサイズの調整をします。

_l-gnav.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@import '../Foundation/mixin';
@import '../Foundation/variable';

.l-header {
  box-shadow: 0 0 15px $box-shadow;
  background-color: $white;
  padding: 0 0 0 20px;
  @include flex(between, center);

  @include tablet {
    padding: 15px 20px;
  }

  &__author {
    margin-left: 10px;
    padding-top: 6px;

    @include smartphone {
      padding-top: 4px;
    }
  }

  &__site {
    &-title {
      @include flex(start, center);
    }

    &-author {
      display: block;
      color: $grey;
      font-size: 12px;
      line-height: 1.4em;

@include smartphone {
font-size: 10px;
line-height: 1.2em;
}
} } &__logo { width: 180px; height: 40px;
@include smartphone {
width: 140px;
height: auto;
}
a:hover { opacity: .7; } } }

スマートフォンサイズで違和感のない文字の大きさと上下の幅になりましたね。

以下の動画のようにスマートフォンのスタイリングが適用されていればレスポンシブ用のスタイルが完了です!

レスポンシブの完成動画

最後に

今回は FLOCSSを使ってスタイルを適用する方法を中心に学びました。これからのカリキュラムについては基本的に 既に定義済みの scssファイルをダウンロードして設定することによって見た目を整えていきます。

次回以降のカリキュラムでどのようにスタイルを適用しているか気になった方は、ぜひこちらのカリキュラムを振り返ってFLOCSSを使ったスタイルの適用方法を見直して下さい。

次は、サーバーサイドの開発を中心にカリキュラムを進めていきます。

この記事のまとめ

  • レスポンシブデザインとは、同じURL・HTMLで、大きいサイズのタブレット・小さいサイズのタブレット・スマートフォンと異なる画面のサイズでそれぞれのデバイスに最適な表示をすること
  • 横並びのようなよく使うまとまったスタイルに関しては、関数を定義して _mixin.scss ファイルに定義しておくと便利