ダークモードが良いのか悪いのか分からないけど、ReactとMaterial-UIでダークモード対応

公式ドキュメントにある通り、非常に簡単です。

import React from "react";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";

function App() {
  const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");

  const theme = React.useMemo(
    () =>
      createMuiTheme({
        palette: {
          type: prefersDarkMode ? "dark" : "light",
        },
      }),
    [prefersDarkMode]
  );

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Routes />
    </ThemeProvider>
  );
}

Dark mode

ダークモードの基本

ダークモードは利用者のスマートフォンやパソコンの OS やブラウザで設定されて、表示を黒ベースの背景に変更する仕組みです。

ダークモードは WEB サイトのカラーバリエーションの1つという単純なものではなく、利用者が望む表示を実現することです。利用者にとって、黒ベースがいいという人には黒ベースを、白ベースがいいという人には白ベースを、そして時間帯によって使い分けたいという人には時間帯で切り替わるようにします。そういったことは OS レベルやブラウザレベルで設定されているため、WEB を作る側からすると、ダークモードなのかライトモードなのかのパラメータを判断して、配色を切り替えることになります。

ダークモードのメリットしては次のようなものが挙げられています。

  • 夜間や薄暗い環境で目に優しい
  • 集中力が高まる、文字を認識しやすい
  • バッテリーが長持ちする(ケースによっては 50%以上消費電力が減る!)

ダークモードは効果があるのか

ダークモードが効果があると言われることが多いですが、本当なのでしょうか? Wired の記事では消費電力以外の項目はほぼほぼ否定されています。

この記事を読む限り、通常モードのほうが集中力も高まるし、誤読も少なくなるし、パフォーマンスも高くなるということになります。プロダクトオーナーはダークモードを採用することでアプリやサイトの利用時間を増やそうとしているのではないかと勘ぐってしまいます。

ただダークモードが出てきてから時間も経っていないので、さらなる研究結果は今後出てくるでしょう。 当サイトでもダークモード対応をしていますが、今後の状況によってはダークモードを廃止するかもしれません。 当サイトでは当面は各種デバイスがダークモードに対応しており、アクセシビリティとしてダークモード対応は継続することにします。

ダークモード対応の基本

ダークモード対応の基本はメディアクエリを使ってスタイルシートを設定することです。 とても簡単ですね。 ただそれぞれの要素ごとに設定していく必要があるため、トータルの対応コストは大きくなります。 一度ダークモード対応してしまうと、それをなくすのはサンクコストを考えると難しいかもしれません。

@media (prefers-color-scheme: dark) {
  body {
    background-color: #11181f;
    color: #ffffff;
  }
}

@media (prefers-color-scheme: light) {
  body {
    background-color: #ffffff;
    color: #11181f;
  }
}

このコードは下記のプレイグラウンドで試すことができます。

【Web プログラミング入門】ブラウザですぐに実行できる HTML、CSS、Javascript

Material-UI でのダークモード対応

これはすでに Material-UI 側で用意されているので、以下の設定だけで利用可能です。

import React from "react";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";

function App() {
  const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");

  const theme = React.useMemo(
    () =>
      createMuiTheme({
        palette: {
          type: prefersDarkMode ? "dark" : "light",
        },
      }),
    [prefersDarkMode]
  );

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Routes />
    </ThemeProvider>
  );
}

それぞれの項目をカスタマイズしたい場合には以下のようになります。 それぞれ palette や typography などを別ファイルで定義したものを import して、createMuiThemeの引数に渡すだけになります。

import React from "react";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";

import palette from "./palette";
import typography from "./typography";
import overrides from "./overrides";

function App() {
  const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");

  const theme = React.useMemo(
    () =>
      createMuiTheme({
        palette: {
          ...palette,
          type: prefersDarkMode ? "dark" : "light",
        },
        typography,
        overrides,
        zIndex: {
          appBar: 1200,
          drawer: 1100,
        },
      }),
    [prefersDarkMode]
  );

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Routes />
    </ThemeProvider>
  );
}

たとえば palette は内容はこうなっています。こうやってまとめて設定することで管理も容易になります。

import { colors } from "@material-ui/core";

const white = "#FFFFFF";
const black = "#000000";

export default {
  black,
  white,
  primary: {
    contrastText: white,
    dark: "#00a896",
    main: "#127681",
    light: "#00a896",
  },
  secondary: {
    contrastText: white,
    dark: "#f4e04d",
    main: "#f3c623",
    light: "#ffc53a",
  },
  success: {
    contrastText: white,
    dark: colors.green[900],
    main: colors.green[600],
    light: colors.green[400],
  },
  info: {
    contrastText: white,
    dark: colors.blue[900],
    main: colors.blue[600],
    light: colors.blue[400],
  },
  warning: {
    contrastText: white,
    dark: colors.orange[900],
    main: colors.orange[600],
    light: colors.orange[400],
  },
  error: {
    contrastText: white,
    dark: colors.red[900],
    main: colors.red[600],
    light: colors.red[400],
  },
  icon: "#00a896",
  divider: colors.grey[200],
};

ダークモード対応をやめる場合

prefersDarkModeの項目を削除するだけです。 ダークモード用の各種設定を消す必要はあまりないと思います。

import React from "react";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";

const theme = createMuiTheme();

function App() {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Routes />
    </ThemeProvider>
  );
}

それでは!

Updated at: Thu Jun 25 2020

© 2020-presentTerms|Privacy