前回までの開発で、社員情報一覧画面は何もスタイルを当てていない状態です。
本章では、RailsのCSSの適法方法やレイアウトの仕組み、効率良くコーディングできるBEMとSassを利用したCSS設計を学習しながら、社員情報一覧画面を以下のような見た目に変更していきます。
レイアウトの変更
まずは、RailsでCSSのスタイルを適用する方法を学習します。
RailsはWebアプリケーション開発をすばやく行えるように、さまざまなことがデフォルトで設定されています。CSSもあるディレクトリに配置するだけで、すぐに利用できるよう設定されています。この部分は、レイアウトの仕組みやスタイルシートの読み込みを学習することで理解することができます。
CSSを適用させてみよう
Railsでは、CSSファイルはapp/assets/stylesheets/
ディレクトリ内に配置します。
rails generate
コマンドでコントローラを生成すると、そのコントローラ用のCSSファイルも自動で生成されます。今回はアプリケーションにsass-railsというgemを入れているので、生成されるファイルの拡張子はcss
ではなくscss
(※1)になります。
employeesコントローラを生成した際には、以下のようにapp/assets/stylesheets/
ディレクトリ内にemployees.scss
というファイルが生成されています。
まずはapp/assets/stylesheets/
ディレクトリ内にあるemployees.scss
を開いて、以下のようにタイトルの文字色を#f44336
に指定しましょう。
1
2
3
.title {
color: #f44336;
}
続いて、上記の文字色を社員情報一覧ページのタイトルに適用させてみます。
app/views/employees/
ディレクトリ内のindex.html.erb
を開いて、以下のハイライト箇所のようにh1
要素にclass属性でtitle
を指定しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
<div>
<% if notice.present? %>
<p><%= notice %></p>
<% end %>
<div>
<h1 class='title'>社員情報一覧</h1>
<%= link_to '社員を作成', '/employees/new' %>
</div>
<%= render @employees %>
</div>
最後にWebブラウザで確認してみます。
ターミナルでrails s
コマンドを実行して、Webサーバーを起動しましょう。その後、社員一覧情報の画面にアクセスし、タイトルの文字色が変更されていることを確認しましょう。
このようにスタイルシートを適用させるには、app/assets/stylesheets
ディレクトリ内にCSSファイルなどを配置させます。
employees.scss
って外部ファイルだよね。CSSの適用方法で学んだときは、外部ファイルはlink要素で呼び出してスタイルを適用させる必要があったけど、Railsでは違うのかな?
1
2
3
4
5
6
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="CSSファイルの場所">
</head>
</html>
外部ファイルのスタイル適用は、Railsでもlink要素での呼び出しが必要だよ。index.html.erb
ではスタイルシートを読み込んでないように見えるね。これは「レイアウト」という仕組みが大きく関係するよ。
レイアウトの仕組みを確認しよう
ビューはコントローラのアクションの処理結果を受け取り、Webブラウザでレンダリングさせるための「HTMLファイル」を作成して、コントローラに渡します。
このときビューは、個別のテンプレート(index.html.erb
)によって作成されたHTMLだけを返しているわけではありません。
Railsのデフォルトでは、個別のテンプレートは「アプリケーションで共通のレイアウト」に自動で埋め込まれます。その上で最終的なHTMLが生成されます。つまり、個別のテンプレートとレイアウトを組み合わせたHTMLが生成されます。
共通のレイアウトは、application.html.erb
のことです。
application.html.erb
を開くと、以下の内容が定義されています。
ハイライト箇所の<%= yield %>
に注目してください。デフォルトでは、個別のテンプレートが<%= yield %>
に自動で埋め込まれます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<title>EmployeeManagement</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
employeesコントローラのindexアクションで呼び出されるindex.html.erb
のテンプレートを以下のように定義している場合で考えてみます。
1
2
<h1>個別のテンプレート</h1>
<p>レイアウトに自動で埋め込まれます。</p>
上記のテンプレートで定義したものは、以下のようにレイアウトの<%= yield %>
に自動で埋め込まれた上で、最終的な出力を生成します。
そして、以下のようにコントローラに生成したHTMLファイルを返します。
このようにRailsではデフォルトで個別のテンプレートには、レイアウトが適用されます。
レイアウトをうまく利用することで、重複コードを避けることができます。例えば、ヘッダーやフッターなど他のページでも共通する部分をapplication.html.erb
に記述することで、個別のテンプレートには、ページ固有のコンテンツだけを定義すればよくなります。
<%= yield %>
をコメントアウトして、挙動を確認してみましょう。application.html.erbの<%= yield %>
では、コントローラで実行したアクションと同じ名前のビューのファイル(個別のテンプレート)のHTMLが出力されます。<%= yield %>
をコメントアウトして、個別のテンプレートが出力されないことを確認してみます。
まずは、application.html.erbを以下のハイライト箇所のように編集しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
<title>EmployeeManagement</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%#= yield %>
<h1>レイアウトテンプレート</h1>
<p>アプリケーションで共通のテンプレートです。</p>
</body>
</html>
続いて、Webブラウザで社員情報一覧ページを開きましょう。
社員情報一覧ページを開くと、以下のようにapplication.html.erb
で定義したコンテンツだけが出力されていることが確認できます。
社員情報一覧ページのソースも確認してみましょう。
画面上で右クリックします。以下のようにメニューが表示されるので、「ページのソースを表示」をクリックしましょう。
クリックすると、別タブでページが開かれます。
以下のようにbody
要素内には、employeesコントローラのindexアクションで呼び出されるindex.html.erb
のHTMLは出力されていないことが確認できます。
最後に<%= yield %>
のコメントを外して、application.html.erbに個別のテンプレートの内容が展開されるようにしましょう。
application.html.erbを以下のように元に戻しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<title>EmployeeManagement</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
社員情報一覧ページを開き、以下のようにindex.html.erb
のコンテンツが表示されていることを確認しましょう。
社員情報一覧ページのソースも確認してみましょう。先ほどと同様に画面上で右クリックし、メニューから「ページのソースを表示」を選択します。
ページのソースを表示すると、以下のようにindex.html.erb
のコンテンツを表示することができていますね。
このように個別のテンプレートがレイアウトであるapplication.html.erbの<%= yield %>
に自動で埋め込まれて、HTMLを展開されることがわかりました。
外部CSSの読み込みを確認しよう
レイアウトの仕組みで学習したように個別のテンプレートは、レイアウトに埋め込まれた上でHTMLを生成します。index.html.erb
では、外部CSSファイルを読み込むことなくemployees.scss
のスタイルが適用されているように見えましたね。
実は、レイアウトのhead要素内のstylesheet_link_tag
から読み込まれています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<title>EmployeeManagement</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
stylesheet_link_tag
は、外部スタイルシートを読み込むlinkタグを生成します。
上記の場合は、app/assets/stylesheets/application.css
を読み込むことを示しています。
application.css
を開くと、以下の内容が定義されています。
ハイライト箇所のrequire_tree .
によって、app/assets/stylesheets
ディレクトリ配下にある全てのファイルが読み込まれるように設定されます。
1
2
3
4
5
6
/*
# 中略 #
*
*= require_tree .
*= require_self
*/
次の行にあるrequire_self
はapplication.css
自身も含めるように設定します。
このようにレイアウトから読み込まれるapplication.css
のrequire_tree .
によって、app/assets/stylesheetsディレクトリ配下のスタイルシートが読み込まれます。
CSS設計
次は、CSS設計手法の「BEM」やBEMと親和性の高い「Sass」を学習します。
BEM
BEMとは、Block(かたまり)・Element(要素)・Modifier(修飾)の頭文字をとったものです。厳格なクラス名の命名ルールが特徴的なCSS設計方法の1つです。
1
block__element--modifier
BEMを使うと、HTMLだけでスタイルが予測しやすくなります。また、長期的なメンテナンス性が高くなったり、開発スピードを上げることができます。
以下のようにBlock(かたまり)を構成するのがElement(要素)です。
1
2
3
4
<div class="search"> <!-- Block -->
<input class="search__input"> <!-- Element -->
<input class="search__btn"> <!-- Element -->
</div>
Modifier(修飾)は、BlockとElementのスタイルや状態を修飾します。
1
2
3
4
<div class="content content--yellow"> <!-- Modifier -->
<img class="content__img" src="">
<div class="content__txt">テキスト</div>
</div>
BEMは、クラス名が長いのでCSSの記述が大変になりますが、この点に関しては、後述するSassで解決することができます。
Block(かたまり)
Webページは、ヘッダー、フッダー、ナビゲーション、サイドバー、メインなどのパーツで構成されています。このパーツにあたる部分がBlock(かたまり)になります。
Header blockの中にあるNav blockのように、Blockは他のBlockを含めることができます。
検索フォームで確認してみます。
検索フォームは、Webページを構成するパーツに当たる部分です。この部分はBlockとして捉えることができますね。
検索フォームには、入力欄や送信ボタンの要素がありますが、Blockだけを指定する場合は、以下のように外側のdiv
要素に対して、search
というクラスを付与します。
1
2
3
4
<div class="search"> <!-- Block -->
<input type="search">
<input type="submit">
</div>
それでは、アプリケーションにもBlockでスタイルを指定してみます!
Blockのスタイルを指定してみよう
application.html.erb
のbody要素内に文書の主要な内容を表すmain要素を追加します。そのmain要素に対して、Blockのクラス名を付与します。クラス名は、社員情報を表すemployee
とします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
<title>EmployeeManagement</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<main class="employee">
<%= yield %>
</main>
</body>
</html>
続いて、スタイルを指定します。
1
2
3
4
5
6
7
8
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
}
employees.scss
には、.title
に対して文字色を指定していましたが、そちらは消しておきましょう。以下のように.employee
に対してのスタイル指定だけになります。
employee
クラスにスタイルを指定したら、ブラウザを再読み込みしてください。以下のように再読み込みしても、見た目の変化が少しわかりづらいですね。
デベロッパーツール(開発者用の検証ツール)で確認してみます。
画面上で右クリックし、メニューの中から「検証」をクリックして、デベロッパーツールを起動してください。main要素にemployeeクラスが付与されて、以下のようにスタイルが適用されていることを確認しましょう。
Element(要素)
Elementは、Blockを構成する要素です。ElementはBlockに属しているので、必ずBlockのクラス名を含めます。BlockとElementは、二重アンダースコア(__
)で区切ります。
先ほどの検索フォームで確認してみます。
検索フォームの入力欄と送信ボタンは、「Search block」を構成する要素(Element)になります。
検索フォームをBlockとElementで指定する場合、以下のように記述することができます。
1
2
3
4
<div class="search"> <!-- Block -->
<input type="search" class="search__input"><!-- Element -->
<input type="submit" class="search__btn"><!-- Element -->
</div>
2行目のElementのクラス名は、search__input
です。Blockのsearch
の後に二重アンダースコア(__
)でinput
を指定していますね。
他にもNav blockのElementのように、ElementはBlock内で繰り返し使うこともできます。
Elementのスタイルを指定してみよう
社員情報一覧のElementのスタイルを指定します。
先ほどは<%= yield %>
の外側のmain要素をBlockにして、employee
というクラスを付与しましたね。
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<!-- 中略 -->
</head>
<body>
<main class="employee">
<%= yield %>
</main>
</body>
</html>
レイアウトの仕組みでも学習したように<%= yield %>
には、個別のテンプレートが埋め込まれます。社員情報一覧のElementは、Blockのemployee
に属すのでクラス名はemployee__Element
になります。
1
2
3
4
5
6
7
8
9
10
11
12
<div class="employee__index">
<% if notice.present? %>
<p><%= notice %></p>
<% end %>
<div class="employee__index__body">
<h1 class="employee__index__body-title">社員情報一覧</h1>
<%= link_to '社員を作成', '/employees/new', class: "employee__button" %>
</div>
<%= render @employees %>
</div>
link_to
でクラス名を付与する場合、class: "クラス名"
と指定します。
h1
要素に付与したクラス名はemployee__index__body-title
ですが、body-title
は2つの単語で表しています。このようにBlockやElementを2つ以上の単語で表す場合は「単語-単語」のように、区切り文字にハイフンを使用します。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
}
.employee__index {
width: 100%;
}
.employee__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
.employee__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
.employee__button {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
employees.scssを編集したら、ブラウザを再読み込みしてください。以下のように見た目が少し変わりましたね。
社員情報一覧画面で社員の情報が1人ずつ表示されている箇所は、index.html.erb
で呼び出している部分テンプレートの_employee.html.erb
です。
_employee.html.erb
を開いて、以下のハイライト箇所のように編集しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="employee__list">
<p class="employee__list__item">
<strong class="task__list__item-label">Name:</strong>
<%= employee.name %>
</p>
<p class="employee__list__item">
<strong class="task__list__item-label">Birthday:</strong>
<%= employee.birthday %>
</p>
<p>
<strong>Department:</strong>
<%= employee.department.name %>
</p>
<%= link_to '社員の詳細情報を見る', employee_path(employee), class: "employee__button" %>
<%= link_to '社員を編集する', edit_employee_path(employee), class: "employee__button" %>
<hr>
</div>
続いて、employees.scss
に上記で付与したクラスのスタイルを指定します。
employees.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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
}
.employee__index {
width: 100%;
}
.employee__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
.employee__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
.employee__list__item {
margin: 20px 0;
}
.employee__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
.employee__button {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
Webブラウザを再読み込みすると、以下のように見た目が変わります。
Modifier(修飾)
既存のBlockやElementに対して、一部見た目や状態を変えたい場合にModifier(修飾)を使います。
Modifierは、「Blockに対して使うModifier」と「Elementに対して使うModifier」があります。BlockやElementの後にハイフン2つで区切って定義します。
1
2
3
4
5
<!-- Blockに対して修飾 -->
Block--Modifier
<!-- Elementに対して修飾 -->
Block__Element--Modifier
社員情報一覧画面のボタンは、employee__button
クラスが付与されています。
1
2
3
4
5
6
7
8
9
10
// 中略
.employee__button {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
3つとも同じスタイルだと分かりづらいので、Modifierで一部見た目を変えてみます。
Modifierは、既存のBlockやElementに対して、一部見た目や状態を変えたい場合に使用します。「社員を作成」ボタンの文字色と背景色だけを変更してみます。
まずはindex.html.erb
を開いて、ハイライト箇所のクラス名をemployee__button--blue
に変更しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
<div class="employee__index">
<% if notice.present? %>
<p><%= notice %></p>
<% end %>
<div class="employee__index__body">
<h1 class="employee__index__body-title">社員情報一覧</h1>
<%= link_to '社員を作成', '/employees/new', class: "employee__button--blue" %>
</div>
<%= render @employees %>
</div>
続いてemployees.scss
を開いて、以下のハイライト箇所のように編集しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 中略
.employee__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
.employee__button,
.employee__button--blue {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
.employee__button--blue {
color: white;
background-color: #2563EB;
}
最後にブラウザを再読み込みさせて、以下のように「社員を作成」のボタンだけが一部見た目が変更されていることを確認しましょう。
_employee.html.erb
を開いて、以下のハイライト箇所のように編集しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="employee__list">
<p class="employee__list__item">
<strong class="task__list__item-label">Name:</strong>
<%= employee.name %>
</p>
<p class="employee__list__item">
<strong class="task__list__item-label">Birthday:</strong>
<%= employee.birthday %>
</p>
<p>
<strong>Department:</strong>
<%= employee.department.name %>
</p>
<%= link_to '社員の詳細情報を見る', employee_path(employee), class: "employee__button--gray" %>
<%= link_to '社員を編集する', edit_employee_path(employee), class: "employee__button--gray" %>
<hr>
</div>
employees.scss
を開いて、以下のハイライト箇所を追加しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//中略
.employee__button,
.employee__button--blue,
.employee__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
.employee__button--blue {
color: white;
background-color: #2563EB;
}
.employee__button--gray {
background-color: #F3F4F6;
}
最後にブラウザを再読み込みさせて、以下のように「社員を作成」ではないボタンの見た目が変更されていることを確認しましょう。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
}
.employee__index {
width: 100%;
}
.employee__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
.employee__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
.employee__list__item {
margin: 20px 0;
}
.employee__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
.employee__button,
.employee__button--blue,
.employee__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
.employee__button--blue {
color: white;
background-color: #2563EB;
}
.employee__button--gray {
background-color: #F3F4F6;
}
次はSCSSについて学習します。CSSよりも、コードの記述量が減って保守性が高まるので、人為的なミスを減らすことができます。
SCSS
SCSSは、Sassの記法の1つのです。Sassとは、CSSを拡張したメタ言語(言語を定義する為の言語)のことです。
BEMのデメリットは、クラス名が長くなりCSSで記述する際は冗長になってしまう点でしたが、BEMと親和性の高いSassを利用することで、CSSよりも非常に効率良くコーディングすることができます。
1
2
3
4
5
6
7
8
9
.search {
margin: 30px;
}
.search__input {
font-size: 18px;
}
.search__btn {
color: red;
}
1
2
3
4
5
6
7
8
9
10
11
.search {
margin: 30px;
&__input {
font-size: 18px;
}
&__btn {
color: red;
}
}
Sassには、SASS記法とSCSS記法の2種類ありますが、本章ではSCSS記法について学習します。
SCSS記法
SCSS記法は、スタイルの書き方がCSSと変わらないので、元々CSSを書いていた方はSASS記法よりも入りやすいです。
SCSSはCSSと見た目は似ていますが、波括弧{}
を入れ子にしている箇所が異なります。
1
2
3
4
<ul>
<li>サンプルテキスト</li>
<li>サンプルテキスト</li>
</ul>
上記のHTMLはul
を親要素、li
を小要素とした階層になります。
このような階層構造の場合、CSSでは親子関係なく、以下のハイライト箇所のようにul
の波括弧{}
内にはulのスタイルだけが指定されます。子要素のli
は含めません。
1
2
3
4
5
6
7
8
ul {
margin: 1em;
}
li {
padding-left: 1em;
color: red;
}
しかし、SCSS記法で記述する場合は、ulの波括弧{}の中にliの子要素を含めた入れ子構造(ネスト)にすることで、依存関係を示すことができます。
1
2
3
4
5
6
7
8
ul {
margin: 1em;
li {
padding-left: 1em;
color: red;
}
}
セパレーターの親子関係
BEMでは、Block、Element、Modifierに対してセパレーターを使って区切っていました。この「区切り元」と「区切り先」はそれぞれ「親」と「子」の関係になります。
以下のsearch__input
の場合は、searchが親でinputが子になります。
1
2
3
4
<div class="search">
<input type="search" class="search__input"><!-- searchが区切り元、inputが区切り先 -->
<input type="submit" class="search__btn"><!-- Element -->
</div>
この親子関係をSassのアンパサンド(&
)と呼ばれるものを利用することで、効率的に記述できるようになります。
アンパサンド
SCSS記法では、アンパサンドと呼ばれる&
を使ってネストすると、親セレクタを参照することができます。ネストした&
の後にセパレーターを忘れてしまうと、親子関係とみなされず、CSSが上手くコンパイルされないので注意してください。
以下の場合、&
はsearch
を参照しています。
1
2
3
4
5
6
7
8
9
10
11
.search {
margin: 30px;
&__input { /* &はsearchを参照するので search__inputになる */
font-size: 18px;
}
&__btn { /* &はsearchを参照するので search__btnになる */
color: red;
}
}
上記がCSSにコンパイルされると、以下のようになります。
1
2
3
4
5
6
7
8
9
.search {
margin: 30px;
}
.search__input {
font-size: 18px;
}
.search__btn {
color: red;
}
BEMのデメリットは、クラス名が長くなりCSSで記述する際は冗長になってしまう点でしたが、SCSSのアンパサンド&
を使ってネストすることで、親セレクタを参照し、クラス名を短く記述することができます。
SCSSにすると、毎回.search
と書く必要もなく、記述量が減り、見た目もわかりやすくなるね!
CSSをSCSSに書き換えてみよう
employees.scss
に記述されるCSSをSCSSに書き換えてみましょう。
.employee{ }
の中に.employee__index以下を含めて入れ子構造にしましょう。employees.scss
で指定されるクラス名は、1行目の.employee
以外は、全て.employee
に属すElementやModifierです。Blockの中にネストさせて、&
で参照させることが可能です。
まずは、8行目にある.employee
の閉じ括弧}
を以下のハイライトのように最後に置いて、入れ子構造にしましょう。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
.employee__index {
width: 100%;
}
.employee__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
.employee__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
.employee__list__item {
margin: 20px 0;
}
.employee__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
.employee__button,
.employee__button--blue,
.employee__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
.employee__button--blue {
color: white;
background-color: #2563EB;
}
.employee__button--gray {
background-color: #F3F4F6;
}
}
上記のように.employee__index
以下は、インデントを「半角スペース2つ分」入れます。インデントは、エディターの右下にある設定で調整することができます。
以下のように「Spaces: 2」であれば、特に設定は必要ありません。
上記以外の方は右下の設定箇所をクリックして、以下のように「Spaces: 2」になるように設定しておきましょう。
あとは動画のように最終行の閉じ括弧を含めない.employee__index
以下を全て選択し、tabキーを押して「半角スペース2つ分」のインデントを入れるだけです。
&
に置き換えましょう。.employee{}
の中に含むクラス名の.employee
の部分を&
に置き換えましょう。
.employee__index
であれば&__index
、.employee__index__body
であれば&__index__body
のように置き換えます。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
&__index {
width: 100%;
}
&__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
&__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
&__list__item {
margin: 20px 0;
}
&__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
&__button,
&__button--blue,
&__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
&__button--blue {
color: white;
background-color: #2563EB;
}
&__button--gray {
background-color: #F3F4F6;
}
}
まずは、以下のハイライト箇所に注目してください。
__index
という部分が重複していますね。&__index { }
の中に&__index__body { }
と&__index__body-title { }
を入れてネストさせましょう。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
&__index {
width: 100%;
}
&__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
&__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
// 中略
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.employee {
display: flex;
// 中略
&__index {
width: 100%;
&__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
&__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
// 中略
}
上記の変更によって&__index__body { }
と&__index__body-title { }
が同じ階層になりましたが、2つのクラス名は__index__body
の箇所が重複しているので、さらにネストできそうです。
以下のように&__index__body { }
の中に&__index__body-title { }
を入れましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.employee {
display: flex;
// 中略
&__index {
width: 100%;
&__index__body {
display: flex;
justify-content: space-between;
align-items: center;
&__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
}
// 中略
}
そして、&__list__item{ }
と&__list__item-label{ }
も__list__item
が重複していますね。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.employee {
display: flex;
// 中略
&__list__item {
margin: 20px 0;
}
&__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
// 中略
}
以下のように&__list__item{ }
の中に&__list__item-label{ }
を入れて、ネストさせましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.employee {
display: flex;
// 中略
&__list__item {
margin: 20px 0;
&__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
}
// 中略
}
以下のemployees.scss
のように、重複箇所が全てネストされていることを確認しましょう。&__button
以降は、特に変更していません。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
&__index {
width: 100%;
&__index__body {
display: flex;
justify-content: space-between;
align-items: center;
&__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
}
&__list__item {
margin: 20px 0;
&__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
}
&__button,
&__button--blue,
&__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
&__button--blue {
color: white;
background-color: #2563EB;
}
&__button--gray {
background-color: #F3F4F6;
}
}
まずは、&__index { }
の中に含まれるクラス名を変更していきます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.employee {
//中略
&__index {
width: 100%;
&__index__body {
display: flex;
justify-content: space-between;
align-items: center;
&__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
}
//中略
}
上記のハイライト箇所を以下のように変更しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.employee {
//中略
&__index {
width: 100%;
&__body { /* &は__indexを参照するので__index__bodyになる */
display: flex;
justify-content: space-between;
align-items: center;
&-title { /* &は__index__bodyを参照するので__index__body-titleになる */
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
}
//中略
}
続いて、&__list__item { }
の中に含まれるクラス名を変更していきます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.employee {
display: flex;
// 中略
&__list__item {
margin: 20px 0;
&__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
}
// 中略
}
上記のハイライト箇所を以下のように変更しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.employee {
display: flex;
// 中略
&__list__item {
margin: 20px 0;
&-label { /* &は__list__itemを参照するので__list__item-labelになる */
display: block;
font-weight: 700;
margin-bottom: 4px;
}
}
// 中略
}
employees.scssを編集したら、ブラウザを再読み込みしてください。CSSからSCSSに書き換えても、社員情報一覧画面のスタイルが正常に適用されていることを確認しましょう。
CSSからSCSSに書き換える前は、以下のようにBEMのクラス名が冗長で重複するクラス名の部分を繰り返し記述する必要がありましたね。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
}
.employee__index {
width: 100%;
}
.employee__index__body {
display: flex;
justify-content: space-between;
align-items: center;
}
.employee__index__body-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
.employee__list__item {
margin: 20px 0;
}
.employee__list__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
.employee__button,
.employee__button--blue,
.employee__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
.employee__button--blue {
color: white;
background-color: #2563EB;
}
.employee__button--gray {
background-color: #F3F4F6;
}
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
&__index {
width: 100%;
&__body {
display: flex;
justify-content: space-between;
align-items: center;
&-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
}
&__list__item {
margin: 20px 0;
&-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
}
&__button,
&__button--blue,
&__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
&__button--blue {
color: white;
background-color: #2563EB;
}
&__button--gray {
background-color: #F3F4F6;
}
}
このようにBEMと親和性の高いSass(SCSS)を利用することで、CSSよりも非常に効率良くコーディングすることができます。
SCSSの他の機能
SCSSでは、他にも変数や演算、関数、ディレクティブを使用することができます。
本章では、SCSSの代表的な2つのディレクティブである「@extendディレクティブ」と「@importディレクティブ」について学習します。
- @extendディレクティブ - 定義済みのスタイルを継承する
- @importディレクティブ - 外部のスタイルシートを読み込む
ディレクティブとは@名前
で指定することのできる命令のことです。
@extendディレクティブ
@extendディレクティブを利用することで、定義済みのスタイルを他のクラスに継承させることができます。
以下のように.sample
クラスのスタイル定義の中で@extend ディレクティブを使用すると、指定したセレクタに設定されているスタイル定義を、.sample
クラスに継承させることができます。セレクタ名には、クラス名などを引用符で囲まずに指定します。
1
2
3
.sample {
@extend <セレクタ名>;
}
例えば、.base-content
のスタイルを.content
に継承させる場合は、以下のように記述します。
1
2
3
4
5
6
7
8
9
10
11
.base-content {
border: 1px solid grey;
font-size: 20px;
padding: 20px;
width: 200px;
}
.content {
@extend .base-content; /* .base-contentを継承する */
border-color: red; /* 一部スタイルを変更 */
}
上記がCSSにコンパイルされると、以下のように同じプロパティを持つスタイルはまとめられます。そして.content
に定義したborder-color: red
は個別に出力されます。
1
2
3
4
5
6
7
8
9
10
11
.base-content, .content { /*同じスタイルはまとめられる*/
border: 1px solid grey;
font-size: 20px;
padding: 20px;
width: 200px;
}
/*独自で定義したスタイルは個別に記述される*/
.content {
border-color: red;
}
@extendディレクティブを利用することで、同じプロパティをまとめてくれるので、余計な重複コードを出力してしまうという心配がなくなります。またベースのスタイルを継承した上で一部スタイルを変更させることができます。
&__button--blue{ }
と&__button--gray{ }
の中に@extendディレクティブを利用して、&__button { }
のスタイルを継承できるようにしていきます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.employee {
// 中略
&__button,
&__button--blue,
&__button--gray {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
&__button--blue {
color: white;
background-color: #2563EB;
}
&__button--gray {
background-color: #F3F4F6;
}
}
上記を以下のように変更しましょう。@extendディレクティブで指定するセレクタは、&__button
のコンパイル後のクラス名の.employee__button
です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.employee {
// 中略
&__button { /* コンパイル後のクラス名は.employee__buttonになる */
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
}
&__button--blue {
@extend .employee__button; /* .employee__buttonを継承する */
color: white;
background-color: #2563EB;
}
&__button--gray {
@extend .employee__button; /* .employee__buttonを継承する */
background-color: #F3F4F6;
}
}
@extendディレクティブを利用して&__button { }
のスタイルを&__button--blue
と&__button--gray
に継承させることができました。上記のようにコードを変更したことで、クラス名が重複する部分(__button
)を&
で記述できるようになります。
&
を利用して、クラス名が重複する部分をなくしましょう。&__button { }
の中に&__button--blue { }
と&__button--gray { }
を入れて、以下のように&
でクラス名を&--blue
、&--gray
に変更しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.employee {
// 中略
&__button {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
&--blue {
@extend .employee__button;
color: white;
background-color: #2563EB;
}
&--gray {
@extend .employee__button;
background-color: #F3F4F6;
}
}
}
アンパサンド&
を使ってネストすると、親セレクタを参照し、クラス名が重複する部分をスッキリと記述することができます。
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
.employee {
display: flex;
margin-left: auto;
margin-right: auto;
margin-top: 112px;
max-width: 90%;
padding: 0 20px;
&__index {
width: 100%;
&__body {
display: flex;
justify-content: space-between;
align-items: center;
&-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
}
}
&__list__item {
margin: 20px 0;
&-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
}
&__button {
display: inline-block;
padding: 12px 20px;
font-weight: 700;
border-radius: 8px;
text-decoration: inherit;
color: #000;
font-size: 16px;
&--blue {
@extend .employee__button;
color: white;
background-color: #2563EB;
}
&--gray {
@extend .employee__button;
background-color: #F3F4F6;
}
}
}
@importディレクティブ
@importディレクティブは、外部スタイルシート(.scssの拡張子のファイル)をインポートする機能です。CSSにコンパイルされると、1つのファイルとして書き出されます。
1
2
3
4
5
/* ファイルをインポートする */
@import "ファイル名.scss";
/* 拡張子は省略可能なので、下記でも良い*/
@import "ファイル名";
application.cssではrequire_tree .
によって、app/assets/stylesheets
ディレクトリ配下にある全てのファイルが読み込まれるように設定されていましたね。
1
2
3
4
5
6
/*
# 中略 #
*
*= require_tree .
*= require_self
*/
require_tree .
を利用せずに、@importディレクティブでapplication.cssにemployees.scss
をインポートしてみます。以下のように編集してください。
1
@import './employees';
以下のようにapplication.css
に元々記述されていたコードは、全て削除して@import './employees';
を追加しましょう。
application.cssを編集したら、ブラウザを再読み込みしてください。以下のように社員情報一覧画面は、employees.scss
のスタイルが適用されていないことが確認できます。
application.cssでemployees.scss
が正常にインポートされていません。どこが間違えているか分かりますか。
1
@import './employees';
@importディレクティブは、CSSではなくSass(SCSS)の機能です。そのため、ファイルの拡張子をapplication.css
からapplication.scss
に変更する必要があります。
以下のようにファイル名を変更しましょう。
ファイル名の拡張子を.scss
に変更したら、再度ブラウザを再読み込みして、以下のように社員情報一覧画面にスタイルが適用されていることを確認しましょう。
ここまでの学習したBEMとSCSSの知識を活かして、社員情報一覧画面以外のページもスタイル定義していきましょう。
詳細画面の見た目を変えてみよう
詳細画面の見た目をBEMとSCSSで定義していきます。
まずは、詳細画面にアクセスしてみましょう。詳細画面にアクセスすると、以下の緑枠で囲う部分はすでに見た目が整っていますね。
これはindex.html.erb
とshow.html.erb
が同じ部分テンプレート(_employee.html.erb
)を呼び出しているからです。
社員情報一覧画面の見た目を作成する際に、_employee.html.erb
には以下のようにBEMでクラスを指定しましたね。そのクラスに対しても、スタイルは定義済みです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="employee__list">
<p class="employee__list__item">
<strong class="task__list__item-label">Name:</strong>
<%= employee.name %>
</p>
<p class="employee__list__item">
<strong class="task__list__item-label">Birthday:</strong>
<%= employee.birthday %>
</p>
<p>
<strong>Department:</strong>
<%= employee.department.name %>
</p>
<%= link_to '社員の詳細情報を見る', employee_path(employee), class: "employee__button" %>
<%= link_to '社員を編集する', edit_employee_path(employee), class: "employee__button" %>
<hr>
</div>
部分テンプレート以外のshow.html.erb
の箇所をBEMで指定していきます。
以下のハイライト箇所のように、BEMでクラス名を指定しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="employee__show">
<div class="employee__show__body">
<% if notice.present? %>
<p><%= notice %></p>
<% end %>
<%= render @employee %>
<%= link_to '社員一覧画面に戻る', '/employees', class: "employee__button--gray" %>
<div>
<%= button_to '社員を削除する', employee_path(@employee), method: :delete, class: "employee__button--gray" %>
</div>
</div>
</div>
link_toの箇所に指定したクラス名のスタイルは、すでに社員情報一覧画面を作成した際に定義されているので、クラスを付与しただけでスタイルが適用されます。
Webブラウザを再読み込みすると、以下のように見た目が変わります。
以下のCSSをSCSSに書き換えて、employees.scss
でスタイルを定義してみましょう。SCSSの書き換えは、CSSをSCSSに書き換えを参考にしてください。
1
2
3
4
5
6
7
8
9
10
11
.employee__show {
display: flex;
width: 66%;
margin-left: auto;
margin-right: auto;
}
.employee__show__body {
margin-left: auto;
margin-right: auto;
}
上記のCSSをSCSSに書き換えて、employees.scss
で定義することができれば、詳細画面は以下のような見た目になります。
employees.scss
を編集したら、以下の「解答をみる」をクリックして、SCSSの書き方があっているかを確認しましょう。
-
答え
app/assets/stylesheets/employees.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
.employee { //中略 &__index { width: 100%; &__body { display: flex; justify-content: space-between; align-items: center; &-title { font-weight: 700; font-size: 36px; line-height: 40px; margin: 0; } } }
&__show {display: flex;width: 66%;margin-left: auto;margin-right: auto;&__body {margin-left: auto;margin-right: auto;}}&__list__item { margin: 20px 0; &-label { display: block; font-weight: 700; margin-bottom: 4px; } } //中略 }
以下のように1箇所だけスタイルが異なりますね。これは、ユーザーエージェントスタイルシートの影響です。style属性を利用して、ボタンを横並びにしてみます。
Railsでは外部スタイルシートを呼び出す以外にも、CSSの適用方法で学習したようなstyle要素やstyle属性を利用することができます。style属性では、要素内にstyle属性を追加して単一の要素のみスタイルを適用できます。
以下のハイライト箇所のようにshow.html.erb
のdiv要素にstyle属性を追加しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="employee__show">
<div class="employee__show__body">
<% if notice.present? %>
<p><%= notice %></p>
<% end %>
<%= render @employee %>
<%= link_to '社員一覧画面に戻る', '/employees', class: "employee__button--gray" %>
<div style="display: inline-block; margin-left: 2px;">
<%= button_to '社員を削除する', employee_path(@employee), method: :delete, class: "employee__button--gray" %>
</div>
</div>
</div>
Webブラウザを再読み込みすると、以下のように見た目が変わります。
新規投稿画面の見た目を変えてみよう
新規投稿画面の見た目をBEMとSCSSで定義していきます。
まずは、新規投稿画面にアクセスしてみましょう。以下のようにユーザーエージェントスタイルシートだけが適用されている状態です。
1
2
3
4
5
<div class="employee__new">
<h1 class="employee__new-title">社員を新規作成</h1>
<%= render "form", employee: @employee %>
</div>
new.html.erb
では、部分テンプレートの_form.html.erb
を呼び出しています。
以下のハイライト箇所のように_form.html.erb
にBEMでクラスを付与しましょう。
※ form.collection_select
にはクラス名だけではなく、{prompt: "選択してください"}
も追加しましょう。
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
<%= form_with(model: @employee, class: "employee__new__form") do |form| %>
<% if @employee.errors.any? %>
<div>
<ul>
<% @employee.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="employee__new__form__item">
<%= form.label :name %>
<%= form.text_field :name, class: "employee__new__form__item-input" %>
</div>
<div class="employee__new__form__item">
<%= form.label :birthday %>
<%= form.date_field :birthday, class: "employee__new__form__item-input" %>
</div>
<div class="employee__new__form__item">
<%= form.label :department_id, "Department:" %>
<%= form.collection_select :department_id, @departments, :id, :name, {prompt: "選択してください"}, {class: "employee__new__form__item-input"} %><br>
</div>
<%= form.submit class: "employee__button--blue" %>
<% if action_name == "new" %>
<%= link_to '社員一覧画面に戻る', employees_path, class: "employee__button--gray" %>
<% elsif action_name == "edit" %>
<%= link_to '社員の詳細情報を見る', employee_path(@employee), class: "employee__button--gray" %>
<% end %>
<% end %>
Webブラウザを再読み込みすると、すでにemployees.scss
で定義されているボタンのスタイルが適用されます。
以下のCSSをSCSSに書き換えて、employees.scss
でスタイルを定義してみましょう。SCSSの書き換えは、CSSを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
.employee__new {
margin-left: auto;
margin-right: auto;
width: 66%;
}
.employee__new-title {
font-weight: 700;
font-size: 36px;
line-height: 40px;
margin: 0;
}
.employee__new__form__item {
margin: 20px 0;
}
.employee__new__form__item-label {
display: block;
font-weight: 700;
margin-bottom: 4px;
}
.employee__new__form__item-input {
display: block;
margin-top: 8px;
padding: 8px 12px;
width: 100%;
border-radius: 4px;
border: 1px solid #E5E7EB;
font-size: 16px;
line-height: 24px;
color: #575F74;
}
上記のCSSをSCSSに書き換えて、employees.scssで定義することができれば、新規作成画面は以下のような見た目になります。
employees.scssを編集したら、以下の「解答をみる」をクリックして、SCSSの書き方があっているかを確認しましょう。
-
答え
app/assets/stylesheets/employees.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
.employee { //中略 &__index { width: 100%; //中略 }
&__new {margin-left: auto;margin-right: auto;width: 66%;&-title {font-weight: 700;font-size: 36px;line-height: 40px;margin: 0;}&__form__item {margin: 20px 0;&-label {display: block;font-weight: 700;margin-bottom: 4px;}&-input {display: block;margin-top: 8px;padding: 8px 12px;width: 100%;border-radius: 4px;border: 1px solid #E5E7EB;font-size: 16px;line-height: 24px;color: #575F74;}}}&__show { // 中略
この記事のまとめ
- application.html.erbは、アプリケーションで共通のレイアウト
<%= yield %>
によって、個別のテンプレートが自動で埋め込まれて、最終な出力を生成する
この記事で学んだことをTwitterに投稿して、アウトプットしよう!
Twitterの投稿画面に遷移します