MediaQueryList

  • 定义

包含一个布尔值matches和字符串media的对象:

{
  matches: true,
    media: "(600px < width < 2000px)",
    onchange: null
}
  • 说明
    • matches:一个布尔值,如果当前 document 与媒体查询列表相匹配,则返回 true,否则返回 false。
    • media:代表序列化的媒体查询的字符串。
    • onchange:当其媒体查询的求值结果发生变化时,改函数将会被调用(需要使用addEventListener或赋值绑定)。

media 属性

  • 定义

HTMLMetaElement.media属性允许为theme-color元数据指定媒体。

theme-color属性允许在支持此属性的浏览器和操作系统中设置浏览器工具栏或 UI 的颜色。media属性允许为不同的media值设置不同的主题颜色。

  • 用法

为暗色模式设置主题色

const meta = document.createElement("meta");
meta.name = "theme-color";
meta.content = "#3c790a";
meta.media = "(prefers-color-scheme: dark)";
document.head.appendChild(meta);

以上示例创建一个新的<meta>元素,其name属性设置为theme-colorcontent属性设置为#3c790amedia属性设置为prefers-color-scheme: dark,并把元素附加到文档<head>上。当用户在操作系统中指定暗色模式时,可以使用media属性设置不同的theme-color。最后会转换成这样的元素:

<meta
  name="theme-color"
  content="#3c790a"
  media="(prefers-color-scheme: dark)"
/>
  • 示例
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- 设置基于系统主题的初始颜色 -->
    <meta
      name="theme-color"
      content="#ffffff"
      media="(prefers-color-scheme: light)"
    />
    <meta
      name="theme-color"
      content="#3c790a"
      media="(prefers-color-scheme: dark)"
    />

    <title>Dynamic Theme Color</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100vh;
      }
      .btn-toggle-theme {
        padding: 10px 20px;
        margin-top: 20px;
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <h1>Dynamic Theme Color Example</h1>
    <button class="btn-toggle-theme" onclick="toggleTheme()">
      Toggle Theme
    </button>

    <script>
      // 获取当前系统主题并应用
      function setThemeColor() {
        const isDarkMode = window.matchMedia(
          "(prefers-color-scheme: dark)"
        ).matches;
        const themeColorMetaTag = document.querySelector(
          'meta[name="theme-color"]'
        );
        themeColorMetaTag.setAttribute(
          "content",
          isDarkMode ? "#3c790a" : "#ffffff"
        );
        document.body.style.backgroundColor = isDarkMode
          ? "#3c790a"
          : "#ffffff";
        document.body.style.color = isDarkMode ? "#ffffff" : "#000000";
      }

      // 监听系统主题的变化
      window
        .matchMedia("(prefers-color-scheme: dark)")
        .addEventListener("change", setThemeColor);

      // 切换主题手动更新颜色
      function toggleTheme() {
        const currentColor = document.body.style.backgroundColor;
        const newColor =
          currentColor === "rgb(60, 121, 10)" ? "#ffffff" : "#3c790a";
        const themeColorMetaTag = document.querySelector(
          'meta[name="theme-color"]'
        );
        themeColorMetaTag.setAttribute("content", newColor);
        document.body.style.backgroundColor = newColor;
        document.body.style.color =
          newColor === "#ffffff" ? "#000000" : "#ffffff";
      }

      // 初始化主题颜色
      setThemeColor();
    </script>
  </body>
</html>

点击按钮可实现背景和文字颜色的切换。

window.matchMedia()

  • 定义

matchMedia()方法返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。返回的MediaQueryList可被用于判定 Document 是否匹配媒体查询,或者监控一个document来判定它匹配了或者停止匹配了此媒体查询。

  • 参数
    • mediaQueryString:一个被用于媒体查询解析的字符串。
  • 示例
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <span class="mq-value"></span>
    <script>
      let mql = window.matchMedia("(max-width: 600px)");
      document.querySelector(".mq-value").innerText = mql.matches;
    </script>
  </body>
</html>

mediaQueryString 规则

针对媒体类型

  • 针对打印机
@media print {
  /* … */
}
  • 针对屏幕和打印设备
@media screen, print {
  /* … */
}

针对媒体功能

  • 鼠标悬停在元素之上
@media (hover: hover) {
  /* … */
}
  • 横向或纵向
@media print and (orientation: portrait) {
  /* … */
}
  • 最大宽度
@media (max-width: 1250px) {
  /* … */
}

或者可以写成这样

@media (width <= 1250px) {
  /* … */
}
  • <>的运用
@media (min-width: 30em) and (max-width: 50em) {
  /* … */
}

@media (30em <= width <= 50em) {
  /* … */
}

上面这两个规则等效(需要区别于 JS 的条件判断)

  • 任何具有彩色屏幕的设备
@media (color) {
  /* … */
}

创建复杂的媒体查询

  • 宽度至少为 30 em 的横向设备上
@media (min-width: 30em) and (orientation: landscape) {
  /* … */
}

类似的将设备限制为屏幕:

@media screen and (min-width: 30em) and (orientation: landscape) {
  /* … */
}

:::info
orientation 包含两个属性:landscape(横向)、portrait(纵向)

:::

  • 设备高度为 680px 或更高,或者浏览器视口处于纵向模式(视口高度大于视口宽度)
@media (min-height: 680px), screen and (orientation: portrait) {
  /* … */
}

:::info
逗号分隔查询列表,表示进行多个查询匹配

:::

  • 除印刷媒体之外
@media not print {
  /* … */
}
  • not只对后面紧接的媒体查询生效,例如
@media not screen and (color), print and (color) {
  /* … */
}

等效于:

@media (not (screen and (color))), print and (color) {
  /* … */
}