2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

テーマ切り替え可能なCSS設計について考えてみた

Last updated at Posted at 2018-03-12

最近、1プロジェクトの中に複数サービスがあり、サービスによってコンポーネントの色やサイズを調整したいという要望がありました。
このとき、CSS設計をどのように行うべきかを考えた結果のまとめになります。

注意

他によい方法があるかもしれませんので、検討時に選択肢の1つとして考えていただければと思います。
また、よりよい方法を知っているよという場合、是非その方法を教えていただけるとうれしいです。

実装について

わかりやすいのでボタンで考えてみます。

サービスのテーマカラーのボタンを設置したいとします。
このとき、btn--serviceをクラスに指定すれば、指定した色のボタンが実装できるとします。
そうなると下記のようなコードになります。

.btn {
  ...

  &--service {
    background-color: #f00;
  }
}
<button class="btn btn--service">テキスト</button>

よく見慣れた形です。

複数サービスの場合

複数のサービスがあった場合、どうなるでしょうか。
すぐに思いつくのが、それぞれ別のクラス(modifire)を作成する方法でしょうか?

.btn {
  ...

  &--serviceA {
    background-color: #f00;
  }
  &--serviceB {
    background-color: #0f0;
  }
}
<button class="btn btn--serviceA">テキスト</button>
<button class="btn btn--serviceB">テキスト</button>

このような形になるかと思います。
(※本来であれば、サイズ用のクラスなどがあるかと思いますが、ここでは省略しています)

では、次は問い合わせボタンも定義していくとします。
その際、問い合わせボタンの色は、サービスごとで違う色にしたいとします。
先ほどと同じように対応するのであれば、下記のようになるかと思います。

.btn {
  ...

  &--inquiryServiceA {
    background-color: #f00;
  }
  &--inquiryServiceB {
    background-color: #0f0;
  }
}
<button class="btn btn--inquiryServiceA">テキスト</button>
<button class="btn btn--inquiryServiceB">テキスト</button>

これでも問題はないのですが、そのサービスの中で使用するのに、わざわざそのサービス名がついたクラス名をつけるのって面倒ではないでしょうか?

scssを別にする

では問題を解決するために、scssを別にしてみます。

serviceA/_btn.scss

.btn {
  ...

  &--inquiry {
    background-color: #f00;
  }
}

serviceB/_btn.scss

.btn {
  ...

  &--inquiry {
    background-color: #0f0;
  }
}

こうなれば、これをそれぞれのサービスの共通scssでimportすればいいだけです。

でも、ボタンコンポーネントがサービスごとに散ってしまいました。
やはりボタンはボタンで固まっていて欲しくないでしょうか?

mixinという方法もありだとは思いますが、毎回作成するのも少し面倒なので、別の方法を考えてみました。

そこで、提案するのが、色などを管理するtheme.scssをサービスごとに作成し、ここで管理するという方法です。

対応方法

_btn.scss

.btn {
  ...

  &--inquiry {
    background-color: $inquiry_color;
  }
}

background-colorの指定を変数にしました。
ここで宣言した変数を、各サービスで上書きしていくことになります。

base/_theme.scss

// 指定がなかった場合のデフォルトを指定しておく
$inquiry_color: #fff !default

デフォルトとなる色などを指定しておきます。
今は必要ないかもしれないですが、今後上書きの必要がない場合に使用していきます。

serviceA/_theme.scss

$inquiry_color: #f00;

serviceA用の色を指定します。

serviceB/_theme.scss

$inquiry_color: #0f0;

serviceB用の色を指定します。

serviceB/layout.scss

@import "base/theme";
@import "serviceA/theme";
@import "btn";

importの順番が重要になります。
まず、デフォルトのテーマを読みこんで、その後にサービスAのテーマを読み込んでいます。
その結果、base/themeで指定されたものをベースにし、その後serviceA/themeで指定されたもので上書きすることになります。

※パスは必要に応じて修正してください

serviceB/layout.scss

@import "base/theme";
@import "serviceB/theme";
@import "btn";

こちらに関してはserviceAと同様になります。

まとめ

以上が対応方法になります。

このようにサービスごとに変化させたい値を変数で切り出し、読み込み時に上書きしていくことで、コンポーネントをまとめたままでも、サービスごとのModifire(パターン違いのクラス)を定義する必要がなくなります。

もちろん、普通にModifireとして定義した方がいい場合もあるので、常にこの方法の方がいいということはないと思います。
状況に応じて、このようなCSS設計も選択肢の1つに加えていただければと思います。

2
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?