web-dev-qa-db-ja.com

CSSを優先する方法の色スキーム設定をオーバーライドする方法

MacOS、Windowsがすでに実装しているように、私はダークモードを実装しています。iOSはネイティブダークモードを導入する予定です。

SafariChrome、およびFirefoxには、次のCSSメディアルールを使用するネイティブオプションがあります。

@media (prefers-color-scheme: dark) {
body {
    color:#fff;
    background:#333333
}

これにより、ダークモードに設定されているシステムが自動的に識別され、囲まれたCSSルールが適用されます。

しかしながら;ユーザーがシステムをダークモードに設定している場合でも、特定のWebサイトのライトまたはデフォルトのテーマを好む場合があります。 Microsoft Edgeを(まだ)サポートしていない@media (prefers-color-schemeユーザーの場合もあります。最高のユーザーエクスペリエンスを実現するために、これらのユーザーがこれらのケースでダークモードとデフォルトモードを切り替えられるようにしたいと思います。

HTML5またはJavaScriptを使用して、これを実行できるメソッドはありますか?私が試したコードを含めますが、これを実装するための情報を見つけることができませんでした!

12
JimmyBanks

@JimmyBanksが提供するソリューションを採用し、1)チェックボックスをテキストボタンに切り替え、2)OSテーマの変更時に自動テーマ切り替えを追加しました。

CSSは変更されていません。明るいテーマは:rootに、暗いテーマは[data-theme="dark"]に保存されています。

:root {
  --color_01: #000;
  --color_02: #fff;
  --color_03: #888;
}

[data-theme="dark"] {
  --color_01: #fff;
  --color_02: #000;
  --color_03: #777;
}

<head> JSにはいくつかの編集があり、いくつかの省略とdata-themeステートメントの後続のJSブロックへの移動が含まれています。

var theme = 'light';
if (localStorage.getItem('theme')) {
  if (localStorage.getItem('theme') === 'dark') {
    theme = 'dark';
  }
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
  theme = 'dark';
}

次に、JSの2番目のブロックの編集と関連するHTMLを示します。 theme_switchはテーマを切り替えますが、theme_OSはサイトのテーマをOSテーマの変更で自動的に更新します。

var theme;
function theme_apply() {
  'use strict';
  if (theme === 'light') {
    document.getElementById('theme_readout').innerHTML = 'Dark';
    document.documentElement.setAttribute('data-theme', 'light');
    localStorage.setItem('theme', 'light');
  } else {
    document.getElementById('theme_readout').innerHTML = 'Light';
    document.documentElement.setAttribute('data-theme', 'dark');
    localStorage.setItem('theme', 'dark');
  }
}
theme_apply();
function theme_switch() {
  'use strict';
  if (theme === 'light') {
    theme = 'dark';
  } else {
    theme = 'light';
  }
  theme_apply();
}
var theme_OS = window.matchMedia('(prefers-color-scheme: light)');
theme_OS.addEventListener('change', function (e) {
  'use strict';
  if (e.matches) {
    theme = 'light';
  } else {
    theme = 'dark';
  }
  theme_apply();
});
<a onclick="theme_switch()">Theme: <span id="theme_readout"></span></a>

改善のためのご提案がございましたら、ぜひお知らせください。

0
Meanderbilt

私のソリューション(無線入力の3つのオプション:ダーク、システム、ライト)のJimmyBanksおよびMeanderbiltソリューションの適応:

少し冗長だと思いますが、頭を巻くのに少し苦労しました

const themeSwitches = document.querySelectorAll('[data-color-theme-toggle]')

function removeColorThemeLocalStorage() {
  localStorage.removeItem('color-theme')
}

function saveColorTheme(colorTheme) {
  if (colorTheme === 'system') {
    removeColorThemeLocalStorage()
    return
  }
  localStorage.setItem('color-theme', colorTheme)
}

function applyColorTheme() {
  const localStorageColorTheme = localStorage.getItem('color-theme')
  const colorTheme = localStorageColorTheme || null
  if (colorTheme) {
    document.documentElement.setAttribute('data-color-theme', colorTheme)
  }
}

function themeSwitchHandler() {
  themeSwitches.forEach(themeSwitch => {
    const el = themeSwitch
    if (el.value === localStorage.getItem('color-theme')) {
      el.checked = true
    }

    el.addEventListener('change', () => {
      if (el.value !== 'system') {
        saveColorTheme(el.value)
        applyColorTheme(el.value)
      } else {
        removeColorThemeLocalStorage()
        document.documentElement.removeAttribute('data-color-theme')
      }
    })
  })
  applyColorTheme()
}
document.addEventListener('DOMContentLoaded', () => {
  themeSwitchHandler()
  applyColorTheme()
})

html {
  --hue-main: 220;
  --color-text: hsl(var(--hue-main), 10%, 25%);
  --color-text--high-contrast: hsl(var(--hue-main), 10%, 5%);
  --color-link: hsl(var(--hue-main), 40%, 30%);
  --color-background: hsl(var(--hue-main), 51%, 98.5%);
}

@media (prefers-color-scheme: dark) {
  html.no-js {
    --color-text: hsl(var(--hue-main), 5%, 60%);
    --color-text--high-contrast: hsl(var(--hue-main), 10%, 80%);
    --color-link: hsl(var(--hue-main), 60%, 60%);
    --color-background: hsl(var(--hue-main), 10%, 12.5%);
  }
}

[data-color-theme='dark'] {
  --color-text: hsl(var(--hue-main), 5%, 60%);
  --color-text--high-contrast: hsl(var(--hue-main), 10%, 80%);
  --color-link: hsl(var(--hue-main), 60%, 60%);
  --color-background: hsl(var(--hue-main), 10%, 12.5%);
}
    <div class="color-scheme-toggle" role="group" title="select a color scheme">
    <p>saved setting: <span class="theme-readout">...</span></p>
        <input type="radio" name="scheme" id="dark" value="dark" aria-label="dark color scheme"> <label for="dark">dark</label>
        <input type="radio" name="scheme" id="system" value="system" aria-label="system color scheme" checked="system"> <label for="system">system</label>
        <input type="radio" name="scheme" id="light" value="light" aria-label="light color scheme"> <label for="light">light</label>
    </div>
0
scsskid