学习 CSS At Rules 媒体查询 — @media

前言

之前写过一篇《学习 CSS At Rules 容器查询 --- @container》 文章,其中提到了 容器查询 的蛮生兄弟 媒体查询,两兄弟都同属于 CSS At-Rules 大家庭。但论两兄弟的"出生",那 媒体查询 可是老大哥了。所以这篇文章算是补发,也是带大家认识下这位老大哥 媒体查询 @media

在前端开发中,我们往往需要一套网页同时支持适配 不同分辨率屏幕WEB端 (PC端和移动端),而我们将同时能够自适配不同分辨率屏幕的网页称为响应式网页。在最初方案中我们通过 JS 监听浏览器视区宽度变化来实现响应式布局 (onresize) ,但当我们监听浏览器视区宽度 resize,卸载当前样式文件,然后加载新的样式文件。以此往复网页不断卸载样式、加载新样式,此时我们就会看到明显网页抖动。可见 JS 来触发响应式布局,并不是一种好的方式。

所以为了实现平滑、顺畅、无抖动的响应式布局,CSS3 推出了 媒体查询 @media

媒体查询

简介

媒体查询 可以让我们根据设备显示器的特性(如视口宽度、屏幕比例、设备方向:横向或纵向)为其应用特定的 CSS 样式,媒体查询由媒体类型或检测媒体特性的条件表达式组成。

  • 媒体类型: 媒体类型描述了给定设备的一般类别

    媒体类型 介绍说明 状态
    all 所有媒体 默认值(可省略)
    screen 屏幕媒体,包括电脑、手机、平板 /
    print 打印媒体,如打印机 /
    ...
  • 媒体特性: 媒体功能描述了给定的的输出设备或环境的特定特征

    媒体特性 介绍说明
    width 视区宽度(可加max min前缀)
    height 视区高度(可加max min前缀)
    device-width 设备屏幕分辨率的宽度(可加max min前缀)
    orientation portrait竖屏/landscape横屏
    ...

语法定义

  • @media 语法中,定义待应用样式的媒体

    css 复制代码
      /* 适配所有媒体 */
      @media { /* css code */ }
      @media all { /* css code */ }
      
      /* 仅适配打印媒体 */
      @media print {
        /* css code */ 
      }
        
      /* 仅适配手机设备 */
      @media (max-width: 768px) {
        /* css code */ 
      }
        
      /* 仅适配竖屏设备 */
      @media (orientation: portrait) {
        /* css code */ 
      }
        
  • style 元素的 media 属性中,定义待应用样式的媒体

    html 复制代码
      <!-- 适配所有媒体 -->
      <style type="text/css"></style>
      
      <!-- 仅适配打印媒体 -->
      <style type="text/css" media="print"></style>
      
      <!-- 仅适配手机设备 -->
      <style type="text/css" media="(max-width: 768px)"></style>
        
      <!-- 仅适配竖屏设备 -->
      <style type="text/css" media="(orientation: portrait)"></style>
      
  • @import url语法中,定义待应用样式的媒体

    css 复制代码
      /* 适配所有媒体 */
      @import url('./index.css');
      
      /* 仅适配打印媒体 */
      @import url('./index.css') print;
       
      /* 仅适配手机设备 */
      @import url('./index.css') (max-width: 768px);
       
      /* 仅适配竖屏设备 */
      @import url('./index.css') (orientation: portrait);
       
  • 在 <link > 元素的 media 属性中,定义了待应用链接资源(通常是 CSS)的媒体

    html 复制代码
      <!-- 适配所有媒体 -->
      <link rel="stylesheet" href="./index.css">
      
      <!-- 仅适配打印媒体 -->
      <link rel="stylesheet" href="./index.css" media="print">
       
      <!-- 仅适配手机设备 -->
      <link rel="stylesheet" href="./index.css" media="(max-width: 768px)">
       
      <!-- 仅适配竖屏设备 -->
      <link rel="stylesheet" href="./index.css" media="(orientation: portrait)">
        
  • 在 <picture > 之内 <source > 元素的 media 属性中,定义不同的显示/设备场景提供图像版本

    html 复制代码
      <picture>
       <source srcset="./lower.jpg" media="(max-width: 768px)" />
       <source srcset="./higher.jpg" media="(min-width: 960px)" />
       <img src="./normal.png" alt="photo" />
      </picture>

在媒体查询中,有这么一些注意事项

  1. 媒体类型是必要条件,但 all 可以省略
  2. 媒体特性是次要条件,可以不定义。如果定义必须用小括号括起来且只能定义一个
  3. 媒体类型、媒体特性,他们彼此之间需使用 逻辑运算符 关联, 即"与"、"或"、"非"

逻辑运算符

当创建一个取决于多个条件的复杂媒体查询时, 这就是需要 逻辑运算符 的配合使用。具体如下:

  • and: 将媒体功能与媒体类型或其他媒体功能组合一起, 用户设备完全匹配时应用样式,例如

    css 复制代码
      /* 仅适配横向的手机设备 */
      @media (max-width: 768px) and (orientation: landscape) { 
        /* css code */
      } 
      
  • ,: 用户设备与各种媒体类型或特性中任何一种匹配时,可以用逗号分隔来应用样式,例如

    css 复制代码
      /* 适配用户设备的最小宽度为 768px 或 纵向模式的屏幕设备 */
      @media (min-width: 768px), screen and (orientation: portrait) {
        /* css code */
      } 
      
  • not: 会反转整个媒体查询的含义。它只会否定要应用的特定媒体查询。例如

    css 复制代码
      /* 下面两者等价 */
      @media not all and (monochrome) {}
      @media not (all and (monochrome)) {}
      
      /* 下面两者等价 */
      @media not screen and (color), print and (color) {}
      @media (not (screen and (color))), print and (color) {}
      
  • only: 防止不支持带有媒体功能的媒体查询的旧版浏览器应用给定的样式。对现代浏览器没有影响

    css 复制代码
      /* 适配屏幕媒体 */
      @media only screen {}

媒体查询的应用

例如常见的 Bootstrap 响应式栅格系统设计

css 复制代码
/* Small devices (landscape phones, 576px and up) */
@media (min-width: 576px) { ... }

/* Medium devices (tablets, 768px and up) */
@media (min-width: 768px) { ... }

/* Large devices (desktops, 992px and up) */ */
@media (min-width: 992px) { ... }

/* X-Large devices (large desktops, 1200px and up) */
@media (min-width: 1200px) { ... }

/* XX-Large devices (larger desktops, 1400px and up) */
@media (min-width: 1400px) { ... }

媒体查询单位

单位 说明
vw 表示浏览器视口宽度的 1%
vh 表示浏览器视口高度的 1%
vmin 表示浏览器视口尺寸较小的值,如果视口尺寸是 1280px * 960px,则 100vmin 对应的是尺寸较小的宽度 960px
vmax 表示浏览器视口尺寸较大的值,如果视口尺寸是 1280px * 960px,则 100vmax 对应的是尺寸较大的宽度 1280px

有了这些媒体查询单位,相比 JSwindow.innerWidthwindow.innerHeight 的获取和设置,在 CSS 中的适配更加平滑和便捷。

相关 JS API

JavaScript 中可以使用 Window.matchMedia() 方法根据媒体查询进行测试。还可以使用 MediaQueryList.addListener() 在查询状态发生变化时收到通知。借助此功能,你的应用动态响应设备配置,方向或状态的更改。

  • matchMedia() 方法返回一个新的 MediaQueryList 对象,用于判定 document 是否匹配媒体查询,或者监控 document 来判定它匹配了或者停止匹配了此媒体查询。

    js 复制代码
      window.matchMedia('(min-width: 600px)')
      
      // result:
      //  {
      //    matches: true,
      //    media: "(min-width: 600px)",
      //    onchange: null 
      //  }
  • addListener() 方法向 MediaQueryListener添加一个侦听器,该侦听器将运行自定义回调函数以响应媒体查询状态的更改。

    js 复制代码
      const mql = window.matchMedia("(min-width: 600px)")
    
      mql.addListener(function(e) {
        if (e.matches) {
          /* 视口宽度 >= 600像素 */
        } else {    
          /* 视口宽度 < 600像素 */
        }
      })

与容器查询区别 ?

  • 媒体查询 @media 关注匹配的是浏览器窗口尺寸
  • 容器查询 @container 关注匹配的是父容器元素尺寸

关于 容器查询 更多信息,请看这篇

相关推荐
Mr_Mao3 小时前
Naive Ultra:中后台 Naive UI 增强组件库
前端
前端小趴菜055 小时前
React-React.memo-props比较机制
前端·javascript·react.js
摸鱼仙人~6 小时前
styled-components:现代React样式解决方案
前端·react.js·前端框架
sasaraku.6 小时前
serviceWorker缓存资源
前端
RadiumAg7 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo7 小时前
ES6笔记2
开发语言·前端·javascript
yanlele7 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
中微子9 小时前
React状态管理最佳实践
前端
烛阴9 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子9 小时前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端