RailsのCSS設計ベストプラクティスはこれだと思う

2023/09/30に公開

はじめに

普段でRailsで開発しているのですが、CSSがほんと難しい😓

  • bootstrapで開発してたけど細かいところは自分で書かないといけない
  • 命名どうしようか?
  • ディレクトリ構成どうしよう、どのファイルに書けばいいの?

など、いろいろ悩むと思います。
なので普段開発してる中で個人的にこれが一番いいなと思う手法を紹介します。

BEMで書く

scssでBEMで書きます。(BEMがわかる方は飛ばしていただいで大丈夫です)

BEMについては【CSS設計】ゼロからわかるBEM超入門を見て欲しいのですが(ありがたいことにたくさんの人に見てもらっているみたいです)、ざっくり説明すると

HTMLを「block」と「element」の2つに分けてCSSを管理する手法です。
elementは「block名 + __(アンダーバー2つ) + element名」と命名します。

<header class="header">
  <p class="header__text">hogehoge</p>
</header>

BEMにも流派?があるみたいでして(modifierとかmixとか)、基本的には以下のルールで書いています。

  • 基本的に1要素1クラス
  • modifierは使わない、使いたくなったらステートをつける
  • bootstrapとの混在は許容する

基本的に1要素1クラス

1つの要素には1つのクラスをつけるようにします。
ただこのルールを破るときは結構あります笑

<header class="header">
  <p class="header__text">hogehoge</p>
  <p class="header__text">hogehoge</p>
</header>

modifierは使わない、使いたくなったらステートをつける

1要素に1クラスだと細かいところに手が届かないので、ステートを許容します。(BEMだとmodifierという方法を使っている流派もあるみたい)

ステートは「ここのテキストだけ赤にしたい!」みたいな時に使います。
命名規則isプレフィックスをつけます。

<header class="header">
  <p class="header__text">hogehoge</p>
  <p class="header__text is-danger">hogehoge</p> // ここだけ赤文字にする
</header>

ただこれも諸刃の剣なので使い過ぎには注意です。

bootstrapとの混在は許容する

最初からデザイナーさんががっつり入ってくれるプロジェクトならいいのですが、そうでないことが多いです。そういう時はbootstrapで作っていきます。

ただ開発の中盤あたりからデザイナーさんが入ったりすると自分でcssを書かないといけません。
なのでbootstrapのクラスと独自クラスの混在は許容します。

<div class="mb-3">
  <p class="hoge-text">hogehoge</p>
  <a href="#" class="btn btn-primary">link</a>
</div>

ただ以下のようなbootstrapのコンポーネントを使いつつ、見た目の変更するようなスタイルの当て方は避けましょう。

<div class="card blog-card">
  <img src="..." class="card-img-top blog-card__img">
  <div class="card-body blog-card__body">
    <h5 class="card-title blog-card__title">Card title</h5>
    <p class="card-text blog-card__text">Card text</p>
    <a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
</div>

これだとbemで書く意味があまりないので、ちょっと手間かもしれませんが自分で頑張って書きましょう。半年後の自分を助けられるのは今の自分ですね。

<div class="blog-card">
  <img src="..." class="blog-card__img">
  <div class="blog-card__body">
    <h5 class="blog-card__title">Card title</h5>
    <p class="btn btn-primary">Card text</p>
  </div>
</div>

ディレクトリ構成

結論から言うと、以下のディレクトリ構成で開発します(参考github)

app/assets/stylesheetsの中
- initializers/
- overrides/
- shared/
- views/
- application.scss

それぞれの役割について

  • initializersは、色、フォント、mixinといった変数や関数を定義する
  • overridesは、bootstrapなどcssフレームワークの上書き
  • sharedは、プロジェクト共通のスタイルを書く
  • viewsはapp/viewsと同じディレクトリ構成にして、ページごとのスタイルを書く

viewsについて説明が足りないと思うので詳しく説明します。
前提として、scssを書くときは1つのviewに対して、1つのblockで対応します。
なのでstylesheets/viewsapp/viewsは似たような構成を取ります。

例えばapp/views配下がこんな感じなら

  • messages
    • index.html.erb
    • show.html.erb
    • new.html.erb
    • edit.html.erb
    • _form.html.erb

stylesheets/views配下にはこんな感じのファイルを作ります。

  • messages-index.scss
  • messages-show.scss
  • messages-new.scss
  • messages-edit.scss
  • messages-form.scss

index.html.erbとmessages-index.scssは以下のようになります。
blockの命名は(ディレクトリ名-ファイル名).scssとします。

index.html.erb
<div class="messages-index">
  <h1 class="messages-index__heading">メッセージ一覧</h1>
  ...
</div>
messages-index.scss
.messages-index {
  padding: 60px 0;
  backgroud: #ccc;
}

.messages-index__heading {
  font-size: 32px;
}

おわりに

かなりシンプルなルールですが、とりあえずこれだけ守っておけばメンテナンスしやすくなるかなと思います。
細かいルールについては書いてませんが、プロジェクトごとにどうしてすればいいのか考えながら、ローカライズしていくのがいいのかなと思います。

他にもこんなディレクトリ構成もあるよ!とかありましたら教えてくれたら嬉しいですー😃

Discussion