はじめに
Webサイトを作る上でCSSは避けては通れませんが、CSSをわかりやすく書くことは難しく、作っていくうちに複雑になりすぎることがよくあります。
また、JavaScriptを使用して動的にページの見た目を変えることもよくあり、JavaScriptとも連携しやすいように書く必要があります。
この2つの問題はそれぞれSASS(SCSS)とCSSカスタムプロパティで解決できるので、本記事では具体例としてダークモードの実装方法について解説したいと思います。
なお、本記事ではSASSはSCSSの文法で記述します。
簡単な例
まずはSASSの変数機能とCSSカスタムプロパティを使ってダークモードを実装します。
// 色をSCSS変数として定義する
$border-color-light: #000000;
$border-color-dark: #ffffff;
$text-color-light: #000000;
$text-color-dark: #ffffff;
$background-color-light: #ffffff;
$background-color-dark: #000000;
// テーマごとに変数を設定
.light-theme {
--border-color: $border-color-light;
--text-color: $text-color-light;
--background-color: $background-color-light;
}
.dark-theme {
--border-color: $border-color-dark;
--text-color: $text-color-dark;
--background-color: $background-color-dark;
}
body {
background-color: var(--background-color);
button {
// CSSカスタムプロパティの値を使うように設定
border-color: var(--border-color);
color: var(--text-color);
background-color: var(--background-color);
}
}
これはコンパイルすると、以下のようなCSSになり、light-theme
、dark-theme
クラスが定義され、それぞれ同じCSSカスタムプロパティが定義されています。
.light-theme {
--border-color: #000000;
--text-color: #000000;
--background-color: #ffffff;
}
.dark-theme {
--border-color: #ffffff;
--text-color: #ffffff;
--background-color: #000000;
}
body {
background-color: var(--background-color);
}
body button {
border-color: var(--border-color);
color: var(--text-color);
background-color: var(--background-color);
}
生成されたlight-theme
とdark-theme
クラスをJavaScriptで切り替えることで、同じ名前のCSSカスタムプロパティでもテーマごとに値が切り替わり、ダークモードの実装が実現できます。
See the Pen spectrum-web-analyzer by FOURIER Inc. (@fourier-inc) on CodePen.
値の生成
上記の例でも目的は達成できていますが、テーマごとにSASS変数を定義し、CSSカスタムプロパティとして定義する必要があるため、記述するのが大変です。 そのため、SASSの機能を活用して、その手間を減らします。
$schemes: light, dark;
$scheme-colors: (
border: (#000000, #ffffff), //1番目がライトテーマ、2番目がダークテーマ
text: (#000000, #ffffff),
background: (#ffffff, #000000)
);
@each $scheme in $schemes {
// テーマごとのクラスを作成
.#{$scheme}-theme {
// 色を定義
@each $name, $colors in $scheme-colors {
$color: nth($colors, index($schemes, $scheme));
--#{$name}-color: #{$color};
}
}
}
main {
button {
border-color: var(--border-color);
color: var(--text-color);
background-color: var(--background-color);
}
}
少しコードが複雑になりましたが、生成されるCSSは同じです。このコードでは複数のSASSの機能を使用しています。
1つ目は$scheme-colors
のマップ変数で、border
やtext
の名前をキーとして、色を配列にして1番目にライトテーマ用、2番目にダークテーマ用の色をいれています。 こうすることで、テーマごとに同じ名前の変数を定義する必要がなくなり、コード量が減って楽になります。
2つ目は@each
を使って$scheme
や$scheme-colors
の変数を順番に取り出している点で、この部分でCSSカスタムプロパティを同じように一気に定義しています。
このように書くことで、新しく色を追加したい場合でも最小限の手間で追加することが可能となりました。
RGB値の変数を定義
ここまででテーマごとの色の定義方法について解説しましたが、これらの値には透過値が入っておらず、後から透過値を組み合わせることができない問題があります。
そのため、透過値と組み合わせられるようにRGB値を定義します。
$schemes: light, dark;
$scheme-colors: (
border: (#000000, #ffffff), //1番目がライトテーマ、2番目がダークテーマ
text: (#000000, #ffffff),
background: (#ffffff, #000000)
);
@each $scheme in $schemes {
// テーマごとのクラスを作成
.#{$scheme}-theme {
// 色を定義
@each $name, $colors in $scheme-colors {
$color: nth($colors, index($schemes, $scheme));
$r: red($color);
$g: green($color);
$b: blue($color);
--#{$name}-color: #{$color};
--#{$name}-r-color: #{$r};
--#{$name}-g-color: #{$g};
--#{$name}-b-color: #{$b};
--#{$name}-rgb-color: #{$r, $g, $b};
}
}
}
main {
button {
border-color: var(--border-color);
color: var(--text-color);
background-color: var(--background-color);
}
}
これをコンパイルすると、以下のようになります。
.light-theme {
--border-color: #000000;
--border-r-color: 0;
--border-g-color: 0;
--border-b-color: 0;
--border-rgb-color: 0, 0, 0;
--text-color: #000000;
--text-r-color: 0;
--text-g-color: 0;
--text-b-color: 0;
--text-rgb-color: 0, 0, 0;
--background-color: #ffffff;
--background-r-color: 255;
--background-g-color: 255;
--background-b-color: 255;
--background-rgb-color: 255, 255, 255;
}
.dark-theme {
--border-color: #ffffff;
--border-r-color: 255;
--border-g-color: 255;
--border-b-color: 255;
--border-rgb-color: 255, 255, 255;
--text-color: #ffffff;
--text-r-color: 255;
--text-g-color: 255;
--text-b-color: 255;
--text-rgb-color: 255, 255, 255;
--background-color: #000000;
--background-r-color: 0;
--background-g-color: 0;
--background-b-color: 0;
--background-rgb-color: 0, 0, 0;
}
main button {
border-color: var(--border-color);
color: var(--text-color);
background-color: var(--background-color);
}
CSSカスタムプロパティが大量に定義されましたが、これで各色のRGB値が使用できるようになりました。
特徴的なのが—#{name}-rgb-color
変数で、値の中にカンマが入っています。このカンマ入りのCSSカスタムプロパティは、以下のようにCSSのrgba
と組み合わせて使用することで透過値を設定できます。
div {
background: rgba(var(--background-rgb-color), .1);
}
まとめ
本記事ではSASSとCSSカスタムプロパティを連携してダークテーマの実装をしました。 SASSを使うことで素のCSSよりも簡潔に書くことができ、CSSカスタムプロパティで動的な要素も比較的簡単に実装できました。
この記事で紹介した機能は様々な形で応用できるので、読者の皆様の参考になれば幸いです。
新しいメンバーを募集しています
Hirayama / Engineer
1997年生まれ、南伊豆出身。学生時代にC#で画像処理アプリケーションを作ったりしていました。業務では主にLaravelを使用してサーバーサイドのプログラミングをしています。趣味はドライブとシミュレーションゲーム。