学习 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 语法中,定义待应用样式的媒体
/* 适配所有媒体 */ @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>
在媒体查询中,有这么一些注意事项
- 媒体类型是必要条件,但 all 可以省略
- 媒体特性是次要条件,可以不定义。如果定义必须用小括号括起来且只能定义一个
- 媒体类型、媒体特性,他们彼此之间需使用 逻辑运算符 关联, 即“与”、“或”、“非”
逻辑运算符
当创建一个取决于多个条件的复杂媒体查询时, 这就是需要 逻辑运算符 的配合使用。具体如下:
-
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 |
有了这些媒体查询单位,相比 JS 的 window.innerWidth
和 window.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
关注匹配的是父容器元素尺寸
转载自:https://juejin.cn/post/7281601361983864832