はじめに
最近のWebアプリケーションでは、ユーザーの好みに応じてダークモードとライトモードを切り替える機能が一般的になってきています。この記事では、CSSのカスタムプロパティ(CSS変数)を使用して、シンプルかつ効果的なテーマ切り替え機能を実装する方法をご紹介します。
成果物のイメージ
ボタンによりテーマ切り替える。
実装のポイント
- CSS変数を使用してテーマカラーを管理
- レスポンシブデザインへの対応
- アニメーションによる視覚的な演出
- JavaScriptによる動的なテーマ切り替え
実装手順
1. プロジェクトの構成
まず、以下のような構成でファイルを作成します:
output/
├── dark-theme.css
├── light-theme.css
├── responsive.css
├── animation.css
└── index.html
2. テーマごとのCSS定義
ダークテーマ(dark-theme.css)
:root {
--background-color: #121212;
--text-color: #ffffff;
--primary-color: #BB86FC;
--secondary-color: #03DAC6;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
.card {
background-color: #1E1E1E;
border: 1px solid #333333;
}
ライトテーマ(light-theme.css)
:root {
--background-color: #ffffff;
--text-color: #333333;
--primary-color: #6200EE;
--secondary-color: #03DAC6;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
.card {
background-color: #f5f5f5;
border: 1px solid #e0e0e0;
}
3. レスポンシブデザインの実装(responsive.css)
html {
font-size: 16px;
}
h1 {
font-size: 2.5em;
}
@media (max-width: 768px) {
html {
font-size: 14px;
}
h1 {
font-size: 2em;
}
}
4. アニメーションの追加(animation.css)
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in {
animation: fadeIn 1.5s ease-in-out;
}
5. HTMLの実装
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSSテーマ確認</title>
<link id="theme-link" rel="stylesheet" href="output/dark-theme.css">
<link rel="stylesheet" href="output/responsive.css">
<link rel="stylesheet" href="output/animation.css">
<style>
.switch-buttons {
margin: 20px;
}
button {
margin: 5px;
padding: 10px 20px;
cursor: pointer;
}
.card {
margin: 20px auto;
padding: 30px;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="switch-buttons">
<button onclick="switchTheme('dark')">ダークテーマ</button>
<button onclick="switchTheme('light')">ライトテーマ</button>
</div>
<h1 class="fade-in">CSSテーマ確認ページ</h1>
<div class="card fade-in">
カードデザインのサンプルです。
</div>
<script>
function switchTheme(theme) {
const link = document.getElementById('theme-link');
if (theme === 'dark') {
link.href = 'output/dark-theme.css';
} else {
link.href = 'output/light-theme.css';
}
}
</script>
</body>
</html>
6. Pythonによるファイル生成
以下のPythonスクリプトを使用して、必要なファイルを自動生成します:
import os
os.makedirs('output', exist_ok=True)
# CSSファイルの内容
dark_css = '''
:root {
--background-color: #121212;
--text-color: #ffffff;
--primary-color: #BB86FC;
--secondary-color: #03DAC6;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
.card {
background-color: #1E1E1E;
border: 1px solid #333333;
}
'''
light_css = '''
:root {
--background-color: #ffffff;
--text-color: #333333;
--primary-color: #6200EE;
--secondary-color: #03DAC6;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
.card {
background-color: #f5f5f5;
border: 1px solid #e0e0e0;
}
'''
responsive_css = '''
html {
font-size: 16px;
}
h1 {
font-size: 2.5em;
}
@media (max-width: 768px) {
html {
font-size: 14px;
}
h1 {
font-size: 2em;
}
}
'''
animation_css = '''
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in {
animation: fadeIn 1.5s ease-in-out;
}
'''
# HTMLの内容
html_content = '''
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSSテーマ確認</title>
<link id="theme-link" rel="stylesheet" href="output/dark-theme.css">
<link rel="stylesheet" href="output/responsive.css">
<link rel="stylesheet" href="output/animation.css">
<style>
.switch-buttons {
margin: 20px;
}
button {
margin: 5px;
padding: 10px 20px;
cursor: pointer;
}
.card {
margin: 20px auto;
padding: 30px;
width: 80%;
max-width: 500px;
text-align: center;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="switch-buttons">
<button onclick="switchTheme('dark')">ダークテーマ</button>
<button onclick="switchTheme('light')">ライトテーマ</button>
</div>
<h1 class="fade-in">CSSテーマ確認ページ</h1>
<div class="card fade-in">
カードデザインのサンプルです。
</div>
<script>
function switchTheme(theme) {
const link = document.getElementById('theme-link');
if (theme === 'dark') {
link.href = 'output/dark-theme.css';
} else {
link.href = 'output/light-theme.css';
}
}
</script>
</body>
</html>
'''
# ファイルを出力
with open('output/dark-theme.css', 'w') as f:
f.write(dark_css)
with open('output/light-theme.css', 'w') as f:
f.write(light_css)
with open('output/responsive.css', 'w') as f:
f.write(responsive_css)
with open('output/animation.css', 'w') as f:
f.write(animation_css)
with open('output/index.html', 'w') as f:
f.write(html_content)
print("CSSとHTMLファイルを生成しました。")
実装のポイント解説
CSS変数の活用
テーマカラーをCSS変数として定義することで、以下のメリットがあります:
- 色の一元管理が可能
- 変数の再利用が容易
- JavaScriptからの操作も可能
レスポンシブデザイン
- メディアクエリを使用して画面サイズに応じたスタイル調整
- フォントサイズをemで指定し、相対的なサイズ調整を実現
アニメーション
-
@keyframes
を使用したフェードインアニメーション - ページの読み込み時やテーマ切り替え時の視覚的な演出
テーマ切り替えの実装
JavaScriptを使用してlink
要素のhref
属性を動的に切り替えることで、テーマの切り替えを実現しています。
まとめ
この実装方法のメリットは以下の通りです:
- シンプルで理解しやすい構造
- CSS変数による効率的なテーマ管理
- スムーズなアニメーション効果
- レスポンシブ対応による優れたユーザー体験
今回の実装は基本的な例ですが、これをベースに以下のような拡張が可能です:
- ユーザーの設定を保存(LocalStorage使用)
- システムのテーマ設定との連動
- より複雑なアニメーション効果の追加