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

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

    1. 移动优先

    响应式设计的第一原则就是移动优先( mobile first),顾名思义就是构建桌面版之前要先构建移动端布局。这样才能确保两个版本都生效。
    开发移动版网页有很多限制:屏幕空间受限、网络更慢。用户跟网页交互的方式也不一样:可以打字,但是用着很别扭,不能将鼠标移动到元素上触发效果等。如果一开始就设计一个包含全部交互的网站,然后再根据移动设备的限制来制约网站的功能,那么一般会以失败告终。
    而移动优先的方式则会让你设计网站的时候就一直想着这些限制。一旦移动版的体验做好了(或者设计好了),就可以用“渐进增强”( progressive enhancement)的方式为大屏用户增加体验。
    下图是我们要构建的网页。这是移动版的设计。
    image.png
    网页有三个主要组件:头部、覆盖了一些文字的主图、主内容。还有点击右上角图标后会出现的隐藏菜单(如下图所示)。这个由三条横线组成的图标通常被叫作汉堡包图标,因为它们就像汉堡包的面包和肉饼。
    image.png
    移动端布局一般是很朴素的设计。除了前面提到的交互菜单,移动版设计主要关注的是内容。在大屏上,可以把页面的大块区域拿来做头部、主图和菜单。然而在移动设备上,用户通常有更明确的目标。他们可能正在外面和朋友们玩,想要快速查到商店的营业时间或者其他具体的信息,比如商品价格或者目的地址。

    重点: 做响应式设计时,一定要确保 HTML 包含了各种屏幕尺寸所需的全部内容。你可以对每个屏幕尺寸应用不同的 CSS,但是它们必须共享同一份 HTML。

现在,需要思考较大的视口该如何设计。虽然要先给移动端写布局,但是心里装着整体的设计,才能帮助我们在实现过程中做出合适的决定。比如在示例里需要添加一个中等屏幕的和大屏幕的断点(breakpoint)。下图显示的是中等屏幕的布局。
image.png

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

这个视口尺寸比移动端稍微多了一些发挥空间。头部和主图可以设置更大的内边距。菜单元素刚好可以在一行排开,这样就无须隐藏了。汉堡包图标去掉了,因为无须用它来打开菜单。现在主内容可以分布到三个等宽的列。大部分元素填充在距离视口边缘 1em 的范围内。
更大的视口跟上面一样,但是可以增加网页的外边距,增加主图尺寸,如下图所示。
image.png
因为要先实现移动版设计,所以更应该了解在更大的视口下网页长什么样,这样才能在一开始就写出合适的 HTML 结构。新建一个网页和样式表,给页面添加样式表,同时给 HTML 的元素添加代码清单1所示的内容。

  1. <header id="header" class="page-header">
  2. <div class="title">
  3. <h1>Wombat Coffee Roasters</h1>
  4. <div class="slogan">We love coffee</div>
  5. </div>
  6. </header>
  7. <nav class="menu" id="main-menu">
  8. <button class="menu-toggle" id="toggle-menu">
  9. toggle menu
  10. </button>
  11. <div class="menu-dropdown">
  12. <ul class="nav-menu">
  13. <li><a href="/about.html">About</a></li>
  14. <li><a href="/shop.html">shop</a></li>
  15. <li><a href="/menu.html">Menu</a></li>
  16. <li><a href="/brew.html">Brew</a></li>
  17. </ul>
  18. </div>
  19. </nav>
  20. <aside id="id" class="hero">
  21. Welcome to Wombat Coffee Roasters! We are
  22. passionate about our craft, striving to bring you
  23. the best hand-crafted coffee in the city.
  24. </aside>
  25. <main id="main">
  26. <div class="row">
  27. <section class="column">
  28. <h2 class="subtitle">Single-origin</h2>
  29. <p>We have built partnerships with small farms
  30. around the world to hand-select beans at the
  31. peak of season. We then carefully roast in
  32. <a href="/batch-size.html">small batches</a>
  33. to maximize their potential.
  34. </p>
  35. </section>
  36. <section class="column">
  37. <h2 class="subtitle">Blends</h2>
  38. <p>Our tasters have put together a selection of
  39. carefully balanced blends. Our famous
  40. <a href="/house-blend.html">house blend</a>
  41. is available year round.
  42. </p>
  43. </section>
  44. <section class="column">
  45. <h2 class="subtitle">Brewing Equipment</h2>
  46. <p>We offer our favorite kettles, French
  47. presses, and pour-over cones. Come to one of
  48. our <a href="/classes.html">brewing
  49. classes</a> to learn how to brew the perfect
  50. pour-over cup.</p>
  51. </section>
  52. </div>
  53. </main>

在这段标记里,切换移动版菜单的图标放在 nav 元素里。 nav-menu 放置的位置能够同时满足移动和桌面设计的需求。 row 和 column 类是为了桌面设计而添加的。
接下来给页面添加样式。首先,添加简单的样式设置页面的字体、标题和颜色,如下图所示。因为目前关注的是移动端样式,所以要将浏览器的宽度缩小,模拟一个移动设备的大小。这样就能看到小屏幕上的页面是什么样的了。
image.png
样式如代码清单2所示。将它们添加到样式表,创建 border-box,为其添加大小、字体和链接颜色。代码清单2用到了基于视口的响应式字号,并且定义了页面头部和主体的样式。

  1. /*:root——匹配代表文档的树的根元素*/
  2. :root {
  3. box-sizing: border-box;
  4. /*基础字号会根据视口大小适当缩放*/
  5. font-size: calc(1vw + 0.6em);
  6. }
  7. *, *::before, *::after {
  8. box-sizing: inherit;
  9. }
  10. body {
  11. margin: 0;
  12. font-family: 'Times New Roman', Times, serif;
  13. }
  14. a:link {
  15. color: #1476b8;
  16. font-weight: bold;
  17. text-decoration: none;
  18. }
  19. a:visited {
  20. color: #1430b8;
  21. }
  22. a:hover {
  23. text-decoration: underline;
  24. }
  25. a:active {
  26. color: #b81414;
  27. }
  28. .page-header {
  29. padding: 0.4em 1em;
  30. }
  31. .title > h1 {
  32. color: #333;
  33. text-transform: uppercase;
  34. font-size: 1.5rem;
  35. margin: 0.2em 0;
  36. }
  37. .slogan {
  38. color: #888;
  39. font-size: 0.875em;
  40. margin: 0;
  41. }
  42. .hero {
  43. padding: 2em 1em;
  44. text-align: center;
  45. background-image: url(./image/caffee.jpg);
  46. background-size: 100%;
  47. color: #fff;
  48. /*深色的文字投影确保浅色文字在复杂背景中可读*/
  49. text-shadow: 0.1em 0.1em 0.3em #000;
  50. }
  51. main {
  52. padding: 1em;
  53. }
  54. .subtitle {
  55. margin-top: 1.5em;
  56. margin-bottom: 1.5em;
  57. font-size: 0.875em;
  58. text-transform: uppercase;
  59. }

1.1. 创建移动版的菜单

目前页面还剩最复杂的部分等待实现:菜单。现在开始构建。完成后的效果如下图所示。
image.png
不管用什么语言写代码都是一个迭代过程, CSS 也不例外。在这个页面里,菜单需要特殊考虑。我原本是将