侧边栏壁纸
博主头像
博主等级

秋风清,秋月明,落叶聚还散,寒鸦息复惊,相思相见知何日,此时此夜难为情!

  • 累计撰写 22 篇文章
  • 累计创建 33 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

网页暗黑模式切换

尘
2024-06-10 / 0 评论 / 0 点赞 / 81 阅读 / 21527 字
温馨提示:
本文最后更新于 2024-06-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

网页的暗黑模式切换

在网页中实现暗黑模式和亮色模式的切换,通过定义CSS变量(Custom Properties)来管理不同的主题颜色,并根据特定的条件来应用这些变量。

实现效果

switchTheme.gif

移动端还存在一个问题,如下图第三张,移动设备上的浏览器设置为暗黑模式(Dark Mode)时,页面的浅色模式样式被浏览器覆盖,如果对于该情况有特殊需求,比如保持不被覆盖,可通过使用媒体查询检测系统暗黑模式再设置相应样式。

使用 CSS 媒体查询 prefers-color-scheme,你可以检测用户的系统是否启用了暗黑模式,并相应地调整网页的样式。

相应代码设置:

/* 这个用于处理浏览器设置为暗色模式的情况 */
@media (prefers-color-scheme: dark) {
  :root {
    --text-color: #2ecc71;
    --bg-color: #34495e;
  }
}

完整代码

  • index.html

    <!DOCTYPE html>
    <html lang="zh">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link
          href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/minireset.css/0.0.2/minireset.min.css"
          type="text/css"
          rel="stylesheet"
        />
        <link rel="stylesheet" href="./index.css" />
        <link rel="stylesheet" href="./theme.css" />
        <title>暗黑模式切换</title>
      </head>
      <body>
        <div class="container">
          <div class="themeTitle selector" id="themeTitle">浅色</div>
          <div class="themeSwitch">
            <label class="ui-switch">
              <input type="checkbox" id="themeSwitch" onclick="switchTheme()" />
              <div class="slider">
                <div class="circle"></div>
              </div>
            </label>
          </div>
        </div>
      </body>
      <script src="./index.js"></script>
    </html>
    
  • index.css

    /* switch settings 👇 */
    
    .ui-switch {
      /* switch */
      --switch-bg: rgb(135, 150, 165);
      --switch-width: 48px;
      --switch-height: 20px;
      /* circle */
      --circle-diameter: 32px;
      --circle-bg: rgb(0, 56, 146);
      --circle-inset: calc((var(--circle-diameter) - var(--switch-height)) / 2);
    }
    
    .ui-switch input {
      display: none;
    }
    
    .slider {
      -webkit-appearance: none;
      -moz-appearance: none;
      appearance: none;
      width: var(--switch-width);
      height: var(--switch-height);
      background: var(--switch-bg);
      border-radius: 999px;
      position: relative;
      cursor: pointer;
    }
    
    .slider .circle {
      top: calc(var(--circle-inset) * -1);
      left: 0;
      width: var(--circle-diameter);
      height: var(--circle-diameter);
      position: absolute;
      background: var(--circle-bg);
      border-radius: inherit;
      background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTkuMzA1IDEuNjY3VjMuNzVoMS4zODlWMS42NjdoLTEuMzl6bS00LjcwNyAxLjk1bC0uOTgyLjk4Mkw1LjA5IDYuMDcybC45ODItLjk4Mi0xLjQ3My0xLjQ3M3ptMTAuODAyIDBMMTMuOTI3IDUuMDlsLjk4Mi45ODIgMS40NzMtMS40NzMtLjk4Mi0uOTgyek0xMCA1LjEzOWE0Ljg3MiA0Ljg3MiAwIDAwLTQuODYyIDQuODZBNC44NzIgNC44NzIgMCAwMDEwIDE0Ljg2MiA0Ljg3MiA0Ljg3MiAwIDAwMTQuODYgMTAgNC44NzIgNC44NzIgMCAwMDEwIDUuMTM5em0wIDEuMzg5QTMuNDYyIDMuNDYyIDAgMDExMy40NzEgMTBhMy40NjIgMy40NjIgMCAwMS0zLjQ3MyAzLjQ3MkEzLjQ2MiAzLjQ2MiAwIDAxNi41MjcgMTAgMy40NjIgMy40NjIgMCAwMTEwIDYuNTI4ek0xLjY2NSA5LjMwNXYxLjM5aDIuMDgzdi0xLjM5SDEuNjY2em0xNC41ODMgMHYxLjM5aDIuMDg0di0xLjM5aC0yLjA4NHpNNS4wOSAxMy45MjhMMy42MTYgMTUuNGwuOTgyLjk4MiAxLjQ3My0xLjQ3My0uOTgyLS45ODJ6bTkuODIgMGwtLjk4Mi45ODIgMS40NzMgMS40NzMuOTgyLS45ODItMS40NzMtMS40NzN6TTkuMzA1IDE2LjI1djIuMDgzaDEuMzg5VjE2LjI1aC0xLjM5eiIgLz4KPC9zdmc+");
      background-repeat: no-repeat;
      background-position: center center;
      -webkit-transition: left 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
        -webkit-transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
      -o-transition: left 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
        transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
      transition: left 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
        transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
        -webkit-transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-align: center;
      -ms-flex-align: center;
      align-items: center;
      -webkit-box-pack: center;
      -ms-flex-pack: center;
      justify-content: center;
      box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2),
        0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
    }
    
    .slider .circle::before {
      content: "";
      position: absolute;
      width: 100%;
      height: 100%;
      background: rgba(255, 255, 255, 0.75);
      border-radius: inherit;
      -webkit-transition: all 500ms;
      -o-transition: all 500ms;
      transition: all 500ms;
      opacity: 0;
    }
    
    /* actions */
    
    .ui-switch input:checked + .slider .circle {
      left: calc(100% - var(--circle-diameter));
      background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTQuMiAyLjVsLS43IDEuOC0xLjguNyAxLjguNy43IDEuOC42LTEuOEw2LjcgNWwtMS45LS43LS42LTEuOHptMTUgOC4zYTYuNyA2LjcgMCAxMS02LjYtNi42IDUuOCA1LjggMCAwMDYuNiA2LjZ6IiAvPgo8L3N2Zz4=");
    }
    
    .ui-switch input:active + .slider .circle::before {
      -webkit-transition: 0s;
      -o-transition: 0s;
      transition: 0s;
      opacity: 1;
      width: 0;
      height: 0;
    }
    
    body {
      background-color: var(--bg-color);
      color: var(--text-color);
      transition: background-color 0.3s, color 0.3s;
    }
    
    .container {
      width: 100%;
      margin: 0 auto;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding-top: 6rem;
    }
    
    .themeTitle {
      font-size: 2rem;
      font-weight: 700;
      margin-bottom: 1rem;
    }
    
    /* 文字不可选中 */
    .selector {
      -webkit-user-select: none; /* Chrome, Safari, Opera */
      -moz-user-select: none; /* Firefox */
      -ms-user-select: none; /* Internet Explorer/Edge */
      user-select: none; /* 标准浏览器 */
    }
    
    .themeSwitch {
      margin: 1rem 0;
    }
    
  • index.js

    let theme = "";
    
    function switchTheme(model) {
      // 如果没有传入数据,则是切换主题,传入了数据,则是设置主题
      if (model) {
        theme = model;
      } else {
        theme = theme === "light" ? "dark" : "light";
      }
      console.log("switchTheme");
      const text = theme === "light" ? "浅色" : "深色";
      const checked = theme === "light" ? false : true;
      document.documentElement.setAttribute("data-theme", theme);
      document.getElementById("themeTitle").innerText = text;
      document.getElementById("themeSwitch").checked = checked;
      localStorage.setItem("theme", theme);
    }
    
    // 页面加载完成
    window.onload = function () {
      // 获取主题设置
      const theme = localStorage.getItem("theme") || "light";
      switchTheme(theme);
    };
    
  • theme.css

    /* 暗色主题 */
    html[data-theme="dark"] {
      --text-color: #f2f2f2;
      --bg-color: #171717;
    }
    
    /* 默认亮色主题 */
    :root {
      --text-color: #000;
      --bg-color: #f2f2f2;
    }
    
    /* 这个用于处理浏览器设置为暗色模式的情况 */
    @media (prefers-color-scheme: dark) {
      :root {
        --text-color: #2ecc71;
        --bg-color: #34495e;
      }
    }
    
0

评论区