Safari 27.3 betaのAdaptive Dark Modeを防ぐcolor-schemeの書き方
目次
TL;DR
機能の概要 Safari 27.3 betaのAdaptive Dark Modeは、OSがダーク表示のとき、ダークモード未対応の明るいサイトをSafari側で暗く描き直す機能。ユーザーが設定で有効化する。
変換を止める条件 HTMLの <meta name="color-scheme" content="light dark"> か、CSSの color-scheme: light dark で対応を宣言しているページは変換対象から外れる。
注意点 変換を抑えるために color-scheme: light dark を宣言すると、OSがダークのときはブラウザ既定の文字色も明るい色へ変わる。背景色だけを白に固定して文字色を指定していないページでは、白い背景に白い文字が重なり読めなくなる。Adaptive Dark Modeが文字を白くしたのではなく、宣言とOSダーク設定による既定色の副作用。宣言とセットでダーク用の背景色・文字色を用意しておく必要がある。部分除外の light only はbeta 1ではまだ反映されない。
Appleが2026年11月3日に開発者向けに配布したiOS 27.3、iPadOS 27.3、macOS 27.3の最初のベータで、Safariに「Adaptive Dark Mode」が追加された。
WebKitの発表記事によると、ダークモードに対応していない明るい配色のサイトを、Safariが自動で暗い見た目に変換して表示する。
サイトを運営する側から見ると、ダーク用の配色を用意していないページが、Safari側の処理で配色を変えて表示される。
変換されるのは、ユーザーが機能を有効にしていて、ページがダーク対応を宣言していなくて、全体が明るい場合になる。
サイト側で決められるのはCSSの color-scheme の宣言なので、その書き方と、宣言を追加したときの挙動をコード例と一緒に整理してみる。
なお、Safari 27.3 betaの実機での見え方は未確認で、Adaptive Dark Modeの挙動の説明はWebKitの発表記事やCSS仕様・MDNの記述を元にしている。
記事中のコード例はmacOSのSafari 26.5.2で開き、color-scheme の宣言によってページの見た目がどう変わるかを確かめた。
Adaptive Dark Modeが何をするか
使うときは、まずOSの外観設定をダークにする。
その状態で背景の明るいサイトを開くと、Safariが変換後のプレビューを出し、「Try」をタップすると暗い表示に切り替わる。
9to5Macの記事では、自動で適用するか、サイトごとに選ぶかも設定できるとしている。
変換処理は、色の明るさ(輝度)を反転させつつ色相を保つ仕組みだ。
文字と背景のコントラストは、アクセシビリティ基準のWCAGが定める4.5:1を目標にしている。
ボタンや画像の上に載った文字、カーソルを重ねて出るメニューが使えなくならないよう、要素ごとに判定しているとも書いている。
要素ごとの扱いはこんな感じ。
| 対象 | Adaptive Dark Modeでの扱い |
|---|---|
| もともと暗い背景に明るい文字のページ | 何も変えない |
| CSSの明るいグラデーション | 暗くする |
| SVG画像 | アイコンやロゴが見えるよう、必要なら色を変える |
| ビットマップ画像 | ほとんどはそのまま。白黒の単純なロゴだけ、画素の明るさの分布(ヒストグラム)から判定して反転する |
<canvas> の中身 | 内容を予測しにくいので変えない |
マスクや mix-blend-mode | 変換した要素では効果を無効にすることがある |
変換されないための宣言
color-scheme は、その要素がライトとダークのどちらの配色で描画されてよいかをブラウザに伝えるCSSプロパティで、light dark と指定すると「自前でダークモードに対応している」という意味になる。
WebKitの発表では、この宣言があるページにはAdaptive Dark Modeは何もしない。
宣言の場所はHTMLの <head> か、CSSの :root や body を勧めていて、あとからJavaScriptで追加するのは避けるよう案内されている。
<!-- HTMLで宣言する。<head>の中、CSSより前に置く -->
<meta name="color-scheme" content="light dark">
/* CSSで宣言する */
:root {
color-scheme: light dark;
}
次のように、読み込み完了後にスクリプトで宣言を追加する形は避けておく。
// 避ける例:ページ表示後にJavaScriptで宣言を追加している
window.addEventListener('load', () => {
const meta = document.createElement('meta');
meta.name = 'color-scheme';
meta.content = 'light dark';
document.head.append(meta);
});
宣言ごとの扱いはこんな感じ。
| ページの状態 | 変換されるか | 出典での扱い |
|---|---|---|
light dark をmetaかCSSで宣言 | されない | WebKitの発表に明記 |
light only をmetaかCSSで宣言 | 変換から外す指定だが、beta 1では反映されない | WebKitの発表に明記。beta 1では only キーワードに未対応と注記あり |
| 宣言なしで、背景が明るい | される | WebKitの発表に明記 |
| 宣言なしで、もともと暗い | されない | WebKitの発表に明記 |
light だけ、dark だけを宣言 | 不明 | WebKitの発表には書かれていない |
beta 1の時点で確実に変換を抑えられるのは、light dark を宣言する方法になる。
宣言だけ追加したときの文字消失
color-scheme: light dark は変換停止スイッチというより、「このページはダーク表示にも対応している」とブラウザへ伝える宣言だ。
この宣言があると、OSがダーク表示のときはブラウザ側の既定配色がダーク用に切り替わる。
CSSの仕様では、宣言で決まった配色がスクロールバーやフォーム要素の既定の色を変え、ルート要素(html タグ)ではページの背景色も変えるとしている。
文字色を指定していない要素は、ブラウザの既定の文字色を使う。
この既定色はOSやブラウザの配色に合わせて変わるシステムカラーで、ダーク用では明るい色になる。
そのため背景色だけを白に固定していたページでは、白い背景に白い文字が重なって読めなくなる。
<!-- 注意すべき例:宣言だけ追加して、ダーク用の配色を用意していない -->
<meta name="color-scheme" content="light dark">
<style>
body {
background: #ffffff; /* 背景は白に固定している */
/* 文字色は指定していないので、ダーク表示では既定の明るい色になる */
}
</style>
このコードに見出し、本文、リンク、入力欄、ボタンを追加したページを、Safari 26.5.2で開いた。
OSの外観設定がライトのときは、白い背景に黒い文字で普通に読める。

OSをダーク表示に切り替えると、見出しと本文が消えた。
見出しと本文の位置は画素が白(#FFFFFF)になり、文字は背景と同じ真っ白で読めない。
表示が残ったのは薄紫のリンクと、黒いダーク用の外観に変わった入力欄とボタンだけで、白い背景から目立っている。

宣言を追加するなら、ダーク用の背景色と文字色も一緒に用意しておく。
ダークモードに対応した最小のコード例
1ファイルで試せる最小のコード例はこんな感じ。
ロゴ画像(logo-light.svg と logo-dark.svg)を同じフォルダーに置くと切り替えに対応でき、画像がない場合は代替テキストが表示される。
保存してブラウザで開き、OSの外観設定をライトとダークで切り替えると、配色が変わる。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- ダークモードに対応していると宣言する。CSSより前に置く -->
<meta name="color-scheme" content="light dark">
<title>color-schemeの例</title>
<style>
:root {
color-scheme: light dark;
/* light-dark(ライトのときの色, ダークのときの色) */
--bg: light-dark(#ffffff, #121212);
--text: light-dark(#1a1a1a, #e6e6e6);
--muted: light-dark(#5f6368, #a0a4a8);
--link: light-dark(#0b57d0, #8ab4f8);
--card: light-dark(#f4f5f7, #1e1f22);
--border: light-dark(#d9dce1, #3a3c40);
}
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: system-ui, sans-serif;
line-height: 1.7;
}
main {
max-width: 40rem;
margin: 0 auto;
padding: 24px 16px;
}
a {
color: var(--link);
}
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
}
.note {
color: var(--muted);
font-size: 0.875rem;
}
</style>
</head>
<body>
<main>
<!-- ロゴはライト用とダーク用を出し分ける -->
<picture>
<source srcset="logo-dark.svg" media="(prefers-color-scheme: dark)">
<img src="logo-light.svg" alt="サイトのロゴ" width="160" height="40">
</picture>
<h1>color-schemeの例</h1>
<div class="card">
<p>OSの外観設定を切り替えると、背景と文字の色が変わる。</p>
<p><a href="#">リンクの色</a>もダーク用に変わる。</p>
<p><input type="text" placeholder="入力欄もダーク用の見た目になる"></p>
<p class="note">補足の文字は少し薄い色にしている。</p>
</div>
</main>
</body>
</html>
light-dark() は、ページの配色がライトのときは1つ目の色、ダークのときは2つ目の色を返すCSSの関数だ。
MDNによると、使うには color-scheme を light dark に設定しておくのが前提で、ふつうは :root に書く。
ロゴの出し分けに使っている <picture> と media="(prefers-color-scheme: dark)" の組み合わせは、WebKitの発表でもダークモード対応の手段として案内されている。
このページをSafari 26.5.2で開き、OSの外観設定をライトとダークで切り替えた。
画像ファイルがない状態では、ロゴ位置に代替テキストの「サイトのロゴ」が表示される。
ライト表示のときは白い背景に灰色のカードが並ぶ。

ダークに切り替えると、背景、カード、文字、リンクが light-dark() の2つ目の色に変わり、入力欄もダーク用の外観になった。

light-dark() に未対応のブラウザもサポートする場合は、メディアクエリで色を上書きする。
<style> の :root 部分を次のように変更する。
:root {
color-scheme: light dark;
--bg: #ffffff;
--text: #1a1a1a;
--muted: #5f6368;
--link: #0b57d0;
--card: #f4f5f7;
--border: #d9dce1;
}
/* OSがダーク表示のときだけ上書きする */
@media (prefers-color-scheme: dark) {
:root {
--bg: #121212;
--text: #e6e6e6;
--muted: #a0a4a8;
--link: #8ab4f8;
--card: #1e1f22;
--border: #3a3c40;
}
}
切り替えボタンでライトとダークを選ぶコード例
OSの設定に従うだけでなく、ページのボタンでライトとダークを選べるようにしているサイトも多い。
その場合も、<meta name="color-scheme" content="light dark"> はHTMLに最初から書いておく。
JavaScript側はユーザーが選んだ配色の反映に絞って処理させる。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 宣言はHTMLに最初から書いておき、スクリプトで追加しない -->
<meta name="color-scheme" content="light dark">
<script>
// 描画前に、保存済みの選択をhtml要素へ反映する(一瞬白く光るのを防ぐ)
(() => {
let saved = null;
try {
saved = localStorage.getItem('theme');
} catch {}
if (saved === 'light' || saved === 'dark') {
document.documentElement.dataset.theme = saved;
}
})();
</script>
<title>切り替えボタンの例</title>
<style>
:root {
color-scheme: light dark; /* 未選択のときはOSの設定に従う */
--bg: light-dark(#ffffff, #121212);
--text: light-dark(#1a1a1a, #e6e6e6);
}
/* ボタンで選んだときは配色を固定する */
:root[data-theme="light"] {
color-scheme: light;
}
:root[data-theme="dark"] {
color-scheme: dark;
}
body {
margin: 0;
padding: 24px 16px;
background: var(--bg);
color: var(--text);
font-family: system-ui, sans-serif;
}
</style>
</head>
<body>
<button type="button" id="theme-toggle">ライト/ダークを切り替える</button>
<p>ボタンで選んだ配色は次に開いたときも使われる。</p>
<script>
const root = document.documentElement;
document.getElementById('theme-toggle').addEventListener('click', () => {
// いま表示されている配色を調べて、反対側に切り替える
const current = root.dataset.theme
?? (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
const next = current === 'dark' ? 'light' : 'dark';
root.dataset.theme = next;
try {
localStorage.setItem('theme', next);
} catch {}
});
</script>
</body>
</html>
色は light-dark() で定義しておき、ボタンでは color-scheme の値だけを切り替えている。
color-scheme: light にすると light-dark() は1つ目の色を返し、スクロールバーや入力欄もライト用の見た目になる。
OSがダーク表示でも利用者がライトを選んだ場合、フォームなどの部品まで含めてライト表示になる。
Safari 26.5.2で、OSをダーク表示にした状態でこのページを開いた。
最初は黒い背景に明るい文字で表示され、ボタンを押すとページ全体がライトに切り替わった。
ボタン自体もライト用の見た目になり、再読み込みしてもライトのまま維持されていた。

この例は <head> のmetaタグで light dark を宣言しているので、WebKitの説明に従えば、ダーク対応のページとして扱われて変換されない。
ただ、ユーザーがライトを選ぶと、CSS側では <html> の color-scheme が light だけになり、metaタグの宣言と食い違う。
metaとCSSの指定が食い違ったときにSafariがどちらを優先して判定するかは、WebKitの発表には書かれていない。
この組み合わせでどう扱われるかは、Safari 27.3 betaの実機で確認しておきたい。
一部だけ変換させない light only
特定の部分だけ変換を避けたい場合もある。
グラフの色分け、商品写真の背景、ブランドカラーで塗ったバナーなどがそれに当たる。
WebKitの発表では、light only を宣言すると変換の対象から外れる。
metaタグならページ全体、CSSなら要素を選んで指定できる。
ただし、Safari 27.3 beta 1の時点ではこの指定はまだ反映されない。
<!-- ページ全体を変換の対象から外す -->
<meta name="color-scheme" content="light only">
/* グラフと商品写真の枠だけ、ライトのまま表示させる */
.sales-chart,
.product-photo-frame {
color-scheme: light only;
}
only はもともとCSSの仕様にあるキーワードで、仕様では「ブラウザがその要素の配色を上書きするのを禁じる」と定義されている。
MDNには、ChromeのAuto Dark Themeによる色の上書きを止める用途も書かれている。
仕様の文法では only は色の指定の前にも後ろにも置けるので、only light と light only は同じ意味になる。
ただし、WebKitの発表には「Safari 27.3 beta 1では only キーワードに対応していない」との注記がある。
ベータの更新に合わせて状況を確認する案内になっており、beta 1の時点では、部分的に外したい要素でも light dark を宣言したうえで自前のダーク配色を指定する形になる。
/* beta 1で変換を止める場合:その要素でダーク対応を宣言し、配色を自分で決める */
.sales-chart {
color-scheme: light dark;
background: light-dark(#ffffff, #1e1f22);
color: light-dark(#1a1a1a, #e6e6e6);
}
変換に任せる場合に直しておくところ
自前でダーク用の配色を作らず、Adaptive Dark Modeの変換に任せる方法もある。
その場合でも変換後の崩れを防ぎやすいよう、WebKitの発表では以下の対策が挙げられている。
| 直すところ | 理由 |
|---|---|
| ロゴやアイコンのビットマップ画像をSVGにする | SVGは必要に応じて色を変換できるが、ビットマップは白黒の単純なロゴしか反転しない |
| タイル状の背景画像をCSSの単色やグラデーションにする | CSSの色は変換できるが、背景画像はそのまま残る |
| 画像のスプライトを最新のCSSに置き換える | スプライトもビットマップ画像なので、白黒の単純なロゴ以外はそのまま残る |
| 本文の画像は背景を透過にし、背景色を画像データ内に含めない | 透過していない白い背景だけが暗いページの中で浮く |
| コンテナに余白(padding)を設ける | 要素同士が詰まるのを防ぐ |
サイト側からの変換検出
WebKitの発表によると、SafariはAdaptive Dark Modeが適用されたことをサイト側から検出できないようにしている。
JavaScriptでCSSの色を読み出すと、サイトが指定した元の色がそのまま返る。
<canvas> から画像を取り出した場合も、元の色のまま描かれる。
そのため、アクセス解析のスクリプトなどでAdaptive Dark Modeの適用ユーザー数を集計することはできない。
実際の表示を確認するには、Safari 27.3 betaの実機でページを開いて確かめる形になる。
表示が乱れたページを見つけたときの報告先も、WebKitの発表に案内されている。
サイトの運営者はApple宛ての web-evangelist@apple.com へ、Safariの利用者はFeedback Assistantから報告できる。