likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 20

学习 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前缀)
    orientationportrait竖屏/landscape横屏
    ...

语法定义

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

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

      <!-- 适配所有媒体 -->
      <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语法中,定义待应用样式的媒体

      /* 适配所有媒体 */
      @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)的媒体

      <!-- 适配所有媒体 -->
      <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 属性中,定义不同的显示/设备场景提供图像版本

      <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: 将媒体功能与媒体类型或其他媒体功能组合一起, 用户设备完全匹配时应用样式,例如

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

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

      /* 下面两者等价 */
      @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: 防止不支持带有媒体功能的媒体查询的旧版浏览器应用给定的样式。对现代浏览器没有影响

      /* 适配屏幕媒体 */
      @media only screen {}
    

媒体查询的应用

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

/* 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 来判定它匹配了或者停止匹配了此媒体查询。

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

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

与容器查询区别 ?

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