响应式网页设计
响应式网页设计(Responsive Web Design,RWD)是一种网页设计方法,旨在使网页在所有屏幕尺寸和分辨率下都能良好地呈现,同时确保良好的可用性。这是一种为多设备网络进行设计的方式。在本文中,我们将帮助你了解一些可以用来掌握响应式设计的技术。
预备知识 | 使用 HTML 构造内容、CSS 样式基础、文本和字体样式基础,熟悉CSS 布局基本概念。 |
---|---|
学习成果 |
|
响应式设计的前身:移动网页设计
在响应式网页设计成为使网站跨不同设备类型工作的标准方法之前,Web 开发人员过去常常谈论移动网页设计、移动网页开发,或者有时是移动友好设计。这些基本上与响应式网页设计相同——目标是确保网站在布局、内容(文本和媒体)和性能方面,能够在具有不同物理属性(屏幕尺寸、分辨率)的设备上良好地工作。
区别主要在于所涉及的设备以及可用于创建解决方案的技术。
- 我们过去常说桌面设备或移动设备,但现在有许多不同类型的设备,如台式机、笔记本电脑、手机、平板电脑、手表等。我们现在需要防御性地设计网站,以适应常见的屏幕尺寸和分辨率,以及未知的情况,而不是仅仅迎合几种不同的屏幕尺寸。
- 过去的移动设备在 CPU/GPU 和可用带宽方面性能较低。有些甚至不支持 CSS 甚至 HTML,因此,通常会进行服务器端浏览器嗅探来确定设备/浏览器类型,然后再提供设备能够处理的网站。移动设备通常只能获得非常简单、基础的体验,因为这是它们所能处理的全部。如今,移动设备能够处理与台式计算机相同的技术,因此这类技术已不那么常见了。
- 你仍然应该使用本文中讨论的技术来为移动用户提供合适的体验,因为仍然存在电池寿命和带宽等限制需要考虑。
- 用户体验仍然是一个需要关注的问题。例如,一个旅游网站的移动用户可能只想查询航班时间和延误信息,而不是看到一个展示飞行路径和公司历史的 3D 动画地球。
- 现代技术在创建响应式体验方面要好得多。例如,响应式图片/媒体技术现在允许向不同设备提供适当的媒体,而无需依赖服务器端嗅探等技术。
响应式网页设计简介
HTML 本质上是响应式的,或者说是流式的。如果你创建一个只包含 HTML 而没有 CSS 的网页,并调整窗口大小,浏览器会自动重排文本以适应视口。
虽然默认的响应式行为听起来似乎不需要任何解决方案,但在宽屏显示器上全屏显示的长行文本可能难以阅读。这个问题可以通过 CSS 来解决,例如创建窄列来限制行长。然而,这可能会给那些缩小浏览器窗口或在移动设备上查看网站的用户带来新问题——这些列会看起来被挤压,变得更难阅读。
通过设置固定宽度来创建不可调整大小的网页也不可行;这会导致在窄设备上出现滚动条,在宽屏幕上则有太多空白空间。
响应式网页设计(RWD)是一种设计方法,它解决了所有可用设备和设备尺寸范围的问题,使内容能够自动适应屏幕,无论是在平板电脑、手机、电视还是手表上查看。
响应式网页设计不是一项独立的技术——它是一种方法。它是一个术语,用来描述一套用于创建能够响应任何用于查看内容的设备的布局的最佳实践。
响应式设计这个术语由 Ethan Marcotte 在 2010 年创造,描述了使用流式网格、流式图片和媒体查询来创建响应式内容。
当时,建议是使用 CSS float
进行布局,并使用媒体查询来查询浏览器宽度,为不同的断点创建布局。流式图片被设置为不超过其容器的宽度;它们的 max-width
属性被设置为 100%
。当其包含的列变窄时,流式图片会缩小,但当列变宽时,它们不会变得比其固有尺寸更大。这使得图片能够缩小以适应其内容,而不是溢出,但如果容器变得比图片更宽,图片也不会变大而出现像素化。
现代 CSS 布局方法本身就是响应式的,并且自从 Marcotte 的文章发表以来,Web 平台内置了大量功能,使得设计响应式网站变得更加容易。
本文的其余部分将解释在创建响应式网站时你可能想要使用的各种 Web 平台功能。
媒体查询
媒体查询允许我们运行一系列测试(例如,用户的屏幕宽度或分辨率是否大于某个值),并有选择地应用 CSS 来适当地为用户的需求设置页面样式。
例如,以下媒体查询测试当前网页是否以屏幕媒体(因此不是打印文档)显示,并且视口宽度至少为 80rem
。只有在这两个条件都为真时,.container
规则才会应用。
@media screen and (width >= 80rem) {
.container {
margin: 1em 2em;
}
}
你可以在一个样式表中添加多个媒体查询,调整整个布局或其部分,以最好地适应各种屏幕尺寸。引入媒体查询并改变布局的点被称为断点。
使用媒体查询时,一种常见的方法是为窄屏设备(例如手机)创建一个简单的单列布局,然后检查更宽的屏幕,并在知道有足够的屏幕宽度来处理它时,实现一个多列布局。优先为移动设备设计被称为移动优先设计。
如果使用断点,最佳实践鼓励使用相对单位来定义媒体查询断点,而不是单个设备的绝对尺寸。
媒体查询块内定义的样式有不同的方法;从使用媒体查询根据浏览器尺寸范围<link>
样式表,到仅包含用于存储与每个断点相关值的自定义属性变量。
媒体查询可以帮助实现 RWD,但不是必须的。灵活的网格、相对单位以及最小和最大单位值可以在没有媒体查询的情况下使用。
备注: Scrimba 有一个名为旁注:媒体查询 MDN 学习合作伙伴 的教程,它提供了媒体查询的交互式介绍,以及一个挑战来测试你是否理解基础知识。
响应式布局技术
响应式网站建立在灵活的网格之上,这意味着你不需要针对每一种可能的设备尺寸进行像素完美的布局。
通过使用灵活的网格,你可以在内容开始看起来不佳时更改某个特性或添加一个断点来改变设计。例如,为了确保随着屏幕尺寸增加行长不会变得难以阅读,你可以使用 columns
;如果一个盒子在变窄时被挤压成每行只有两个词,你可以设置一个断点。
包括 Flexbox 和 CSS 网格在内的几种布局方法默认就是响应式的。它们都假设你正在尝试创建一个灵活的网格,并为你提供了更简单的方法来实现。
Flexbox
在 flexbox 中,flex 项目会缩小或增长,根据其容器中的空间来分配项目之间的空间。通过更改 flex-grow
和 flex-shrink
的值,你可以指示当项目周围遇到更多或更少空间时,你希望它们如何表现。
在下面的示例中,flex 项目将在 flex 容器中各占等量的空间,使用之前讨论过的 flex: 1
简写(参见 Flexbox:Flex 项目的灵活尺寸)。
.container {
display: flex;
}
.item {
flex: 1;
}
以下是我们如何将 flexbox 与媒体查询结合用于响应式设计。
<div class="wrapper">
<div class="col1">
<p>
This layout is responsive. See what happens if you make the browser window
wider or narrow.
</p>
</div>
<div class="col2">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of
millions of people had watched the rising smoke-wreaths of their fires
without drawing any special inspiration from the fact.
</p>
</div>
</div>
@media screen and (width >= 600px) {
.wrapper {
display: flex;
}
.col1 {
flex: 1;
margin-right: 5%;
}
.col2 {
flex: 2;
}
}
调整你的浏览器窗口大小。当上述示例的尺寸超过 600px
宽度阈值时,布局将在单列和两列布局之间切换。
CSS 网格
在 CSS 网格布局中,fr
单位允许在网格轨道之间分配可用空间。下一个示例创建了一个具有三个尺寸为 1fr
的轨道的网格容器。这将创建三个列轨道,每个轨道占据容器中可用空间的一部分。你已经看过这种方法(回顾请参见 使用 fr 单位的灵活网格)。
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
以下是我们如何将网格布局与媒体查询结合用于响应式设计。
<div class="wrapper">
<div class="col1">
<p>
This layout is responsive. See what happens if you make the browser window
wider or narrow.
</p>
</div>
<div class="col2">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of
millions of people had watched the rising smoke-wreaths of their fires
without drawing any special inspiration from the fact.
</p>
</div>
</div>
@media screen and (width >= 600px) {
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr;
column-gap: 5%;
}
}
再次尝试调整你的浏览器窗口大小——你应该会看到示例布局在 600px
宽度阈值处发生变化,与前一个示例的方式相同。
响应式图片/媒体
为确保媒体永远不会大于其响应式容器,可以使用以下方法:
img,
picture,
video {
max-width: 100%;
}
这会缩放媒体元素,以确保它们永远不会溢出其容器。
备注: 使用一张大图并将其缩小以适应小设备会浪费带宽,因为下载了比需要更大的图片。它也可能看起来不好——例如,一张横向图片在宽屏显示器上可能看起来不错,但在移动设备上可能难以看清,而移动设备更适合纵向图片。这类问题可以使用 <picture>
元素和 <img>
的 srcset
和 sizes
属性来解决。这些是高级功能,超出了本课程的范围,但你可以在响应式图片中找到详细指南。
其他有用的提示
响应式排版
响应式排版描述了在媒体查询中改变字体大小,或使用视口单位来反映屏幕空间的多少。
使用媒体查询实现响应式排版
在这个例子中,我们想将一级标题设置为 4rem
,这意味着它将是我们基础字体大小的四倍。这是一个非常大的标题!我们只希望这个巨大的标题出现在较大的屏幕尺寸上,因此我们首先给标题一个较小的尺寸 2rem
,然后使用媒体查询,如果我们知道用户的屏幕宽度至少为 1200px
,就用较大的尺寸覆盖它。
html {
font-size: 1em;
}
h1 {
font-size: 2rem;
}
@media (width >= 1200px) {
h1 {
font-size: 4rem;
}
}
下一个示例是我们早期响应式网格示例的修改版,它包含了使用上述方法的响应式标题。在移动设备上标题较小,但在桌面设备上,我们看到较大的标题尺寸。
<div class="wrapper">
<div class="col1">
<h1>Watch my size!</h1>
<p>
This layout is responsive. See what happens if you make the browser window
wider or narrow.
</p>
</div>
<div class="col2">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of
millions of people had watched the rising smoke-wreaths of their fires
without drawing any special inspiration from the fact.
</p>
</div>
</div>
html {
font-size: 1em;
}
body {
font:
1.2em "Helvetica",
"Arial",
sans-serif;
margin: 20px;
padding: 0;
background-color: #eeeeee;
}
.wrapper {
max-width: 960px;
margin: 2em auto;
}
h1 {
font-size: 2rem;
margin: 0;
}
.col1,
.col2 {
background-color: white;
}
@media screen and (width >= 600px) {
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr;
column-gap: 5%;
}
h1 {
font-size: 4rem;
}
}
与之前的示例一样,尝试改变浏览器窗口的宽度,并注意不仅布局在 600px
宽度阈值处发生变化,标题大小也发生了变化。
正如这种排版方法所示,你不需要将媒体查询限制在仅改变页面布局上。它们可以用来调整任何元素,使其在不同的屏幕尺寸下更具可用性或更具吸引力。
使用视口单位实现响应式排版
视口单位 vw
也可以用来实现响应式排版,而无需使用媒体查询设置断点。1vw
等于视口宽度的百分之一,这意味着如果你使用 vw
设置字体大小,它将始终与视口的大小相关联。
h1 {
font-size: 6vw;
}
上述做法的问题在于,用户失去了缩放任何使用 vw
单位设置的文本的能力,因为该文本始终与视口的大小相关。因此,你不应该单独使用视口单位来设置文本。
有一个解决方案,它涉及到使用 calc()
。如果你将 vw
单位添加到一个使用固定大小(如 em
或 rem
)设置的值上,那么文本仍然可以缩放。本质上,vw
单位是在那个缩放后的值之上添加的。
h1 {
font-size: calc(1.5rem + 4vw);
}
这意味着我们只需要为标题指定一次字体大小,而不需要为移动设备设置一次,然后在媒体查询中重新定义它。然后,随着你增加视口的大小,字体会逐渐增大。
<div class="wrapper">
<div class="col1">
<h1>Watch my size!</h1>
<p>
This layout is responsive. See what happens if you make the browser window
wider or narrow.
</p>
</div>
<div class="col2">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
</div>
</div>
body {
font: 1.2em / 1.5 sans-serif;
margin: 20px;
padding: 0;
background-color: #eeeeee;
}
.wrapper {
max-width: 960px;
margin: 2em auto;
}
h1 {
font-size: calc(1.5rem + 4vw);
margin: 0;
}
.col1,
.col2 {
background-color: white;
}
@media screen and (width >= 600px) {
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr;
column-gap: 5%;
}
}
像之前一样,尝试调整浏览器窗口的大小,并注意这次标题大小如何随着宽度的变化而逐渐增大。
视口 meta 标签
如果你查看一个响应式页面的 HTML 源代码,你通常会在文档的 <head>
中看到以下 <meta>
标签。
<meta name="viewport" content="width=device-width,initial-scale=1" />
这个viewport
meta 标签告诉移动浏览器,它们应该将视口的宽度设置为设备的宽度,并将文档缩放到其预期大小的 100%,这会以你期望的移动优化尺寸来显示文档。
为什么需要这个?因为移动浏览器倾向于谎报它们的视口宽度。
这个 meta 标签之所以存在,是因为当智能手机刚出现时,大多数网站都没有进行移动优化。因此,移动浏览器会将视口宽度设置为 980 像素,以该宽度渲染页面,并显示一个缩小的桌面布局版本。用户可以放大和平移网站来查看他们感兴趣的部分,但这看起来很糟糕。
通过设置 width=device-width
,你将覆盖移动设备的默认值,比如 iPhone 的默认 width=980px
,替换为设备的实际宽度。没有它,你带有断点和媒体查询的响应式设计可能无法在移动浏览器上按预期工作。如果你有一个在 480px 或更小视口宽度下生效的窄屏布局,但设备却说它的宽度是 980px,那么该用户将看不到你的窄屏布局。
所以你应该始终在你的文档头部包含 viewport meta 标签。
你还可以在 viewport meta 标签的 content
属性中放入许多其他选项——更多细节请参见 <meta name="viewport">
参考。
总结
响应式设计指的是一个能够响应其查看环境的网站或应用程序设计。它包含了许多 CSS 和 HTML 的特性和技术,并且基本上是我们默认构建网站的方式。想想你在手机上访问的网站——遇到一个缩小版的桌面网站,或者需要横向滚动才能找到东西的情况可能相当少见。这是因为 Web 已经转向了这种响应式设计的方法。
借助于本文所涵盖的布局方法,实现响应式设计也变得容易得多。如果你今天刚接触 Web 开发,你拥有的工具比响应式设计早期要多得多。因此,检查你正在使用的任何材料的年代是值得的。虽然历史文章仍然有用,但现代 CSS 和 HTML 的使用使得创建优雅而有用的设计变得更加容易,无论你的访问者使用什么设备查看网站。
接下来,我们将更详细地研究媒体查询,并展示如何使用它们来解决一些常见问题。
另见
- 与触摸屏设备协同工作
- 触摸事件提供了在触摸屏或触控板上解释手指(或触控笔)活动的能力,从而为复杂的基于触摸的用户界面提供高质量支持。
- 使用 pointer 或 any-pointer 媒体查询在支持触摸的设备上加载不同的 CSS。
- CSS-Tricks 的媒体查询指南
- Scrimba 的前端开发者职业路径 MDN 学习合作伙伴 教授你成为一名称职的前端 Web 开发人员所需知道的一切,课程包含有趣的互动课程和挑战、知识渊博的老师以及一个互助的社区。从零开始,直到找到你的第一份前端工作!课程的许多组成部分都提供独立的免费版本。其中包括一个关于响应式设计的模块。