Skip to content

响应式设计

如今我们随时随地都能上网。
上班用台式计算机上网,回家躺在床上用平板上网,在客厅里甚至还可以用电视屏幕上网,更不要说随身携带的智能手机了。
从未有任何一样东西像承载了HTML、CSS和JavaScript的Web平台那样,成为了一个如此普遍存在的生态系统。

这也给 Web 开发人员带来了一个颇具挑战性的问题:应该如何设计网站,才能让用户在任何设备上访问时,网站都既实用又美观?
最初开发人员通过创建两个网站来解决这个问题:桌面版和移动版。
例如,针对移动设备,服务器会将 http://www.wombatcoffee.com 重定向到 http://m.wom-batcoffee.com
移动版网站通常对小屏幕用户提供的体验较少,设计得更精简。

随着市场上出现越来越丰富的设备,这种方法便开始捉襟见肘了。
平板设备该用移动版还是桌面版呢?大屏的“平板手机”呢?iPad Mini呢?如果移动端用户想要执行桌面版的功能呢?
最终,这种将桌面版和移动版强制分开的方案所带来的麻烦比它解决的问题还多。除此之外,还需要同时维护多个网站。

更好的方式是给所有用户提供同一份HTML和CSS。
通过使用几个关键技术,根据用户浏览器视口的大小(或者屏幕分辨率)让内容有不一样的渲染结果。
这种方式不需要分别维护两个网站。只需要创建一个网站,就可以在智能手机、平板,或者其他任何设备上运行。
网页设计师Ethan Marcotte称这种方式为响应式设计(responsive design)。

浏览网页的时候,留意一下你遇到的响应式设计。看看网站是如何响应不同的浏览器宽度的。
新闻类网站尤其有趣,因为它们需要将很多内容挤到一个页面。
一些新闻网站就提供了一个很好的示范,它根据浏览器窗口的宽度分别提供了一列、两列、三列布局。
通常我们缩放浏览器窗口的宽度就可以直接查看网页布局的响应。这就是响应式设计的工作方式。

响应式设计的三大原则如下。

(1) 移动优先。这意味着在实现桌面布局之前先构建移动版的布局。
(2) @media规则。使用这个样式规则,可以为不同大小的视口定制样式。用这一语法,通常叫作媒体查询(media queries),写的样式只在特定条件下才会生效。
(3) 流式布局。这种方式允许容器根据视口宽度缩放尺寸。

我们将介绍这三种原则。
首先会构建一个响应式网页,然后在构建过程中逐步介绍三大原则。
最后会专门介绍图片,因为在响应式网站中对图片的处理比较特殊。

移动优先

响应式设计的第一原则就是移动优先(mobile first),顾名思义就是构建桌面版之前要先构建移动端布局。
这样才能确保两个版本都生效。

开发移动版网页有很多限制:屏幕空间受限、网络更慢。
用户跟网页交互的方式也不一样:可以打字,但是用着很别扭,不能将鼠标移动到元素上触发效果等。
如果一开始就设计一个包含全部交互的网站,然后再根据移动设备的限制来制约网站的功能,那么一般会以失败告终v

而移动优先的方式则会让你设计网站的时候就一直想着这些限制。
一旦移动版的体验做好了(或者设计好了),就可以用“渐进增强”(progressive enhancement)的方式为大屏用户增加体验。 图8-1是我们要构建的网页。你猜对了这是移动版的设计。


图8-1 移动版的页面设计

网页有三个主要组件:头部、覆盖了一些文字的主图、主内容。
还有点击右上角图标后会出现的隐藏菜单(如图8-2所示)。
这个由三条横线组成的图标通常被叫作汉堡包图标,因为它们就像汉堡包的面包和肉饼


图8-2 在移动版页面上点击或者轻触汉堡包图标,打开菜单

移动端布局一般是很朴素的设计。除了前面提到的交互菜单,移动版设计主要关注的是内容。
在大屏上,可以把页面的大块区域拿来做头部、主图、和菜单。然而在移动设备上,用户通常有更明确的目标。
他们可能正在外面和朋友们玩,想要快速查到商店的营业时间或者其他具体的信息,比如商品价格或者目的地址。

移动版设计就是内容的设计。想想看,在桌面版网页里,一边是文章,另一边是侧边栏,侧边栏里有链接和不太重要的内容。
然而在移动端,我们希望文章先出现。换句话说,我们希望最重要的内容先出现在HTML里。
这一点恰好跟可访问性的关注点不谋而合:一个屏幕阅读器优先读到“重要的内容”,或者用户使用键盘浏览时先获取到文章里的链接,然后才是侧边栏里的链接。

话虽如此,这也不是一条铁律。比如在上面的示例里,主图虽然没有底下的内容重要,但是它是设计中最出彩的部分,因此应当放在页面顶部。
它还包含了少量内容,浏览起来也不费工夫。

重点做响应式设计时,一定要确保HTML包含了各种屏幕尺寸所需的全部内容。
你可以对每个屏幕尺寸应用不同的CSS,但是它们必须共享同一份HTML。 现在,需要思考较大的视口该如何设计。虽然要先给移动端写布局,但是心里装着整体的设计,才能帮助我们在实现过程中做出合适的决定。
比如在接下来示例里需要添加一个中等屏幕的和大屏幕的断点(breakpoint)。图8-3显示的是中等屏幕的布局。


图8-3 中等屏幕视口下的网页

断点: 一个特殊的临界值。屏幕尺寸达到这个值时,网页的样式会发生改变,以便给当前屏幕尺寸提供最佳的布局。

这个视口尺寸比移动端稍微多了一些发挥空间。头部和主图可以设置更大的内边距。
菜单元素刚好可以在一行排开,这样就无须隐藏了。汉堡包图标去掉了,因为无须用它来打开菜单。
现在主内容可以分布到三个等宽的列。大部分元素填充在距离视口边缘1em的范围内。

更大的视口跟上面一样,但是可以增加网页的外边距,增加主图尺寸,如图8-4所示。


图8-4 大屏幕视口下的网页

因为要先实现移动版设计,所以更应该了解在更大的视口下网页长什么样,这样才能在一开始就写出合适的 HTML 结构。
新建一个网页和样式表,给页面添加样式表,同时给 HTML 的 <body> 元素添加代码清单8-1所示的内容。

以下代码看起来跟非响应式设计的代码一样,但是有几处考虑了移动版设计,这稍后会解释。

代码清单8-1 响应式设计的网页标记

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<body>
  <header id="header" class="page-header">
    <div class="title">
      <h1>Wombat Coffee Roasters</h1>
      <div class="slogan">We love coffee</div>
    </div>
  </header>

  <nav class="menu" id="main-menu">
    <button class="menu-toggle" id="toggle-menu">
      toggle menu
    </button>
    <div class="menu-dropdown">
      <ul class="nav-menu">
        <li><a href="/about.html">About</a></li>
        <li><a href="/shop.html">Shop</a></li>
        <li><a href="/menu.html">Menu</a></li>
        <li><a href="/brew.html">Brew</a></li>
      </ul>
    </div>
  </nav>

  <aside id="hero" class="hero">
    Welcome to Wombat Coffee Roasters! We are
    passionate about our craft, striving to bring you
    the best hand-crafted coffee in the city.
  </aside>

  <main id="main">
    <div class="row">
      <section class="column">
        <h2 class="subtitle">Single-origin</h2>
        <p>We have built partnerships with small farms
          around the world to hand-select beans at the
          peak of season. We then carefully roast in
          <a href="/batch-size.html">small batches</a>
          to maximize their potential.</p>
      </section>
      <section class="column">
        <h2 class="subtitle">Blends</h2>
        <p>Our tasters have put together a selection of
          carefully balanced blends. Our famous
          <a href="/house-blend.html">house blend</a>
          is available year round.</p>
      </section>
      <section class="column">
        <h2 class="subtitle">Brewing Equipment</h2>
        <p>We offer our favorite kettles, French
          presses, and pour-over cones. Come to one of
          our <a href="/classes.html">brewing
          classes</a> to learn how to brew the perfect
          pour-over cup.</p>
      </section>
    </div>
  </main>

</body>
</html>

切换移动版菜单的图标放在nav元素里。nav-menu放置的位置能够同时满足移动和桌面设计的需求。
row和column类是为了桌面设计而添加的。(你可能从上面的代码看不出来,没关系,稍后会解释。)

接下来给页面添加样式。首先,添加简单的样式设置页面的字体、标题和颜色,如图8-5所示。
因为目前关注的是移动端样式,所以要将浏览器的宽度缩小,模拟一个移动设备的大小。这样就能看到小屏幕上的页面是什么样的了。


图8-5 加上简单样式后的网页

样式如代码清单8-2所示。将它们添加到样式表,创建border-box,为其添加大小、字体和链接颜色。
代码清单8-2用到了前面介绍的基于视口的响应式字号,并且定义了页面头部和主体的样式。

代码清单8-2 给页面加上初始样式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
body {
    margin: 0;
    font-family: Helvetica, Arial, sans-serif;
}

/*
    * Links
    */
a:link {
    color: #1476b8;
    font-weight: bold;
    text-decoration: none;
}
a:visited {
    color: #1430b8;
}
a:hover {
    text-decoration: underline;
}
a:active {
    color: #b81414;
}

/*
    * Header section
    */
.page-header {
    padding: 0.4em 1em;
    background-color: #fff;
}

.title > h1 {
    color: #333;
    text-transform: uppercase;
    font-size: 1.5rem;
    margin: .2em 0;
}

.slogan {
    color: #888;
    font-size: 0.875em;
    margin: 0;
}

/*
    * Hero image
    */
.hero {
    padding: 2em 1em;
    text-align: center;
    background-image: url(coffee-beans.jpg);
    background-size: 100%;
    color: #fff;
    text-shadow: 0.1em 0.1em 0.3em #000;
}

/*
    * Main section
    */
main {
    padding: 1em;
}

.subtitle {
    margin-top: 1.5em;
    margin-bottom: 1.5em;
    font-size: 0.875rem;
    text-transform: uppercase;
}

以上代码比较简单。它将网页标题和副标题设置为全大写,还给页面上各种组件加上了外边距和内边距,并调整了字号。

主图里的text-shadow属性你可能没见过。它里面的几个值最终会构成文字下面的投影。
前两个值是笛卡儿坐标,表明了投影相对于文字位置的偏移量。0.1em 0.1em表示投影相对于文字稍微往右下偏移。
第三个值(0.3em)表示投影模糊的程度。最后 #000 定义了投影的颜色。

其他

概念

弹性布局优化程度有限

在不同设备上正常使用;一般主要处理屏幕大小问题

主要方法:隐藏+折行+自适应空间;rem/viewport/media query

引入媒介查询

流动网格(弹性网格布局flexible grid layout)、弹性图片(flexible image)和媒介查询(media queries)

响应式网站是一个设计理念,它是多项技术的综合体

优缺点

减少工作量:网站、设计、代码、内容都只需要一份;多出来的工作量只是JS脚本、CSS样式做一些改动
节省时间
每个设备都能得到正确的设计
搜索优化

缺点:
会加载更多的样式和脚本资源
设计比较难精确定位和控制
老版本浏览器兼容不好

微信使用腾讯X5浏览服务(QQ浏览器)

媒体查询

1
2
3
4
5
<style>
@media all and (min-width: 800px) and (orientation:landscape) {

}
</style>

媒体属性