CSS light-dark()関数活用ガイド
CSSのlight-dark()関数は、ダークモード対応を劇的に簡素化する新しい機能です。従来のメディアクエリや複雑なCSS変数の管理から解放され、シンプルで保守しやすいコードでライト・ダークモード対応が可能になります。本記事では、基本構文から実践的な活用方法、ブラウザサポート状況まで徹底解説します。
light-dark()関数とは
light-dark()関数は、CSS Color Module Level 5で導入された新しい関数で、ライトモードとダークモードで異なる値を簡潔に指定できます。
基本構文
/* 基本形式 */
color: light-dark(lightModeValue, darkModeValue);
/* 具体例 */
color: light-dark(#000000, #ffffff);
background-color: light-dark(#ffffff, #1a1a1a);
この関数は、color-schemeプロパティと連携して動作します。
color-schemeプロパティとの連携
light-dark()関数を使用するには、color-schemeプロパティの設定が必須です。
グローバル設定
:root {
color-scheme: light dark;
}
この設定により、ブラウザはシステムの設定に応じて自動的にライト・ダークモードを切り替えます。
HTMLでの設定
<!DOCTYPE html>
<html lang="ja">
<head>
<meta name="color-scheme" content="light dark">
<style>
:root {
color-scheme: light dark;
}
body {
background-color: light-dark(#ffffff, #0d1117);
color: light-dark(#24292f, #e6edf3);
}
</style>
</head>
<body>
<h1>自動的にダークモード対応</h1>
</body>
</html>
実践的な使用例
テキストと背景色
:root {
color-scheme: light dark;
}
body {
/* 背景: ライトモードは白、ダークモードは濃いグレー */
background-color: light-dark(#ffffff, #0d1117);
/* テキスト: ライトモードは黒、ダークモードは白 */
color: light-dark(#1f2328, #e6edf3);
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
}
/* リンクの色 */
a {
color: light-dark(#0969da, #2f81f7);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
カードコンポーネント
.card {
background-color: light-dark(#f6f8fa, #161b22);
border: 1px solid light-dark(#d0d7de, #30363d);
border-radius: 8px;
padding: 24px;
box-shadow: light-dark(
0 1px 3px rgba(0, 0, 0, 0.12),
0 1px 3px rgba(0, 0, 0, 0.5)
);
}
.card-title {
color: light-dark(#1f2328, #e6edf3);
font-size: 1.5rem;
margin-bottom: 12px;
}
.card-description {
color: light-dark(#57606a, #8b949e);
line-height: 1.5;
}
ボタンスタイル
.button {
background-color: light-dark(#2da44e, #238636);
color: #ffffff;
border: none;
padding: 12px 24px;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.button:hover {
background-color: light-dark(#2c974b, #2ea043);
transform: translateY(-1px);
box-shadow: light-dark(
0 4px 8px rgba(0, 0, 0, 0.15),
0 4px 8px rgba(0, 0, 0, 0.4)
);
}
.button:active {
transform: translateY(0);
}
.button-secondary {
background-color: light-dark(#f6f8fa, #21262d);
color: light-dark(#24292f, #c9d1d9);
border: 1px solid light-dark(#d0d7de, #30363d);
}
.button-secondary:hover {
background-color: light-dark(#f3f4f6, #30363d);
border-color: light-dark(#bcc4ce, #8b949e);
}
フォーム要素
input[type="text"],
input[type="email"],
textarea {
background-color: light-dark(#ffffff, #0d1117);
color: light-dark(#1f2328, #e6edf3);
border: 1px solid light-dark(#d0d7de, #30363d);
border-radius: 6px;
padding: 8px 12px;
font-size: 14px;
transition: border-color 0.2s;
}
input:focus,
textarea:focus {
outline: none;
border-color: light-dark(#0969da, #1f6feb);
box-shadow: 0 0 0 3px light-dark(
rgba(9, 105, 218, 0.1),
rgba(31, 111, 235, 0.2)
);
}
input::placeholder,
textarea::placeholder {
color: light-dark(#6e7781, #6e7681);
}
ダークモード対応の簡素化
従来の方法と比較して、light-dark()関数がどれだけコードを簡素化するか見てみましょう。
従来の方法(メディアクエリ)
/* ライトモード */
.card {
background-color: #ffffff;
color: #000000;
border: 1px solid #e1e4e8;
}
/* ダークモード */
@media (prefers-color-scheme: dark) {
.card {
background-color: #161b22;
color: #ffffff;
border: 1px solid #30363d;
}
}
light-dark()関数を使用
:root {
color-scheme: light dark;
}
.card {
background-color: light-dark(#ffffff, #161b22);
color: light-dark(#000000, #ffffff);
border: 1px solid light-dark(#e1e4e8, #30363d);
}
コードが半分になり、保守性が大幅に向上します。
CSS変数との組み合わせ
より柔軟な実装のため、CSS変数と組み合わせることも可能です。
:root {
color-scheme: light dark;
/* セマンティックカラー */
--color-primary: light-dark(#0969da, #2f81f7);
--color-secondary: light-dark(#6e7781, #8b949e);
--color-success: light-dark(#1a7f37, #3fb950);
--color-danger: light-dark(#d1242f, #f85149);
--color-warning: light-dark(#9a6700, #d29922);
/* 背景色 */
--bg-primary: light-dark(#ffffff, #0d1117);
--bg-secondary: light-dark(#f6f8fa, #161b22);
--bg-tertiary: light-dark(#f3f4f6, #21262d);
/* ボーダー */
--border-primary: light-dark(#d0d7de, #30363d);
--border-secondary: light-dark(#e1e4e8, #21262d);
/* テキスト */
--text-primary: light-dark(#1f2328, #e6edf3);
--text-secondary: light-dark(#57606a, #8b949e);
--text-tertiary: light-dark(#6e7781, #6e7681);
}
/* 使用例 */
body {
background-color: var(--bg-primary);
color: var(--text-primary);
}
.sidebar {
background-color: var(--bg-secondary);
border-right: 1px solid var(--border-primary);
}
.alert-success {
background-color: var(--color-success);
color: white;
padding: 16px;
border-radius: 6px;
}
実践的なコンポーネント例
ナビゲーションバー
.navbar {
background-color: light-dark(#ffffff, #161b22);
border-bottom: 1px solid light-dark(#d0d7de, #30363d);
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
top: 0;
backdrop-filter: blur(10px);
background-color: light-dark(
rgba(255, 255, 255, 0.8),
rgba(22, 27, 34, 0.8)
);
}
.navbar-brand {
font-size: 1.25rem;
font-weight: 700;
color: light-dark(#1f2328, #e6edf3);
text-decoration: none;
}
.navbar-menu {
display: flex;
gap: 24px;
list-style: none;
margin: 0;
padding: 0;
}
.navbar-link {
color: light-dark(#57606a, #8b949e);
text-decoration: none;
font-weight: 500;
transition: color 0.2s;
}
.navbar-link:hover {
color: light-dark(#1f2328, #e6edf3);
}
.navbar-link.active {
color: light-dark(#0969da, #2f81f7);
}
データテーブル
.table {
width: 100%;
border-collapse: collapse;
background-color: light-dark(#ffffff, #0d1117);
border-radius: 8px;
overflow: hidden;
}
.table thead {
background-color: light-dark(#f6f8fa, #161b22);
}
.table th {
padding: 12px 16px;
text-align: left;
font-weight: 600;
color: light-dark(#1f2328, #e6edf3);
border-bottom: 2px solid light-dark(#d0d7de, #30363d);
}
.table td {
padding: 12px 16px;
color: light-dark(#57606a, #8b949e);
border-bottom: 1px solid light-dark(#d0d7de, #21262d);
}
.table tbody tr:hover {
background-color: light-dark(#f6f8fa, #161b22);
}
.table tbody tr:last-child td {
border-bottom: none;
}
コードブロック
pre {
background-color: light-dark(#f6f8fa, #161b22);
border: 1px solid light-dark(#d0d7de, #30363d);
border-radius: 6px;
padding: 16px;
overflow-x: auto;
font-family: 'Monaco', 'Menlo', monospace;
font-size: 14px;
line-height: 1.5;
}
code {
color: light-dark(#1f2328, #e6edf3);
}
.code-inline {
background-color: light-dark(rgba(175, 184, 193, 0.2), rgba(110, 118, 129, 0.4));
padding: 2px 6px;
border-radius: 3px;
font-family: 'Monaco', 'Menlo', monospace;
font-size: 0.9em;
}
ブラウザサポートとフォールバック
サポート状況(2025年2月現在)
- Chrome/Edge: 123+(2024年3月〜)
- Firefox: 120+(2023年11月〜)
- Safari: 17.5+(2024年5月〜)
フォールバック戦略
最新ブラウザをターゲットにしつつ、古いブラウザのためのフォールバックを提供します。
:root {
color-scheme: light dark;
/* フォールバック: 古いブラウザ用 */
--bg-primary: #ffffff;
--text-primary: #000000;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #0d1117;
--text-primary: #e6edf3;
}
}
/* モダンブラウザ用 */
@supports (background-color: light-dark(#fff, #000)) {
:root {
--bg-primary: light-dark(#ffffff, #0d1117);
--text-primary: light-dark(#000000, #e6edf3);
}
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
}
プログレッシブエンハンスメント
/* ベースライン(全ブラウザ対応) */
.card {
background-color: #ffffff;
color: #000000;
}
/* ダークモード対応(古い方法) */
@media (prefers-color-scheme: dark) {
.card {
background-color: #161b22;
color: #ffffff;
}
}
/* light-dark()関数対応ブラウザ */
@supports (background-color: light-dark(#fff, #000)) {
:root {
color-scheme: light dark;
}
.card {
background-color: light-dark(#ffffff, #161b22);
color: light-dark(#000000, #ffffff);
}
}
パフォーマンスへの影響
light-dark()関数は、CSSの解析時に評価されるため、パフォーマンスへの影響はほとんどありません。
メリット
- CSSファイルサイズの削減: メディアクエリの重複が不要
- 保守性の向上: 色の変更が1箇所で完結
- ランタイムオーバーヘッドなし: JavaScriptが不要
ベストプラクティス
/* Good: セマンティックな変数名 */
:root {
color-scheme: light dark;
--color-primary: light-dark(#0969da, #2f81f7);
--color-text: light-dark(#1f2328, #e6edf3);
}
/* Better: 変数を再利用 */
.button-primary {
background-color: var(--color-primary);
color: white;
}
/* Best: コンポーネントベースの変数 */
.button {
--button-bg: light-dark(#f6f8fa, #21262d);
--button-text: light-dark(#24292f, #c9d1d9);
--button-border: light-dark(#d0d7de, #30363d);
background-color: var(--button-bg);
color: var(--button-text);
border: 1px solid var(--button-border);
}
まとめ
CSS light-dark()関数は、ダークモード実装を劇的に簡素化する強力なツールです。主な利点は以下の通りです。
- シンプルなコード: メディアクエリの重複が不要
- 保守性の向上: 色の定義が1箇所に集約
- パフォーマンス: ランタイムオーバーヘッドなし
- 柔軟性: CSS変数と組み合わせて強力
モダンブラウザのサポートが広がる中、light-dark()関数は今後のスタンダードになっていくでしょう。フォールバック戦略を適切に実装することで、すべてのユーザーに最適な体験を提供できます。