响应式设计

134 阅读21分钟

相对单位

现代技术让用户可以通过多种设备浏览互联网,例如台式显示器、手机、平板等。然而,不同屏幕尺寸的设备为网页开发者带来了一个问题:如何确保一个网站在各种设备上都能保持可读性和视觉美观性,不论屏幕大小如何?

答案就是:响应式设计(Responsive Design) !响应式设计是指网站能够根据以下内容的尺寸自动调整和重组内容的能力:

  • 网站中其他内容的大小。
  • 查看网站的设备屏幕尺寸。

在本课中,我们将学习如何将 HTML 内容的大小相对于网站中的其他内容来设置。

你可能已经注意到网站中常使用的单位 px(像素) 。像素用于将内容设置为确切的尺寸。例如,如果你想让一个 div 宽度正好为 500 像素,高度为 100 像素,就可以使用 px 单位。然而,像素是固定的、硬编码的值当屏幕尺寸发生变化时(例如在手机上从横屏切换到竖屏),使用像素设置尺寸的元素可能会显得太小、溢出屏幕,甚至完全不可读。

通过 CSS,我们可以避免使用硬编码的测量方式,而是使用相对单位。相对单位相对于其他元素进行尺寸设置,相比于固定单位,它们的优势在于:可以保持网页各部分的比例不变,无论屏幕尺寸或布局如何变化。

em单位

要使用相对单位进行尺寸设置,首先需要使用除像素以外的单位。其中一个在 CSS 中可以用于实现相对尺寸的单位是 em,在 CSS 中写作 em

em 这个单位的历史来源是排版中大写字母 “M” 的宽度,但现在已经不再是这种含义。

如今,1em 表示当前元素的字体大小;如果没有指定当前元素的字体大小,则会使用浏览器设置的默认字体大小作为参考。比如,如果浏览器的默认字体大小是 16 像素(这是大多数浏览器的默认设置),那么:

  • 1em = 16px
  • 2em = 32px,依此类推。

下面我们通过两个例子来看看如何在 CSS 中使用 em 单位:

.heading {
  font-size: 2em;
}

在上面的例子中,.heading 没有指定基准字体大小,因此字体大小将相对于浏览器默认字体大小计算。假设浏览器默认是 16px,那么 .heading 的字体大小就是 32px

.splash-section {
  font-size: 18px;
}

.splash-section h1 {
  font-size: 1.5em;
}

在这个例子中,.splash-section 显式地指定了一个基础字体大小为 18px。接下来,.splash-section 内的所有 h1 元素的字体大小设置为 1.5em,这表示它们将相对于 .splash-section 的字体大小计算。
所以,h1 元素的字体大小将是:

1.5 × 18px = 27px

通过这种方式,我们可以更灵活地设置字体大小,而不是依赖于固定的像素值。这样更有利于响应式设计,适应不同屏幕尺寸。

rem

CSS 中的第二种相对单位是 rem,它的写法就是 rem

rem 代表的是 root em(根元素的 em) 。它的行为类似于 em,但不同的是,rem 并不是根据父元素的字体大小来计算,而是根据根元素来计算。根元素指的是 <html> 标签。

大多数浏览器默认将 <html> 的字体大小设置为 16 像素,所以默认情况下,rem 的计算基准值就是 16px。你也可以通过添加 CSS 规则来修改根元素的字体大小:

html {
  font-size: 20px;
}

h1 {
  font-size: 2rem;
}

在上面的例子中,根元素 <html> 的字体大小被设置为了 20 像素。因此,之后所有使用 rem 的元素都会以这个值为基准来计算。比如上面的 h1 元素,它的字体大小是 2rem,那就是 2 × 20px = 40px

使用 rem 的一个优势是:所有元素都以统一的字体大小值为基准进行计算,这样就能更方便地预测和控制字体的大小。

  • 如果你想在整个网站中保持一致的元素大小,rem 是最合适的单位
  • 如果你想让元素相对于其附近的其他元素进行缩放,那使用 em 更适合
  • em 是相对单位,会根据父级元素的 font-size 来计算;
  • 如果父级没有设置,就一路往上找,直到 <html>
  • 如果 <html> 也没设置,那就用浏览器默认值(通常是 16px)为基准。

百分比:高度和宽度

要根据页面中父元素的尺寸对非文本 HTML 元素进行相对大小设置,你可以使用百分比。

百分比常用于设置盒模型的值,比如 width(宽度)、height(高度)、padding(内边距)、border(边框)和 margin(外边距)。它们也可以用来设置定位属性(如 topbottomleftright)。

首先,让我们用百分比来设置元素的高度和宽度。

.main {
  height: 300px;
  width: 500px;
}
 
.main .subsection {
  height: 50%;
  width: 50%;
}

在上面的例子中,.main.subsection 都是表示 div 元素。.subsection 是嵌套在 .main 中的子元素。请注意,父 div.main)的尺寸被设置为高 300 像素,宽 500 像素。

当使用百分比时,元素的尺寸是相对于其父元素的尺寸(也称为容器)来设置的。因此,.subsection 的高度将是 150 像素,宽度将是 250 像素。

注意:由于盒模型包含了内边距、边框和外边距,将元素的宽度设置为 100% 时可能会导致内容溢出其父容器。虽然这样做很诱人,但只有在内容没有内边距、边框或外边距的情况下,才应该使用 100%

百分比:内边距与外边距

百分比也可以用于设置元素的 padding(内边距)和 margin(外边距)。

当你使用百分比设置 height(高度)和 width(宽度)时,你已经了解到子元素的尺寸是基于父元素的尺寸来计算的。

但当你使用百分比来设置 paddingmargin 时,它们是只基于父元素的宽度来计算的

例如,当像 margin-left 这样的属性被设置为百分比(比如 50%)时,该元素将在父容器中向右移动其父容器宽度的一半(这并不是说子元素获得了一个相当于父元素外边距一半的外边距)。

垂直方向上的 padding 和 margin 也基于父元素的宽度来计算。为什么?来看下面这个场景:

  1. 一个容器 div 被定义,但它没有设置高度(也就是说它是“扁平的”)。
  2. 容器内添加了一个子元素,该子元素设置了高度。这会导致父容器的高度被撑开以适应子元素。
  3. 后来子元素需要修改,其高度发生变化。这又导致父容器的高度也随之改变。
  4. 每当子元素高度变化时,这个循环就会持续发生!

在这个场景中,父元素未设置高度,因此每次子元素的高度改变时,父元素也不断跟着改变,形成了无限变化的循环。这也是为什么 垂直方向上的 paddingmargin 会基于父元素的宽度而不是高度 的原因。

注意:在使用相对大小时,建议使用 emrem 来设置文本和与文本大小相关的尺寸(比如文本周围的 padding)。这样可以基于文本大小创建一致的布局。如果不是和文本相关的情况,则应使用百分比来设置尺寸。

宽度/高度:最小值与最大值

尽管使用相对单位可以在不同屏幕尺寸的设备上提供一致的布局,但网页上的元素在变得过小或过大时,仍可能失去其布局的完整性。为了解决这个问题,可以使用以下 CSS 属性限制元素的宽度范围:

  • min-width —— 设置元素的最小宽度。
  • max-width —— 设置元素的最大宽度。

height同理

示例:

p {
  min-width: 300px;
  max-width: 600px;
}

在上面的示例中,当浏览器窗口被缩小或放大时,段落元素的宽度不会小于 300 像素,也不会大于 600 像素。

当浏览器窗口变窄或变宽时,文本可能会变得过于拥挤或过于分散,从而影响可读性。使用这两个属性可以通过限制最小宽度和最大宽度,确保网页内容始终易于阅读。

注意:在设置这些限制时使用像素(px)单位,可以提供明确的、不可突破的尺寸限制。

缩放图像和视频

许多网站包含各种类型的媒体,例如图像和视频。当网页中包含这些媒体内容时,确保它们按比例缩放非常重要,以便用户能够正确地查看。

.container {
  width: 50%;
  height: 200px;
  overflow: hidden;
}

.container img {
  max-width: 100%;
  height: auto;
  display: block;
}

在上面的示例中,.container 代表一个容器 div。它被设置为宽度为 50%(例如页面宽度的一半),高度为 200 像素。设置 overflow: hidden 表示任何超过该容器尺寸的内容都将被隐藏,不会显示在页面上。

第二段 CSS 规则确保图像会随着容器宽度的变化而缩放。height: auto 表示图像的高度会根据宽度自动按比例缩放。最后,display: block 将图像显示为块级元素(默认是 inline-block)。这样做可以防止图像与页面上的其他内容(如文本)对齐,从而避免意外的外边距(margin)出现。

建议记住上面的完整示例。
它代表了一种非常常见的设计模式,用于按比例缩放图像和视频。

注意:
上述示例是将图像(或视频)的宽度缩放到容器的宽度。如果图像尺寸大于容器,高度部分将超出并被隐藏。
如果你想反过来处理(即根据容器的高度进行缩放),可以设置 max-height: 100%width: auto(相当于互换这两个属性的值)。
这样图像会根据容器的高度等比缩放。如果图像尺寸较大,那么图像的宽度部分将超出并被隐藏。

  • overflow: hidden; 让图片显示不要超过父容器
  • max-width: 100%; 让图片完整地显示出来
  • height: auto; 让元素的高度自动适应内容按比例缩放
  • display: block; 将图片设置为块级元素(img默认为行内元素),更好地实现缩放效果

缩放背景图片

HTML 元素的背景图片也可以通过 CSS 属性进行响应式缩放。

body {
  background-image: url('#');
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

在上面的示例中:

  • 第一条 CSS 声明设置了背景图片(# 是一个示意用的占位符,代表图片链接)。
  • 第二条声明告诉 CSS 不要重复显示背景图片(默认情况下,背景图会重复平铺)。
  • 第三条声明将背景图片在元素中居中显示。

最后一条声明才是示例的重点:

  • background-size: cover; 用来缩放背景图片
  • 该属性会让背景图覆盖整个元素的背景区域,同时保持图片的原始宽高比例。
  • 如果图片尺寸大于容器尺寸,那么只会显示图片的一部分内容(仍然是居中显示的)。

总结

你已经学会了如何根据页面中其他元素来设置网页中元素的大小

  • 网页上的内容可以使用相对单位来相对于页面中的其他元素进行尺寸设置。

  • em 单位表示相对于父元素的字体大小来设置字体。

  • rem 单位表示相对于**根元素(即 <html> 元素)**的字体大小来设置字体。

  • **百分比(%)**常用于设置盒模型的属性,例如元素的宽度、高度、内边距(padding)或外边距(margin)。

  • 当使用百分比设置宽度和高度时,子元素的尺寸将相对于父元素的尺寸来计算(注意,必须先设置父元素的尺寸)。

  • 百分比也可以用来设置内边距和外边距。水平和垂直方向的 padding 和 margin 是相对于父元素的宽度来计算的。

  • 可以使用 min-widthmax-width 设置元素的最小和最大宽度

  • 同理,可以使用 min-heightmax-height 设置元素的最小和最大高度

  • 当设置了图像或视频的高度后,可以将其宽度设置为 auto,以便媒体内容按比例缩放。反过来设置也可以达到相同的效果。

  • HTML 元素的背景图像在设置了 background-size: cover 后,也会按比例缩放以覆盖整个背景区域。

Viewport

到目前为止,我们一直在学习如何使用 CSS 创建响应式网页设计。但要让这些响应式的 CSS 真正生效,我们首先需要了解 HTML 中的视口(viewport)元标签

什么是视口(Viewport)?

视口是用户在设备上可见的网页区域,这个区域的大小会根据设备而变化。移动设备上的视口较小,桌面设备上的视口则更大。

根据视口的大小,浏览器会使用 <meta> 元标签来指示网页的缩放比例和显示尺寸
举个例子:假设网页本身是 960 像素宽,但用户的设备屏幕只有 320 像素。如果你加上了 viewport 元标签,网页内容就会被自动缩小至 320 像素以内,用户就不需要手动缩放来查看完整内容了!

如何在 HTML 中添加 <meta> 标签

我们通常在 <head> 标签中加入如下代码:

<!DOCTYPE html> 
<html lang="en"> 
  <head> 
    ...
    <meta name="viewport" content="width=device-width, initial-scale=1">
    ...
  </head> 

元标签的关键组成部分解释:

  • name="viewport":告诉浏览器使用视口相关的设置来显示网页。
  • content 属性:设置视口的具体参数值,例如宽度和缩放比例。
  • width=device-width:将视口宽度设置为设备的屏幕宽度。
  • initial-scale=1:设置初始的缩放比例为 1(也就是不缩放)。

你可以在 MDN 的视口文档 上了解更多关于 scale 的信息。

Media Queries

CSS 使用 (media queries) 来让网页内容适应不同的屏幕尺寸。通过media queries,CSS 能检测当前屏幕的大小,并根据屏幕宽度应用不同的样式规则。

@media only screen and (max-width: 480px) {
  body {
    font-size: 12px;
  }
}

上面的示例展示了媒体查询的应用方式。这个查询的意思是:当屏幕宽度小于或等于 480 像素时(大约相当于很多手机横屏时的宽度),将会应用指定的样式。

  • @media —— 这是媒体查询的关键词,用于开始一条媒体查询规则,并告诉 CSS 编译器如何解析后面的内容。
  • only screen —— 表示这条规则适用于什么类型的设备。在 CSS 早期尝试适配不同设备时,引入了不同的媒体类型(如 screenprinthandheld)。当时希望根据设备类型来应用不同的样式。但后来“handheld”和“screen”设备的尺寸差异变得非常大,光靠设备类型已经无法满足需求。于是我们通常使用 screen 来表示“用于显示内容的设备”,无论是手机、平板还是电脑。only 关键字用于限定这条规则只适用于 screen 类型的设备
  • and (max-width: 480px) —— 这一部分叫做媒体特性(media feature) ,表示当设备的宽度小于或等于 480 像素时,这条 CSS 规则才会生效。媒体特性就是媒体查询中的“条件”,只有满足这些条件,媒体查询中的样式才会被应用。
  • CSS 规则嵌套在花括号 {}。当媒体查询的条件满足时,括号中的样式就会被执行。
    在上述例子中,当用户的屏幕宽度小于 480px 时,body 元素中的文本字体大小将被设置为 12px。

范围

我们可以通过设置多个 widthheight 的媒体特性(media features)来针对特定屏幕尺寸应用样式。其中:

  • min-widthmin-height:分别表示最小宽度和最小高度;
  • max-widthmax-height:分别表示最大宽度和最大高度。

通过组合使用多个宽度或高度限制,可以为媒体查询设置一个“范围”。

@media only screen and (min-width: 320px) and (max-width: 480px) {
    /* 针对 320px 到 480px 范围内的屏幕尺寸的样式 */
}

上面的示例表示:只有当屏幕尺寸在 320 像素到 480 像素之间时,才会应用花括号中的 CSS 样式。
注意 min-width 之后使用了第二个 and,这样可以将两个条件连接起来,共同决定是否应用样式。

上面的写法也可以拆分成两个独立的媒体查询规则:

@media only screen and (min-width: 320px) { 
    /* 屏幕宽度大于等于 320px 时生效的样式 */
}
@media only screen and (min-width: 480px) { 
    /* 屏幕宽度大于等于 480px 时生效的样式 */
}

在这个例子中:

  • 第一条媒体查询会在屏幕大于等于 320px 时生效;
  • 第二条媒体查询会在屏幕大于等于 480px 时生效,可以覆盖第一条中的样式,或者添加新的样式。

dpi

我们还可以使用媒体特性(media features)来针对屏幕分辨率进行样式设置。
很多时候,我们希望只向支持高分辨率的用户提供高质量的媒体内容(例如图片、视频等)。
根据屏幕分辨率进行区分还有助于避免用户下载他们的设备无法正确显示的高分辨率(大文件)图片。

要根据分辨率进行目标设置,我们可以使用以下两个媒体特性:

  • min-resolution:设置最小分辨率
  • max-resolution:设置最大分辨率

这些媒体特性接受的单位可以是:

  • 每英寸点数(dpi, dots per inch)
  • 每厘米点数(dpc, dots per centimeter)

示例:

@media only screen and (min-resolution: 300dpi) {
    /* 针对高分辨率屏幕的样式 */
}

上面的媒体查询表示:当屏幕的分辨率大于或等于 300dpi 时,才会应用括号中的 CSS 样式。

如果屏幕分辨率满足条件,就可以在这个媒体查询中使用高质量的图片、视频或其他媒体资源。

and运算符

在之前的练习中,我们通过使用 and 运算符将多个相同类型的媒体特性连接到一个媒体查询中。
这使我们可以在一个媒体查询中同时使用 min-widthmax-width 来创建一个尺寸范围

其实,and 运算符的作用是要求多个媒体特性同时满足条件
因此,我们也可以使用 and 运算符来同时要求最大宽度为 480 像素分辨率不低于 300dpi

@media only screen and (max-width: 480px) and (min-resolution: 300dpi) {
    /* CSS 规则集 */
}

在上面的例子中:

  • 浏览器会检查两个条件是否都成立:

    • 屏幕宽度是否不超过 480 像素;
    • 屏幕分辨率是否至少为 300dpi;
  • 只有当两个条件都满足时,括号中的 CSS 样式才会被应用。

  • and 运算符可以连接任意多个媒体特性;

逗号分隔的媒体查询列表

如果你希望在多个媒体特性中只要满足任意一个就应用样式,
可以使用**逗号分隔的媒体查询列表(comma-separated list)**来实现。

例如:

假设我们需要在以下任意一个条件为真时应用样式:

  • 屏幕宽度大于 480 像素
  • 屏幕处于横屏模式(landscape)

我们可以这样写:

@media only screen and (min-width: 480px), (orientation: landscape) {
    /* CSS 样式规则 */
}

在上面的例子中,我们使用了 逗号(,) 来分隔多个规则。

这个语句的意思是:

只要其中一个媒体查询条件为真,就会应用里面的 CSS 样式。

第二个媒体特性 orientation 是用来检测设备的方向的:

  • 如果页面的 宽度大于高度,那么就是 横屏(landscape)
  • 如果页面的 高度大于宽度,那么就是 竖屏(portrait)

断点

我们已经了解了如何使用媒体查询(media queries)来根据屏幕尺寸和分辨率应用 CSS 规则,但我们该如何决定设置哪些查询条件呢?

我们设置媒体查询的那些关键尺寸点被称为“断点”(breakpoints) 。断点是网页在某些屏幕尺寸下显示不正常的那些点。例如,如果我们想要针对横屏方向的平板设备,可以设置如下断点:

@media only screen and (min-width: 768px) and (max-width: 1024px) and (orientation: landscape) {
    /* CSS 样式规则 */
}

上面的例子创建了一个适用于横屏平板尺寸范围的媒体查询,并且指定了方向。

然而,为每一种设备都设置断点是非常困难的事情,因为设备的尺寸和形状各异,而且每年还会有新设备发布,带来新的屏幕尺寸。

**因此,最佳实践并不是为特定设备设置断点,而是根据网页内容自然中断(break)的位置来设置断点。**你可以通过调整浏览器窗口大小,观察网页在哪些尺寸下布局出现异常或错位,那些尺寸就可以作为你的媒体查询断点。

在这些断点中,我们可以调整 CSS,使页面能够在不同尺寸下进行良好的缩放和重组,从而达到响应式设计的效果。

通过观察网页在不同尺寸下自然“断裂”的位置,你可以根据具体项目设定最合适的断点,而不是强行让所有项目适配某一固定屏幕尺寸。每个项目都有不同的需求,响应式设计也应当因项目而异。

你还可以查阅一份设备宽度断点列表,作为测试你网站在各种设备上显示效果的参考。

content.codecademy.com/courses/fre…..

总结

  • 当一个网站会根据所查看屏幕的尺寸做出响应时,它就被称为响应式网站(responsive website)。

  • 你可以编写媒体查询(media queries)来适配不同的屏幕尺寸。

  • 向代码中添加 <meta> 视口标签(viewport meta tag)可以让我们控制视口的宽度和缩放,从而确保网页在所有设备上正确地进行尺寸和比例缩放。

  • 媒体查询依赖于“媒体特性”(media features)。媒体特性是必须满足的条件,只有在这些条件被满足时,媒体查询中的 CSS 才会生效。

  • 媒体特性可以检测用户浏览器的多个方面,比如屏幕的宽度、高度、分辨率、方向等。

  • 使用 and 运算符可以要求多个媒体特性同时为真。

  • 使用逗号分隔的媒体特性列表中,只需满足其中一个条件,就会应用对应的 CSS。

  • 设置媒体查询的最佳实践是通过手动缩放浏览器窗口,来观察网页内容在哪些尺寸下自然出现断裂。根据这些“自然断点”设置媒体查询才最合理。

  • 有了你对媒体查询和 CSS 的理解,你现在可以让网站在任何设备上都拥有出色的显示效果,无论是小巧的手机,还是巨大的电视屏幕。通过实现响应式设计,你可以为所有用户提供良好的网页浏览体验。