媒体查询

页面在不同大小的设备上拥有不同的布局和样式,以便充分适配设备。

页面仅在屏幕上显示,且页面的宽度不超过 600px 时,让侧边栏隐藏:

  1. @media only screen and (max-width: 600px) {
  2. .sidebar {
  3. display: none;
  4. }
  5. }

媒体查询表达式包含两类查询条件:

  • 媒体类型

all(所有设备)、print(打印设备)、speech(屏幕阅读器设备)、screen(除屏幕阅读器和打印设备以外的所有设备)。没有媒体类型,默认取 all。

  • 媒体特征表达式

表达式中包含的是在该设备上验证的媒体特征,如是否超过希望的最大值,是否为某种指定设备,是否是高清屏幕等。如果媒体查询返回为真,特征表达式返回为 true,说明当前设备展现页面的条件符合预期。

媒体查询不仅可以写在样式表中,还可以写在 link 标签中:

  1. <link rel="stylesheet" media="only screen and (max-width: 600px)"
  2. type="text/css" href="example.css">

处于性能的考虑,不会采用在外链上增加媒体查询来加载针对性样式,因为这样会增加额外的请求成本。

媒体查询的逻辑

媒体查询中的逻辑就相当于或、与、非的操作。

and(与):将多个媒体类型联系起来,只有当它们全部为真时,媒体查询才算成立,改媒体查询的样式才会生效。

  1. @media (min-width: 320px) and (orientation: landscape) {
  2. .sidebar {
  3. display: none;
  4. }
  5. }

or(或):使用逗号(,)分隔符可以将媒体查询隔离开,如果查询条件中任意一个查询返回 true,则改样式生效。

  1. @media (min-width: 320px), all and (orientation: landscape) {
  2. .sidebar {
  3. display: none;
  4. }
  5. }

not(非):使用 not 关键字就是对当前的媒体查询条件取反操作。
当 not 与 and 同时出现时,not 依然是对整个样式生效,而不是只对最近的条件生效。
当 not 与 逗号分隔的多个媒体查询同时存在时,此时 not 只对它所在的那个媒体查询生效。

媒体查询的策略

顺序

为了兼容不同的设备,通常会提供不同的媒体查询。相同的代码不同的顺序排列就会导致不同的结果。进行匹配媒体查询时会从后往前进行匹配,当匹配成功时,不再向前进行匹配。

max-width 与 min-width

根据页面由窄至宽划分(小于 320px、320px 至 1024px、1024px 以上),提供三种布局样式。

移动优先的方式,优先考虑最小屏幕的设备。

  1. /* 当设备宽度还不足 320px 的移动设备 */
  2. html {
  3. }
  4. /* 宽度为 320px 至 1024px */
  5. @media (min-width: 320px) {
  6. }
  7. /* 宽度为 1024px 以上 */
  8. @media (min-width: 1024px) {
  9. }

桌面优先的方式,优先考虑最大屏幕的设备。

  1. /* 不设定宽度的情况 */
  2. html {
  3. }
  4. /* 当页面不超过 1024px 时 */
  5. @media (max-width: 1024px) {
  6. }
  7. /* 当页面宽度不超过 320px 时 */
  8. @media (max-width: 320px) {
  9. }

device-width 与 width

device-width(设备视口宽度)是设备维度的属性,使用它意味着对设备进行编程。如今设备的宽度是各式各样的,不能使用 device-width 作为衡量尺度,而是使用width(当前页面宽度)。媒体查询布局断点设置的依据是是否让页面看上去更好。

伸缩布局

让子元素充分利用父元素的空间,以便更有效地排列、对齐、平均分布等。简单来说,伸缩布局让水平居中、垂直居中和元素对齐变得更容易。

相对单位

覆盖浏览器默认字体大小

在设置 body 字体大小时采用的最佳实践通常是:

  1. body {
  2. font-size : 100%;
  3. }

但通常我们仍然使用绝对字体,它能覆盖用户的默认设置,尽可能的还原设计,避免字体大小不可控而打乱布局的麻烦。

编写媒体查询的噩梦

继续以 480px 的布局断点为例,假使用为移动端和桌面端的不同元素准备不同大小的字体,需要在每组媒体查询中重写每一类元素字体的大小。

  1. /* 移动端(视口小于 480px) */
  2. body {
  3. font-size : 12px;
  4. }
  5. h1 {
  6. font-size: 24px;
  7. }
  8. h2 {
  9. font-size: 18px;
  10. }
  11. /* 视口大于 480px */
  12. @media (min-width: 480px) {
  13. body {
  14. font-size: 16px;
  15. }
  16. h1 {
  17. font-size: 32px;
  18. }
  19. h2 {
  20. font-size: 24px;
  21. }
  22. }

相对单位 em

相对于最近父元素设置字体大小。
作为字体单位来说,% 与 em 是等价的,但作为容器的尺寸单位而言两者执行的规则不同。

子元素字体大小 em 值 = 子元素字体大小 px 值 / 父元素字体大小 px 值。

因此一种使用 em 单位的实践是:先将 body 字体大小设为默认的 62.5%

  1. body {
  2. font-size:62.5%;
  3. }

这样一来,任何 em 单位想还原为 px 单位,只要将 em 单位数组放大十倍就好了。此时 1em 等于 10px。

相对单位 rem

始终相对于根元素 html,即使该元素不是根元素的直接子元素。
元素字体大小 rem 值 = 元素字体大小 px 值 / html元素字体大小 px 值。

如何使用这几种单位

设计中需要绝对单位 px,设计稿是以绝对单位绘制,em 和 rem 都是以 px 作为中介换算的。
首先设置浏览器默认字体大小为 16px。

  1. html {
  2. font-size : 16px;
  3. }
  4. body {
  5. font-size: 1em; /* 100% 亦可 */
  6. }

最佳实践是将页面分为各个模块分而治之。

  • 将页面根据文字特征分为几个模块:导航、标题、正文等。
  • 每个模块最外层元素,如 header、article,都有自己的字体大小。改字体大小以根元素的字体大小为基准,用 rem 取值。 ```css html { font-size : 16px; }

body { font-size: 1em; / 100% 亦可 / }

nav, header{ font-size: 1.2rem; }

article { font-size: .74rem; }

  1. 为了确保字体大小更精确使用 rem
  2. - 模块最外层元素的字体大小是作为该元素内部大小的基准。当页面字体小时,只需要调整根元素 html 的字体大小就可以了。当需要调整一个模块所有的字体大小时,只需要调整这个模块基准文字大小,也就是最外层字体大小即可。
  3. <a name="0933pg"></a>
  4. ### 其他相对单位
  5. - vh(视口高度):1vh 等于 1% 当前浏览器视口高度。
  6. - vw(视口宽度):1vw 等于 1% 当前浏览器视口宽度。
  7. - vmin :视口高度取最小值。
  8. - vmax :视口高度取最大值。
  9. <a name="7vczge"></a>
  10. ## 标题布局
  11. [Bron 站点](https://www.borngroup.com/) 这样大是一个正在流行的设计趋势。
  12. <a name="9cu0ek"></a>
  13. ## 响应式文字
  14. ```css
  15. header {
  16. font-size: 2.5rem; /* 导航栏基准字体 40px */
  17. }
  18. @media all and (max-width: 480px) {
  19. header {
  20. font-size: 1.125rem; /* 导航栏基准字体 18px */
  21. }
  22. }

先给你的模块设定字号(单位 rem),改字号为模块内所有文字的基准。再给媒体查询断点设置不同的字号(单位 em)

对于阅读体验的考虑,我们不希望文章的每行长度太长或者太短,也不希望两行之间的距离太过于紧密或者疏忽。字体、行高、段落之间的间距等需要恰当搭配才能保证排版的美观。

参考

【1】高性能响应式 Web 开发实战 @ 李光毅