第3章 5節 mod-button-0001を作ろう

この節について

この節ではボタンのモジュールを作成していきますが、ボタンはサイト内の多くの箇所で使用されるモジュールであるということは容易に想像できます。

非常に基本的なモジュールで、見た目もシンプルですが、実は初期段階の設計が難しいモジュールでもあります。
多くの箇所で使用するだけに、拡張が必要になることも多く、行き当たりばったりで無計画に作成するとコードが煩雑になっていく要因になりやすいモジュールです。

disabledな状態、inline-blockのボタン、色、大きさ、ボタン内のテキスト改行の可否、アイコンフォントの入っているものなど、実際のプロジェクトで初めからその全てを作ってしまうと過剰な面もあると思いますが、それらの派生モジュールが必要になったときに拡張しやすい「基本のボタン」を作成しておくことはとても有効です。

今回は以下のようなボタンの作成を通して、実際のサイトの制作や運用に活かせるようにボタンモジュールの作成に慣れていきましょう。

  • 基本のボタン
  • disabledのボタン
  • inline-blockのボタン
  • 色の違うボタン(基本のボタン + 3色)
  • 高さの違うボタン(基本のボタン + 4サイズ)
  • 文字の左右にアイコンがあるボタン
  • 左右両端にアイコンがあるボタン

HTML

まずは以下のHTMLを public/html/module-list.html に追記します。

1
<a href="#">基本のボタン / カラーprimary / サイズmd</a>

Block名を決める

今回のBlock名は mod-button-0001 にします。

scssファイルの作成

ファイル名の命名規則は _Block名.scss です。

先ほど決めたBlock名の先頭にアンダースコア(_)を足したものがファイル名になりますので src/scss/modules/_mod-button-0001.scss を作成します。

Blockクラス

まずは

  • 基本のボタン

を作っていきましょう。

Blockクラスを以下の通り記述します。
先ほど決めたBlock名がそのままクラス名になります。
今回のボタンモジュールは比較的シンプルなデザインのものですがとても多くのプロパティを設定します。

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
.mod-button-0001 {
display: flex;
justify-content: center;
align-items: center;
position: relative;
border-style: solid;
padding-left: 20px;
padding-right: 20px;
width: 100%;
text-align: center;
text-decoration: none;
box-sizing: border-box;
border-radius: 4px;
cursor: pointer;
// ボタンの高さに関わるプロパティ
border-width: 2px;
padding-top: 8px;
padding-bottom: 8px;
line-height: 24px;
font-size: 16px;
// ボタンの色に関わるプロパティ(focus, hoverも含む)
border-color: #ef940b;
background-color: #ef940b;
color: #ffffff;
&:focus,
&:hover {
border-color: lighten(#ef940b, 8%);
background-color: lighten(#ef940b, 8%);
}
}

Blockクラスを付与します。

1
<a href="#" class="mod-button-0001">基本のボタン / カラーprimary / サイズmd</a>

これで基本のボタンのモジュールが1つできました。

Modifierクラス(1つめ)

次は

  • disabledのボタン

を作っていきましょう。

aタグを以下のように1つ追記します。
先ほど作成したボタンは略して、追記分だけを記述しています。

1
2
〜略〜
<a href="#" class="mod-button-0001">状態disabled</a>

disabled属性を付与しても、Modifierクラスのmod-button-0001–disabledを付与しても、同じスタイルが適用されるように以下のとおり追記することにします。

1
2
3
4
5
6
7
8
9
10
11
&[disabled],
&.mod-button-0001--disabled {
// !importantは原則として使用禁止ですが、他のModifierクラスと一緒に付与したときでもdisabledの状態は最も優先されるべきなので使用しています。
border-color: #eeeeee !important;
background-color: #eeeeee !important;
color: #bbbbbb !important;
cursor: default !important;
&:focus {
box-shadow: none !important;
}
}

以下のようにModifierクラス mod-button-0001--disabled を付与することにします。

1
2
〜略〜
<a href="#" class="mod-button-0001 mod-button-0001--disabled">状態disabled</a>

aタグなのでModifierクラスの方を付与しましたが、buttonタグやinput type=”submit” のタグの場合はdisabled属性だけを付与すれば大丈夫です。

Modifierクラス(2〜9個目)

この節のModifierは全部で10個作成しますが、2〜9個目のModifierは同じ要領で追記していくだけなのでまとめて書いてしまいます。

2〜9個目のModifierとして

  • inline-blockのボタン
  • 色の違うボタン(基本のボタン + 3色)
  • 高さの違うボタン(基本のボタン + 4サイズ)

を作っていきましょう。

module-list.html に以下のようにaタグを8個追記します。
先ほどまでに記述したaタグ2つは略しています。

1
2
3
4
5
6
7
8
9
〜略〜
<a href="#" class="mod-button-0001">display inline-block</a>
<a href="#" class="mod-button-0001">カラーsecondary</a>
<a href="#" class="mod-button-0001">カラーneutral</a>
<a href="#" class="mod-button-0001">カラーtransparent</a>
<a href="#" class="mod-button-0001">サイズxl</a>
<a href="#" class="mod-button-0001">サイズlg</a>
<a href="#" class="mod-button-0001">サイズsm</a>
<a href="#" class="mod-button-0001">サイズxs</a>

以下の通り2〜9個目のmodifierを _mod-button-0001.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
.mod-button-0001 {
〜略〜
&.mod-button-0001--inline-block {
display: inline-block;
width: auto;
}
&.mod-button-0001--secondary {
border-color: #db0f28;
background-color: #db0f28;
color: #ffffff;
&:focus,
&:hover {
border-color: lighten(#db0f28, 8%);
background-color: lighten(#db0f28, 8%);
}
}
&.mod-button-0001--neutral {
border-color: #888888;
background-color: #888888;
color: #ffffff;
&:focus,
&:hover {
border-color: lighten(#888888, 8%);
background-color: lighten(#888888, 8%);
}
}
&.mod-button-0001--transparent {
border-color: transparent;
background-color: transparent;
color: #0000E9;
&:focus,
&:hover {
opacity: 0.7;
background-color: #eeeeee;
}
}
&.mod-button-0001--size-xl {
padding-top: 16px;
padding-bottom: 16px;
line-height: 36px;
font-size: 24px;
}
&.mod-button-0001--size-lg {
padding-top: 11px;
padding-bottom: 11px;
line-height: 30px;
font-size: 20px;
}
&.mod-button-0001--size-sm {
padding-top: 4px;
padding-bottom: 4px;
line-height: 20px;
font-size: 13px;
}
&.mod-button-0001--size-xs {
padding-top: 0;
padding-bottom: 0;
line-height: 16px;
font-size: 10px;
}
}

新たに作成したModifierクラス8個を以下のように付与します。

1
2
3
4
5
6
7
8
9
〜略〜
<a href="#" class="mod-button-0001 mod-button-0001--inline-block">display inline-block</a>
<a href="#" class="mod-button-0001 mod-button-0001--secondary">カラーsecondary</a>
<a href="#" class="mod-button-0001 mod-button-0001--neutral">カラーneutral</a>
<a href="#" class="mod-button-0001 mod-button-0001--transparent">カラーtransparent</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-xl">サイズxl</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-lg">サイズlg</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-sm">サイズsm</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-xs">サイズxs</a>

Elementクラスを作成してアイコンモジュールを入れ子にする

次はElementクラスを作成して、その中にFont Awesomeのアイコンを入れ子にしてみましょう。

まず module-list.html に以下のようにaタグとspanタグを追記します。
先ほどまでに記述したaタグは略しています。

1
2
3
4
5
6
7
8
9
10
〜略〜
<a href="#" class="mod-button-0001">
<span>

</span>
テキストの左右にアイコン
<span>

</span>
</a>

以下の通り2つのElementクラスを _mod-button-0001.scss に追記します。
追記部分以外は略しています。

1
2
3
4
5
6
7
8
9
.mod-button-0001 {
〜略〜
.mod-button-0001__before-icon-wrapper {
margin-right: 0.4em;
}
.mod-button-0001__after-icon-wrapper {
margin-left: 0.4em;
}
}

新たに作成したElementクラスを以下のように付与します。

1
2
3
4
5
6
7
8
9
10
〜略〜
<a href="#" class="mod-button-0001">
<span class="mod-button-0001__before-icon-wrapper">

</span>
テキストの左右にアイコン
<span class="mod-button-0001__after-icon-wrapper">

</span>
</a>

次に 第1章 3節 Font Awesomeを導入しよう で作成しておいたアイコンモジュールを以下の通りspanタグ内に コピー&ペーストします。

1
2
3
4
5
6
7
8
9
10
〜略〜
<a href="#" class="mod-button-0001">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
テキストの左右にアイコン
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>

これで文字の左右にアイコンを配置して、表示位置の調整もできました。
左右どちらかだけにアイコンを配置したいときは、spanタグごと片方を削除するだけで大丈夫です。

ついでにテキストを改行した場合のボタンも以下の通り追記します。

1
2
3
4
5
6
7
8
9
10
〜略〜
<a href="#" class="mod-button-0001">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
このボタンは<br>行数に合わせて高さが変化します
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>

改行されてボタンの高さが変化した場合も、その高さに合わせてアイコンは上下中央に配置されます。

Modifierクラス(10個目)

次は

  • 左右両端にアイコンがあるボタン

を作っていきましょう。

module-list.html に以下のようにaタグ、spanタグ、iタグを追記します。
先ほどまでに記述したaタグは略しています。

1
2
3
4
5
6
7
8
9
10
〜略〜
<a href="#" class="mod-button-0001">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
左右両端にアイコン
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>

以下のようにModifierクラス mod-button-0001--icon-justification を追記します。
今回の例では、BlockのModifierクラスが付与されたときに、BlockクラスのプロパティだけでなくElementクラスのプロパティも変化させます。

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
.mod-button-0001 {
〜略〜
&.mod-button-0001--size-xs {
〜略〜
}
&.mod-button-0001--icon-justification {
display: block;
padding-left: 2.6em;
padding-right: 2.6em;
.mod-button-0001__before-icon-wrapper {
display: flex;
align-items: center;
position: absolute;
top: 0;
height: 100%;
left: 0.8em;
}
.mod-button-0001__after-icon-wrapper {
display: flex;
align-items: center;
position: absolute;
top: 0;
height: 100%;
right: 0.8em;
}
}
.mod-button-0001__before-icon-wrapper {
〜略〜
}
〜略〜
}

以下のとおりModifierクラス mod-button-0001--icon-justification を付与することにします。

1
2
3
4
5
6
7
8
9
10
〜略〜
<a href="#" class="mod-button-0001 mod-button-0001--icon-justification">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
左右両端にアイコン
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>

これで左右両端にアイコンが表示できるようになりました。

この節で追加した行の全容

この節では基本のボタンとModifierクラス10個を作成してきました。
行数が非常に多くなったので、全容を一度確認してみましょう。

public/html/module-list.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
36
37
<a href="#" class="mod-button-0001">基本のボタン / カラーprimary / サイズmd</a>
<a href="#" class="mod-button-0001 mod-button-0001--disabled">状態disabled</a>
<a href="#" class="mod-button-0001 mod-button-0001--inline-block">display inline-block</a>
<a href="#" class="mod-button-0001 mod-button-0001--secondary">カラーsecondary</a>
<a href="#" class="mod-button-0001 mod-button-0001--neutral">カラーneutral</a>
<a href="#" class="mod-button-0001 mod-button-0001--transparent">カラーtransparent</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-xl">サイズxl</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-lg">サイズlg</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-sm">サイズsm</a>
<a href="#" class="mod-button-0001 mod-button-0001--size-xs">サイズxs</a>
<a href="#" class="mod-button-0001">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
テキストの左右にアイコン
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>
<a href="#" class="mod-button-0001">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
このボタンは<br>行数に合わせて高さが変化します
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>
<a href="#" class="mod-button-0001 mod-button-0001--icon-justification">
<span class="mod-button-0001__before-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
左右両端にアイコン
<span class="mod-button-0001__after-icon-wrapper">
<i class="fas fa-cat"></i>
</span>
</a>

src/scss/modules/_mod-button-0001.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
124
125
126
.mod-button-0001 {
display: flex;
justify-content: center;
align-items: center;
position: relative;
border-style: solid;
padding-left: 20px;
padding-right: 20px;
width: 100%;
text-align: center;
text-decoration: none;
box-sizing: border-box;
border-radius: 4px;
cursor: pointer;
// ボタンの高さに関わるプロパティ
border-width: 2px;
padding-top: 8px;
padding-bottom: 8px;
line-height: 24px;
font-size: 16px;
// ボタンの色に関わるプロパティ(focus, hoverも含む)
border-color: #ef940b;
background-color: #ef940b;
color: #ffffff;
&:focus,
&:hover {
border-color: lighten(#ef940b, 8%);
background-color: lighten(#ef940b, 8%);
}
&[disabled],
&.mod-button-0001--disabled {
// !importantは原則として使用禁止ですが、他のModifierクラスと一緒に付与したときでもdisabledの状態は最も優先されるべきなので使用しています。
border-color: #eeeeee !important;
background-color: #eeeeee !important;
color: #bbbbbb !important;
cursor: default !important;
&:focus {
box-shadow: none !important;
}
}
&.mod-button-0001--inline-block {
display: inline-block;
width: auto;
}
&.mod-button-0001--secondary {
border-color: #db0f28;
background-color: #db0f28;
color: #ffffff;
&:focus,
&:hover {
border-color: lighten(#db0f28, 8%);
background-color: lighten(#db0f28, 8%);
}
}
&.mod-button-0001--neutral {
border-color: #888888;
background-color: #888888;
color: #ffffff;
&:focus,
&:hover {
border-color: lighten(#888888, 8%);
background-color: lighten(#888888, 8%);
}
}
&.mod-button-0001--transparent {
border-color: transparent;
background-color: transparent;
color: #0000E9;
&:focus,
&:hover {
opacity: 0.7;
background-color: #eeeeee;
}
}
&.mod-button-0001--size-xl {
padding-top: 16px;
padding-bottom: 16px;
line-height: 36px;
font-size: 24px;
}
&.mod-button-0001--size-lg {
padding-top: 11px;
padding-bottom: 11px;
line-height: 30px;
font-size: 20px;
}
&.mod-button-0001--size-sm {
padding-top: 4px;
padding-bottom: 4px;
line-height: 20px;
font-size: 13px;
}
&.mod-button-0001--size-xs {
padding-top: 0;
padding-bottom: 0;
line-height: 16px;
font-size: 10px;
}
&.mod-button-0001--icon-justification {
display: block;
padding-left: 2.6em;
padding-right: 2.6em;
.mod-button-0001__before-icon-wrapper {
display: flex;
align-items: center;
position: absolute;
top: 0;
height: 100%;
left: 0.8em;
}
.mod-button-0001__after-icon-wrapper {
display: flex;
align-items: center;
position: absolute;
top: 0;
height: 100%;
right: 0.8em;
}
}
.mod-button-0001__before-icon-wrapper {
margin-right: 0.4em;
}
.mod-button-0001__after-icon-wrapper {
margin-left: 0.4em;
}
}

表示確認

public/html/module-list.html をブラウザで開いて確認してみてください。

この節のおわりに

この節では10個のModifierクラスを定義しましたが、特にボタンサイズに関しては最初から5段階も作成せずに、必要になってから作成する程度で良いと思います。

Webサイトのデザインは色々ありますので、拡張しやすいボタンとしてこれで完璧というわけではありませんが、多くのパターンに対応できると思います。
今回作成したパターンから大きく外れるボタンは無理にModifierクラスで対応せずに、新たなボタンモジュールの定義を検討するのが良いと思います。

それに対して、ボタンサイズに関わるプロパティが変更されるだけ、ボタンの色に関わるプロパティが変更されるだけなどのモジュールはModifierを追加して対応するのが望ましいと思います。

続きはこちら

とてもやさしいCSS設計チュートリアルの目次へ戻る