由于移动设备(手机,平板电脑等)的流行,越来越多的网站开始使用响应式设计来设计网站。其核心归结为一句话就是,在不同设备上自动适配不同的内容(如下图所示)。而我们为了让网站样式能够支持响应式设计,其中最关键的因素就是 CSS 中的 media queries,media queries 允许我们定义在不同内容和尺寸的设备上的样式。 图片来源:维基百科

如何使用 Media Queries

上面我们说到 media queries 可以帮助我们定义不同尺寸设备上的内容显示,那么我们只需要在我们现有的样式中增加针对特定内容在特定设备或者尺寸的样式即可,例如:

div.container {  
  width: 100%;
}
@media screen only and (min-width: 480px) {
  div.container {
    width: 40%;
  }
}

上面的例子中,我们的定义了只在屏幕(screen only)宽度最小值大于 480px 的时候将宽度从 100% 变成 40%,而这个480px就是我们通常所说的 Break Point 。其中关于更多的 media queries 的属性可以去参考下 Mozilla 的文档1。 不过这个时候大家可能会有所疑问,这里的 480px 真的会预期一样么? image

Break Point 介绍

首先我们要知道,上面的例子中 media queries 针对的是内容的宽度,而通常一个父级元素的宽度是由它包含的子类元素确定的,当然我们也可以制定一个绝对值。当元素的宽度超过屏幕的宽度时我们的内容就会出现水平可滚动的效果,类似下面这种效果:

Parent Width 280px
Child width 380px



同样高度也会出现类似的情况,但是一般从网页交互和用户体验的角度来考虑,我们不会对特定的高度做限定,因为网页的内容是自上而下滚动的,高度可以自由延展。这是可能会想那我定义个 max-width:280px 不就好了嘛。是的,这确实解决了我们的问题,但是随之而来的问题是如果用户改变了他的浏览器的默认字体大小怎么办?在我的上一篇博客中「font-size 的常用长度单位」我介绍了 CSS 中的几种常见单位,其中的单位对于我们做响应式设计中依然至关重要,那具体是怎么表现的呢?

See the Pen breakpoint by xeodou (@xeodou) on CodePen.

在这个例子中当宽度变化时,div 标签的背景透明度将发生改变,我们将从不同维度来看break point 的变化:

  • 更改系统字体大小
  • 缩放屏幕大小
  • 不同浏览器

注:我使用的浏览器版本为 Chrome Version 55.0.2883.95 (64-bit) 和 Safari Version 10.0.2 (12602.3.12.0.1)

正常状态
  • Chrome Chrome 我们可以看到在我拖拽的过程中,随着宽度的缩小三个div标签的背景颜色同时变化,那是因为在不改变系统字体大小并且指定html { font-size: 62.5%; }的时候,在 Chrome 下 480px = 30em = 30rem

  • Safari Safari 我们可以看到其显示的效果和 Chrome 下却有所不同,在宽度小于480px=30em时红色块和绿色块颜色透明度减小,而当宽度小于300px=30rem时蓝色块才开始变化。

更改字体大小
  • Chrome

Chrome 下可以通过设置>高级设置>网页内容 更改字体大小,我们将字体大小从Medium更改到Large,这时 Chrome 的页面内容正常情况下1rem=20px,而当加载html { font-size:62.5%; }后字体大小变成1rem=12.5px
Chrome 1rem=12.5px 我们可以看到其中字体明显变大了,这时候红色色块依然在宽度小于480px的时候颜色变化,而绿色和蓝色色块都同时在30rem=30em=600px时候颜色发生变化。

  • Safari

Safari 下通过点开视图(View)菜单后按住Option键后点击放大或者缩小页面字体2。这时我们将字体像 Chrome 下一样增加字体大小后1rem=19.2px,而当加载html { font-size:62.5%; }后字体大小变成1rem=12px
Safari 文字大小和 Chrome 下一样都明显被放大了,而这时候红色色块也一样在宽度小于480px的时候改变了颜色,而绿色色块在宽度小于30em=12*1.6*30px=576px时候改变了颜色,蓝色块在宽度小于30rem=12*30px的时候颜色发生变化。

定义 Break Point

从上面的这几个例子我们可以看到,就算在同一个设备不同的浏览器下不同的单位也会有不同的表现,虽然px在不同的浏览器甚至是不同的设备中的表现都是一样的,但是当用户希望改变页面的展示形式(字体大小)或者在一个不同的设备上时,他所希望的就是他浏览的网页随着这种改变而改变,所以我们不应该选取px这种非响应式的单位,而且不同浏览器下rem的定义不一致导致我们很难对最终的宽度很有个预测,因此建议选取em做为单位。如果我们在使用 SASS 这种预编译 CSS 时,我们可以使用类似 sass-mq 这种工具库去方便使用各种 media queries,如:

$mq-breakpoints: (
  mobile:  20em,
  tablet:  46.24em,
  desktop: 61.25em,
  wide:    81.25em
);
@import 'mq';
.foo {
  @include mq($from: mobile, $until: tablet) {
    background: red;
  }
  @include mq($from: tablet) {
    background: green;
  }
}

参考链接: