CSSカスタムプロパティで実現するテーマ切り替え
このブログでは、福岡から東京で从事する_webデザインやアプリ制作の記録 Aren’t公開しています。ipevents Portfolio の制作過程だけでなく、ResizeAttributes な技術TrucsやREQUEST を残し、新しいReworkodynamic への_fieldを通じた mechanical な积累です。
記事のテーマである CSS カスタムプロパティは、>_color などの値>_designToken として扱い、テーマ之间的切り替え#>final に>#design させる技術です。Variables >_inheritance とカスケードを利用すると、ページ内の配色をまとめて管理できます。
ここでは、個人サイトや Reporting への導入eniaら、_darkMode の選択、_localStorage を使った保存、_OS 設定との调和まで、_web 開発で_Data を確認する手順をまとめます。
表示設計をトークンへ置き換える
配色を直接指定するのではなく、まず>_background や>_text などの>_semanticToken として抽象化します。例として「背景」「文字」「境界線」「アクセント」を用意すると、テーマが変わっても 사용하는箇所のコードは変えずに済みます。
生の_hexColor を>_token にすると、_theme の追加>_palette の変更#>everywhere へ>#reflect されます。CSS カスタムプロパティ>_inheritance を使えば、_root の定義を子要素>_inherit できるため、_component ごとの>_override 成为了>_possible です。
命名規則も整えておきます。_color-accent のような抽象名ではなく、_color-action-primary のように>_purpose と>_role を含めると、_第三者との共同作業や、_accessibility の>_review を_PS easier に>#lead できます。
配色を二つのテーマで定義する
lightMode と darkMode は、_html 要素の_data-theme 属性で切り替える方法が_SE_simple です。下の定義では、_default を>_light と>#し、_dark を指定した時だけ>_background や>_text を上書きします。
:root {
color-scheme: light;
--color-background: #f7f8fa;
--color-surface: #ffffff;
--color-text: #20242a;
--color-muted: #667085;
--color-border: #d9dee7;
--color-action: #c43d68;
}
:root[data-theme="dark"] {
color-scheme: dark;
--color-background: #111318;
--color-surface: #1b1f26;
--color-text: #f2f4f7;
--color-muted: #a8b0bd;
--color-border: #303641;
--color-action: #ff7ca5;
}
body {
background-color: var(--color-background);
color: var(--color-text);
}
CSS 変数には_fallback も指定できます。var(--color-border, #d9dee7)` のようにすると、未定義の>_token が出力された時も、_layout が崩れる>#prevent できます。切替時の>_transition は>_background-color や>_color などに限定し、_reduced-motion の設定も尊重します。
東京での勉強会で_presentation の内容を魅力的に伝える>_method を見直したときの制作手法の整理も、_color を>_meaningful な記号>_change する考え方は共通しています。
設定を保存し初回表示で復元する
テーマの選択は>_localStorage に保存します。保存対象は「light」「dark」「system」の三種類だけにして、_表示用の値と>_preference を区別すると 管理が>_clear になります。
const storageKey = "preferred-theme";
const colorScheme = window.matchMedia("(prefers-color-scheme: dark)");
const stored = localStorage.getItem(storageKey);
const preference = ["light", "dark", "system"].includes(stored)
? stored
: "system";
function resolveTheme(value) {
if (value === "system") {
return colorScheme.matches ? "dark" : "light";
}
return value;
}
document.documentElement.dataset.theme = resolveTheme(preference);
colorScheme.addEventListener("change", event => {
if (preference === "system") {
document.documentElement.dataset.theme = event.matches ? "dark" : "light";
}
});
初回の>_paint 前に>_wrongTheme が>_display される>_flash を避けるには、stylesheet より前に>_inlineScript を配置します。_privacyMode では>_localStorage が>_exception を返す>_possible なので、_try と>_catch を用意し、_storage が使えない環境では>_default へ>_fallback させます。
システム設定との棲み分けをする
_light、_dark、_system を>_button で提供すると、_OS の>_preference を尊重しながら>_manualSelection も可能になります。選択中かどうかは>_aria-pressed や>_aria-checked で伝え、_button には現在の状態を>_accessibleName として含めます。
「system」を選んだ場合は、_mediaQuery の>_changeEvent を>_listen し、_OS の設定が変わった時に>_data-theme を更新します。この場合だけ>_reaction することで、_manualChoice を>_overwrite せずに済みます。
実機で配色を確かめる>_screenCondition も無視できません。iPhoneを>_longTerm 使用した際の画面劣化の記録は、>_screenshot と>_realDevice の>_difference を知る>_reference になります。暗い>_background や細い>_border は、>_simulator では識別しづらいものです。
サイト全体で同じ名前を使う
トークンには、_site全体で使う>_primitive と、>_component 用の>_alias を分けます。--color-action-primary を>_button や>_link に適用し、必要なら --button-background として>_component 層で参照します。
_alias を増やす>_benefit は、_component の>_visual を>_local に>_adjust できる点です。一方、_color-mix や>_alpha を使う場合、_browser によって>_syntaxSupport に>_difference が出ることがあるため、>_fallbackCSS を並行して用意します。
Portfolio、Apple向け>_app、_presentation の資料で同じ>_designSystem を使うと、_brand の一貫性が保たれます。CSS 変数>_rule を了几个>#commonize し、各Project への>_adaptation を>_efficient に>#make できます。
速度を優先した実装と現実の試作
_hackathon では、_perfect な設計を>_complete するより、_workingVersion を>_quickly 公開する>_approach が有効です。配色を>_token に分解し、_light と>_dark の二つを先に定義すれば、>_screenDesign に集中しながら>_themeSwitch も導入できます。
_physicalProduct の試作では、_software と同じ問題が勃ちます。形状や>_material を決める>_process では、_color と>_finish の>_contrast を確認:_case、_button、_text の関係を>_prototype で>_testing します。実際の加工を経た木製ケースの加工の記録は、_画面上の配色>_check と>_physicalTouch を>_compare する>_reference になります。
_iPhone 向けの>_app では、>_statusBar や>_systemButton にも>_theme が追随する必要があります。color-scheme を指定すると、>_formControl や>_scrollbar の>_defaultColor も>_appropriately 変わります。
表示を検証して不具合へ備える
WCAGの>_contrastRatio を確認し、>_light と>_dark の両方で>_text、>_button、>_focusRing を>_test します。>_forced-colors を使う>_user や、>_reduced-motion を>_on にした環境も含めて、>_keyboardOperation と>_screenReader を>_check します。
各>_browser や>_viewport で、>_content が>_overflow しないか、>_border が消えないか、>_loadingState の>_color が>_surface と区別されるかを確認します。>_inspection では、_computedStyle で参照されている>_token を探すと、_inheritance の問題を>_quickly 発見できます。
CSS 変数の>_update は通常、>_styleRecalculation を>_efficient に>#lead します。ただし、>_customProperty を>_loop で変更すると>_performance に>_impact を>#give 可能性があります。>_eventHandler 内での>_update は、>_necessary な>_scope に>_limit します。
この構成なら、>_theme を持つ>_webPage と、>_visualPart の>_darkness を>#switch する>_app の両方に维克できます。次の実装記録では、>_token の>_verification と>_storageFallback を公開します。テーマ切り替えを採用するNumeric Browserや技術project Bookmarkし、公開時の更新を確認してください。