当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 【第七章 响应式设计】(概述)
- 7.1 移动端优先设计原则(上篇)
- 7.1.1 创建移动端菜单(下篇)
- 7.1.2 给视口添加 meta 标签(下篇)
- 7.2 媒体查询(上篇) ✔️
- 7.2.1 深入理解媒体查询的类型(上篇) ✔️
- 7.2.2 页面断点的添加(中篇,待翻译 ⏳)
- 7.2.3 响应式列的添加(下篇)
文章目录
- 7.2 媒体查询 Media queries
- 7.2.1 深入理解媒体查询的类型 Understanding types of media queries
- 1 最小宽度、最大宽度及其他 min-width, max-width, and beyond
- 2 媒体查询中的范围表示法 Range syntax in media queries
- 3 浅色主题与深色主题 Light and dark themes
- 4 媒体类型 Media types
《CSS in Depth》新版封面
译者按
从这一篇开始,我们将进入 CSS 响应式设计的第二个原则——媒体查询的学习。相关内容在第一版的基础上进行了大幅增补,以适应当下媒体查询的最新需要。篇幅较长,拟分为上、中、下三篇分别介绍,本篇为上篇,将带您深入了解媒体查询的具体类型;中篇将介绍媒体查询断点的设置技巧;下篇涉及响应式列的相关知识。让我们步步为营,先搞定上篇的学习——
7.2 媒体查询 Media queries
响应式设计的第二个原则是使用 媒体查询。媒体查询(media queries) 允许某些样式仅在页面满足特定条件时才生效。这样就可以根据屏幕尺寸定制样式。可以先针对小屏设备定义一套样式,再针对中等屏幕设备定义另一套样式,最后针对大屏设备再定义一套样式,这样就能让页面内容呈现多种布局。
媒体查询使用写作 @media
的 @规则 选中符合特定条件的设备。一条简单的媒体查询写法如以下代码所示:
@media (min-width: 560px) {.title > h1 {font-size: 2.25rem;}
}
在最外层的大括号内可以定义任意的样式规则。@media
规则会进行条件检查,只有满足所有条件时,才会将这些样式应用到页面上。本例中浏览器会检查 min-width: 560px;
,即仅当设备的视口宽度大于等于 560px
时,样式类 title
下的一级标题 h1
元素才能设为 2.25rem
的大号字;若视口小于 560px
,则内部规则集都会被忽略。
媒体查询中的规则仍然遵循常规的层叠原理。它们既可以覆盖媒体查询外部的样式规则(根据选择器的优先级或源码顺序等),也可能被这些样式规则覆盖掉。而媒体查询本身不会影响到它里面的选择器优先级。
关于在媒体查询中使用 px 与 em
虽然也可以使用很多其他单位来定义媒体查询,但
px
和em
无疑是最常用的。例如,除了写成上面的@media (min-width: 560px)
,还可以写成@media (min-width: 35em)
。而用rem
则通常与用em
差不多。在媒体查询中,
em
的值基于浏览器的默认字号,也就是关键字medium
(译注:媒介、媒体)通常对应的16px
。但如果用户在浏览器设置中更改了默认字号,em
的含义也会随之改变。这可能对设计而言是个好事,随着默认字号的增加,页面断点的尺寸也会同步增大。但要注意一点:该行为在所有浏览器中并不一致(Safari
就是个突出的反例)。在过去,由于浏览器存在不一致性,开发人员(包括我本人在内)都会推荐在媒体查询中使用相对单位
em
;然而在最近版本的浏览器中,像素单位px
的表现更加一致。因此,在很多情况下我反倒更推荐使用px
;而当我希望断点处的尺寸可以随默认字号同步缩放时,再换回相对单位em
也不迟。
接下来演示几个给页面设置媒体查询的例子。找到样式表中的 .title
样式,并按照代码清单 7.7 中的样式添加媒体查询,让页面标题拥有响应式行为。
代码清单 7.7 给页面标题样式添加断点
.title > h1 {color: #333;text-transform: uppercase;font-size: 1.5rem;margin-block: 0.2em;
}@media (min-width: 560px) { /* 匹配宽度在 560px 及以上的视口 */.title > h1 {font-size: 2.25rem; /* 用更大的字号覆盖移动端的小号字(1.5rem) */}
}
此时,根据视口大小的不同,页面标题就有了两种不同的字号:视口宽度不足 560px
时字号为 1.5rem
;超过 560px
则为 2.25rem
(译注:刚好等于 560px
时也是 2.25rem
)。
通过缩放浏览器窗口就能测出标题的样式:窗口很窄的时候,看到的是适配移动端的小字号;慢慢扩大浏览器窗口,字号也会平滑过渡,因为页面通过 clamp()
(详见代码清单 7.2)事先设置了响应式的字号;而当页面宽度达到 560px
时,标题的字号则会立马变为 2.25rem
。
窗口宽 560px
的这个临界点,就被称为一个 断点(breakpoint)。大多数情况下,整个样式表里的媒体查询只会复用几个为数不多的断点。本章稍后会介绍如何挑选合适的断点。
7.2.1 深入理解媒体查询的类型 Understanding types of media queries
还可以进一步将两个条件用 and
关键字联合起来,组合为 一个 媒体查询:
@media (min-width: 320px) and (max-width: 560px) { ... }
这样的组合式媒体查询仅在设备同时满足这两个条件时才会生效。如果设备只需要满足其中一个条件,可以用逗号分隔,写作:
@media (max-width: 320px), (min-width: 560px) { ... }
上述媒体查询将匹配宽度小于等于 320px
、或者大于等于 560px
的视口。另外,关键字 or
已收入 W3C 媒体查询第四级规范(W3C Media Queries Level 4 specification),与这里的逗号等效。该写法相对较新,仅在最近版本的 Chrome
、Firefox
及 Safari
浏览器中有效。
1 最小宽度、最大宽度及其他 min-width, max-width, and beyond
刚才那段代码中,min-width
用于匹配视口大于特定宽度的设备;max-width
则相反,用于匹配视口小于特定宽度的设备。它们被统称为 媒体特征(media feature)。
min-width
和 max-width
是目前使用最为广泛的媒体特征,但还有一些别的媒体特征可供选用。下面列出了其中的部分写法:
(min-height: 320px)
—— 匹配高度不低于320px
的视口。(max-height: 320px)
—— 匹配高度不超过320px
的视口。(orientation: landscape)
—— 匹配宽度大于高度的视口。(orientation: portrait)
—— 匹配高度大于宽度的视口。(min-resolution: 2dppx)
—— 匹配屏幕分辨率不小于2dppx
(即每个 CSS 像素里包含两个物理像素点)的设备,比如“视网膜”("retina"
)屏慕。(max-resolution: 2dppx)
—— 匹配屏幕分辨率不超过2dppx
的设备。(pointer: coarse)
—— 匹配不具备精确指向方法(precise pointing method,比如鼠标)的设备。通常匹配的是触摸屏设备,因为用户手指无法准确选中太小的按钮;可以用它来放大这些点击目标。(pointer: fine)
—— 匹配具备精确指向方法的设备,例如鼠标。
查看完整的媒体特征列表,详见 MDN 官方文档:https://developer.mozilla.org/en-US/docs/Web/CSS/@media
基于分辨率的媒体查询对于能够渲染更高分辨率的图像或图标的设备屏幕非常有用。这样一来,屏幕分辨率较低的用户在加载较大的图像时就不会浪费带宽,因为他们看不出差异。本章稍后还将进一步介绍响应式图像的相关知识。
提示
媒体查询还可以放在
<link>
标签中。在页面加入<link rel="stylesheet" media="(min-width: 45em)" href="large-screen.css" />
,只有在min-width
处的媒体查询条件被满足时,文件large-screen.css
中的样式才会在页面生效。但要注意,此时无论视口的宽度如何,该样式文件都会被下载。因此该方案旨在更好地组织代码,并不会节省网络流量。
此外,还有个关键点值得注意:在媒体查询中无法访问自定义属性。也就是说,像 @media (min-width: var(--breakpoint))
这样的写法是无效的,因为 var()
的使用场景仅限于在给某个属性(property)的样式声明赋上某个值时使用。
2 媒体查询中的范围表示法 Range syntax in media queries
媒体查询还有一种新的语法,可以使用小于和大于符号。例如,之前的 @media (min-width: 800px)
可以直接写成 @media (width >= 800px)
。此外,还可以为查询提供一组上下边界(upper and lower bound),例如写作 @media (800px < width < 1200px)
,表示仅对宽度介于 800px
到 1200px
之间的视口生效。
该语法较之传统写法有两个明显优势:首先,使用了该语法的媒体查询读起来更加直观,尤其是在定义上下边界时,像 (800px <= width <= 1200px)
的写法比之前冗长的 (min-width: 800px) and (max-width: 1200px)
更容易理解。
而该语法的第二个好处,则是提供了小于等于(<=
)和大于等于(>=
)符号的配置选项。使用传统写法的媒体查询时,假设某个应用场景中同时存在像 max-width: 30em
与 min-width: 30em
这样的两个媒体查询。如果视口宽度恰巧为 30em
,则二者都将生效,从而可能带来一些不符合预期的效果。而使用新的范围表示方法,就能通过 是否使用等号 来准确描述目标范围在对应边界上的包含情况。再来看几个类似的用法:
@media (480px <= width < 1200px) { ... }
@media (800px < height) { ... }
@media (width = 1600px) { ... }
该语法尽管仍然相对较新,但所有主流浏览器的最新版本都对其提供了支持。获取该语法在各版本浏览器中的最新兼容情况,详见:https://caniuse.com/css-media-range-syntax。
3 浅色主题与深色主题 Light and dark themes
此外,您还可以使用媒体查询来检测用户的操作系统是否设置成了深色模式(dark mode)并据此来为页面提供浅色或深色背景,以匹配用户的偏好:
@media (prefers-color-scheme: dark) {:root {--theme-font-color: white;--theme-background: #222;}
}
或者匹配浅色主题来进行设置:
@media (prefers-color-scheme: light) {:root {--theme-font-color: #222;--theme-background: #eee;}
}
我发现,像上述代码这样充分利用自定义属性,不失为更改整个页面样式的一种相对简单的做法,只要能确保在样式表中始终如一地使用自定义属性就行。
实际运用过程中,完成这样的任务肯定不止这两个自定义变量。后续章节将进一步深入探讨颜色变量的管理。
4 媒体类型 Media types
最后一个要介绍的媒体查询配置选项,为 媒体类型(media type)。常见的两种类型为 screen
和 print
。使用 print
媒体查询可以控制打印时的页面布局,这样就能在打印时去掉背景图(为了省墨),或者隐藏不必要的导航栏。毕竟用户打印网页时,通常只想打印主体内容。
要编写仅在打印时生效的样式(即打印样式),需使用查询语句 @media print
。与 min-width
及其他媒体特征一样,该语句不用加小括号。而针对屏幕样式,则使用 @media screen
。
开发 CSS 的时候,通常在事后才会处理打印样式(an afterthought),而且只在确实需要打印时才会考虑;但还是有必要思考用户是否想要打印该网页。为了帮助用户打印出网页,需要采取一些通用步骤。大多数情况下,都需要将基础打印样式放在 @media print {...}
的媒体查询内。
要使用 display: none
来隐藏像导航菜单、页脚这样的次要内容。用户打印网页时,他们绝大多数情况下只关心网页的主体内容。
还可以将整体的字体颜色设置为黑色,并去掉文字后面的背景图片或背景色。大多数情况下,使用通用选择器就能搞定这一切。以下代码使用了 !important
标记,这样就不用担心被后面的样式代码覆盖掉。
@media print {* {color: black !important;background: none !important;}
}
花费一些时间来优化打印样式,对用户来说是一项很不错的服务。如果要开发的网站预计会有很多打印需求(例如食谱类网站),那就应该花更多时间确保所有的样式都能正常打印。
关于《CSS in Depth》(中译本书名《深入解析 CSS》)
第 1 版 | 第 2 版 | |
---|---|---|
读者评分 | 原版:4.7(亚马逊);中文版:9.3(豆瓣) | 原版:5.0(亚马逊);中文版:暂无,待出版 |
出版时间 | 原版:2018 年 3 月;中文版:2020 年 4 月 | 原版:2024 年 7 月;中文版:暂无,待出版 |
原价 | 原版:$44.99;中文版:¥139.00 | 原版:$59.99;中文版:暂无,待出版 |
现价 | 原版:$36.49;中文版:¥52.54 起步 | 原版:$52.09;中文版:暂无,待出版 |
原版国内预订 | 起步价 ¥461.00 | 起步价 ¥750.00 |
本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!
目前已完结的章节(可进入本专栏查看详情,连载期间完全免费):
- 第一章 层叠、优先级与继承(已完结)
- 1.1 层叠
- 1.2 继承
- 1.3 特殊值
- 1.4 简写属性
- 1.5 CSS 渐进式增强技术
- 1.6 本章小结
- 第二章 相对单位(已完结)
- 2.1 相对单位的威力
- 2.2 em 与 rem
- 2.3 告别像素思维
- 2.4 视口的相对单位
- 2.5 无单位的数值与行高
- 2.6 自定义属性
- 2.7 本章小结
- 第三章 文档流与盒模型(已完结)
- 3.1 常规文档流
- 3.2 盒模型
- 3.3 元素的高度
- 3.4 负的外边距
- 3.5 外边距折叠
- 3.6 容器内的元素间距问题
- 3.7 本章小结
- 第四章 Flexbox 布局(已完结)
- 4.1 Flexbox 布局原理
- 4.2 弹性子元素的大小
- 4.3 弹性布局的方向
- 4.4 对齐、间距等细节处
- 4.5 本章小结
- 第五章 网格布局(已完结)
- 5.1 构建基础网格
- 5.2 网格结构剖析 (上)
- 5.2.1 网格线的编号(下)
- 5.2.2 网格与 Flexbox 配合(下)
- 5.3 两种替代语法
- 5.3.1 命名网格线
- 5.3.2 命名网格区域
- 5.4 显式网格与隐式网格(上)
- 5.4.1 添加变化 (中)
- 5.4.2 让网格元素填满网格轨道(下)
- 5.5 子网格(全新增补内容)
- 5.6 对齐相关的属性
- 5.7 本章小结
- 第六章 定位与堆叠上下文(已完结)
- 6.1 固定定位
- 6.1.1 创建一个固定定位的模态对话框
- 6.1.2 在模态对话框打开时防止屏幕滚动
- 6.1.3 控制定位元素的大小
- 6.2 绝对定位
- 6.2.1 关闭按钮的绝对定位
- 6.2.2 伪元素的定位问题
- 6.3 相对定位
- 6.3.1 创建下拉菜单(上)
- 6.3.2 创建 CSS 三角形(下)
- 6.4 堆叠上下文与 z-index
- 6.4.1 理解渲染过程与堆叠顺序(上)
- 6.4.2 用 z-index 控制堆叠顺序(上)
- 6.4.3 深入理解堆叠上下文(下)
- 6.5 粘性定位
- 6.6 本章小结