Skip to content

响应式设计

响应式网页设计(responsive web design,RWD),RWD 指的是允许 Web 页面适应不同屏幕宽度因素等,进行布局和外观的调整的一系列实践。

响应式 Web 设计不是单独的技术,它是描述 Web 设计的一种方式、或者是一组最佳实践的一个词,它是用来建立可以响应查看内容的设备的样式的一个词。

媒体查询

媒体查询基础

css
@media 媒体类型 and (媒体特征规则) {
  /* CSS rules go here */
}

它由以下部分组成:

  • 一个媒体类型,告诉浏览器这段代码是用在什么类型的媒体上的(例如印刷品或者屏幕);
  • 一个媒体特征规则,是一个被包含的 CSS 生效所需的规则或者测试;
  • 一组 CSS 规则,会在测试通过且媒体类型正确的时候应用。

媒体类型

你可以指定的媒体类型为:

  • all,所有设备
  • print,打印机设备
  • screen,屏幕设备
  • speech,语音识别设备

媒体类型是可选的,如果你没有在媒体查询中指示一个媒体类型的话,那么媒体查询默认会设为用于全部媒体类型。

媒体特征规则

当屏幕宽度正好等于 600px 时触发

css
@media screen and (width: 600px) {
  body {
    color: red;
  }
}

当屏幕宽度至少有 800px 时触发(大于等于 800px)

css
@media screen and (min-width: 800px) {
  .container {
    margin: 1em 2em;
  }
}

当屏幕宽度最大为 400px 时触发(小于等于 400px)

css
@media screen and (max-width: 400px) {
  body {
    color: blue;
  }
}

分辨率(dpi)

当屏幕的分辨率大于 192dpi(dpi 表示一英寸 192 个点,192dpi 是苹果视网膜屏幕的 dpi,以此当作一个参考值) 时触发:

css
@media (min-resolution: 192dpi) {
  body {
    color: blue;
  }
}

朝向

设备处于横放时触发

css
@media (orientation: landscape) {
  body {
    color: rebeccapurple;
  }
}

设备处于竖放时触发

css
@media (orientation: portrait) {
  body {
    color: rebeccapurple;
  }
}

有光标的设备

用户使用有光标的设备时触发:

css
@media (hover: hover) {
  body {
    color: rebeccapurple;
  }
}

媒体特征条件之间的逻辑

使用 and 表示与

css
@media screen and (min-width: 400px) and (orientation: landscape) {
  body {
    color: blue;
  }
}

使用逗号表示或

css
@media screen and (min-width: 400px), screen and (orientation: landscape) {
  body {
    color: blue;
  }
}

使用 not 表示非,直接反转了整个媒体查询的含义。因而在下面的例子中,文本只会在朝向为竖着的时候变成蓝色。

css
@media not all and (orientation: landscape) {
  body {
    color: blue;
  }
}

断点

引入媒体查询的点就叫做断点。

css
@media screen (min-width: 400px) {}

比如这个媒体查询的断点为 400px

如何确定断点?

  • (不推荐)根据某些具体的设备决定,如:iphone\ipad 竖屏\ipad 横屏\macbook
  • (较推荐)将类似的设备分类而决定,如:手机\平板横屏\平板竖屏\笔记本
  • (推荐)根据你的页面布局决定断点,如:对于桌面优先开发,逐渐缩小屏幕宽度,直到布局出现问题,此处便是断点的位置

移动优先?桌面优先?

泛泛地说,你可以采用两种方式实现响应式设计。你可以从桌面或者最宽的视图开始,然后随着视口变得越来越小,加上断点,把物件挪开;你也可以从最小的视图开始,随着视口变得越来越大,增添布局内容。第二种方式被叫做移动优先的响应式设计,很多时候是最值得仿效的做法。

用在最小的那个设备上的视图很多时候都是一个简单的单列内容,很像正常文本流显示的那样。这意味着,你很可能不需要为小设备做多少布局设计,合适地安排下你的源代码,默认情况下你就可以得到可读的布局。

主要考虑以下几点:

  • 用户主要在移动端还是桌面端
  • 客户一般更喜欢桌面端的网页原型
  • 移动端布局简单,开发迅速

真的需要媒体查询吗?

弹性盒、网格和多栏布局都给了你建立可伸缩的甚至是响应式组件的方式,而不需要媒体查询。这些布局方式能否在不加入媒体查询的时候实现你想要的设计,总是值得考虑的一件事。

例如,你可能想要一组卡片,至少为二百像素宽,并在主文章里尽可能多地放下这些二百像素的卡片。这可以用网格布局实现,而完全不使用媒体查询。

css
grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr));

响应式布局

最初,只能通过浮动实现网格,解决响应式布局问题:

  • 浮动网格(早期时候使用)

后来出现了现代布局技术:

  • 多列布局
  • 弹性盒子
  • 网格布局

响应式图像

最简单的响应式图像处理:

css
img {
  max-width: 100%;
}

max-width 可以限制图像的最大宽度,结合百分比属性值可以实现响应式图像,但这种方法有以下弊端:

  • 图像有可能会显示得比它的原始尺寸小很多,以至于浪费带宽
  • 有时候,你可能不想在移动端和桌面端有相同的图像宽高比例

后来的响应式图像,使用 <picture> 元素和 <img> 的 srcset 和 sizes 特性,很好地解决了这两个问题。HTML 中的响应式图像分为以下三种:

  • DRP(设备像素比)越大,分辨率越大
  • 图像尺寸越大,分辨率越大
  • 美术风格:对于小屏设备,图像需要进行裁剪,从而突出图像内容主体

CSS 中也可以通过媒体查询实现响应式图像

响应式排版

响应式排版,是指实现响应式的字体。

例如,你可以通过媒体查询,在大屏幕上显示字体更大的标题,在小屏幕上显示较小的标题

或者,可以通过视口单位(vw)实现响应式排版:

css
h1 {
  font-size: 6vw;
}

但是这样会产生问题,因为文本总是随着视口的大小改变大小,用户失去了缩放任何使用 vw 单位的文本的能力。当视口过窄时,会出现标题比正文小的情况。永远都不要只用 viewport 单位设定文本

css
h1 {
  font-size: calc(1.5rem + 3vw);
}

以上是解决办法。使用了 calc(),如果你将 vw 单位加到了使用固定大小(例如 em 或者 rem)的值,那么文本仍然是可放缩的。

视口元标签

html
<meta name="viewport" content="width=device-width,initial-scale=1" />

这个元标签告诉移动端浏览器:

  • width:可视区域的宽度为设备的宽度。
  • intial-scale:页面首次被显示是可视区域的缩放级别,取值 1.0 则页面按实际尺寸显示,无任何缩放

元标签还可以设置以下值:

  • minimum-scale:设定最小缩放级别。
  • maximum-scale:设定最大缩放级别。
  • user-scalable:如果设为 no 的话阻止缩放。

你应该避免使用 minimum-scale、maximum-scale,尤其是将 user-scalable 设为 no。用户应该有权力尽可能大或小地进行缩放,阻止这种做法会引起访问性问题。

为何需要 width=device-width?因为移动端浏览器倾向于在它们的视口宽度上说谎。原来 iPhone 发布以后,人们开始在小的手机屏幕上阅览网页,而大多数站点未对移动端做优化的缘故。移动端浏览器因此会把视口宽度设为 960 像素。通过设定 width=device-width,你用设备的实际宽度覆写了苹果默认的 width=960px,然后你的媒介查询也会像预期那样生效。

基于 MIT 许可发布