Skip to content

为所有用户获得最佳体验的设计

可以使用许多不同的设备来查看网页:台式机、平板电脑和手机。无论使用哪种设备,您的网页都应该看起来美观且易用。

网页不应舍弃信息来适合较小的设备,而应使其内容适合任何设备: qq截图20220326100039.png 如果您使用 CSS 和 HTML 调整大小、隐藏、缩小、放大或移动内容,以使其在任何屏幕上看起来都很好,则称为响应式 Web 设计。

始终移动优先设计

移动优先(Mobile First)指的是在对台式机或任何其他设备进行设计之前,优先针对移动设备进行设计(这将使页面在较小的设备上显示得更快)。

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

什么是视口?

视口(viewport)是用户在网页上的可见区域。

视口随设备而异,在移动电话上会比在计算机屏幕上更小。

在平板电脑和手机之前,网页仅设计为用于计算机屏幕,并且网页拥有静态设计和固定大小是很常见的。

然后,当我们开始使用平板电脑和手机上网时,固定大小的网页太大了,无法适应视口。为了解决这个问题,这些设备上的浏览器会按比例缩小整个网页以适合屏幕大小。

这并不是完美的!勉强是一种快速的修正。

设置视口

HTML5 引入了一种方法,使 Web 设计者可以通过 标签来控制视口。

您应该在所有网页中包含以下 视口元素:

css
<meta name="viewport" content="width=device-width, initial-scale=1.0">

它为浏览器提供了关于如何控制页面尺寸和缩放比例的指令。

width=device-width 部分将页面的宽度设置为跟随设备的屏幕宽度(视设备而定)。

当浏览器首次加载页面时,initial-scale=1.0 部分设置初始缩放级别。

qq截图20220326095816.png

把内容调整到视口的大小

用户习惯在台式机和移动设备上垂直滚动网站,而不是水平滚动!

因此,如果迫使用户水平滚动或缩小以查看整个网页,则会导致不佳的用户体验。

还需要遵循的一些附加规则:

  1. 请勿使用较大的固定宽度元素 - 例如,如果图像的宽度大于视口的宽度,则可能导致视口水平滚动。请务必调整此内容以适合视口的宽度。

  2. 不要让内容依赖于特定的视口宽度来呈现好的效果 - 由于以 CSS 像素计的屏幕尺寸和宽度在设备之间变化很大,因此内容不应依赖于特定的视口宽度来呈现良好的效果。

  3. 使用 CSS 媒体查询为小屏幕和大屏幕应用不同的样式 - 为页面元素设置较大的 CSS 绝对宽度将导致该元素对于较小设备上的视口太宽。而是应该考虑使用相对宽度值,例如 width: 100%。另外,要小心使用较大的绝对定位值,这可能会导致元素滑落到小型设备的视口之外。

构建响应式网格视图

响应式网格视图通常有 12 列,总宽度为 100%,并且在调整浏览器窗口大小时会收缩和伸展。计算一列的百分比:100% / 12 列 = 8.33%。

首先,确保所有 HTML 元素的 box-sizing 属性设置为 border-box。这样可以确保元素的总宽度和高度中包括内边距(填充)和边框。

然后,我们为 12 列中的每一列创建一个类,即 class="col-" 和一个数字,该数字定义此节应跨越的列数

css
.col-1  {width: 8.33%;}
.col-2  {width: 16.66%;}
.col-3  {width: 25%;}
.col-4  {width: 33.33%;}
.col-5  {width: 41.66%;}
.col-6  {width: 50%;}
.col-7  {width: 58.33%;}
.col-8  {width: 66.66%;}
.col-9  {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}

HTML:

html
<div class="row">
  <div class="col-3">...</div> <!-- 25% -->
  <div class="col-9">...</div> <!-- 75% -->
</div>

媒体查询

什么是媒体查询?

媒体查询是 CSS3 中引入的一种 CSS 技术。

仅在满足特定条件时,它才会使用 @media 规则来引用 CSS 属性块。

css
/*如果浏览器窗口是 600px 或更小,则背景颜色为浅蓝色*/

@media only screen and (max-width: 600px) {
  body {
    background-color: lightblue;
  }
}

媒体查询基础

上面我们已经简单体验了一下媒体查询的用法,最简单的媒体查询语法看起来像是这样子的:

css
@media media-type and (media-feature-rule) {
  /* CSS rules go here */
}

它由以下部分组成:

  • 一个媒体类型,告诉浏览器这段代码是用在什么类型的媒体上的(例如屏幕或者印刷品)

  • 一个媒体表达式,是一个被包含的CSS生效所需的规则或测试

  • 一组CSS规则,会在测试通过且媒体类型正确的时候应用

媒体类型

常见的媒体类型有:

  • all:所有类型设备
  • print:打印预览模式
  • screen:屏幕设备,是我们最常用的类型

下面的媒体查询会在页面被打印的时候把 body 设定为 12pt 大小,当页面在浏览器载入的时候,他将不会生效

css
@media print {
  body {
    font-size: 12pt;
  }
}

更复杂的媒体查询

前面的例子我们看到,每次只使用了一个媒体特征,但实际上不同的媒体特征可以组合来用,支持“或与非”逻辑判断。

媒体查询中的“与”逻辑

你可以使用 and 来组合媒体类型和特征,例如,我们想要测得 min-widthorientation,而 body 的文字只会在视口至少400像素宽,且设备横放时变为蓝色,那么规则可以这么来写:

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

媒体查询中的“或”逻辑

如果你有一组查询,且要其中任何一个都可以匹配的话,那么你可以使用逗号分开这些查询。在下面的例子中,文本会在视口至少400像素宽的时候,或者设备处于横放状态的时候变为蓝色,如果其中一项满足,那么查询就匹配上了。

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;
  }
}

添加断点

在稍早前,我们制作了一张包含行和列的网页,但是这张响应式网页在小屏幕上看起来效果并不好。

媒体查询可以帮助您。我们可以添加一个断点,其中设计的某些部分在断点的每一侧会表现得有所不同。 qq截图20220326100039.png

css
/* 针对手机: */
[class*="col-"] {
  width: 100%;
}

@media only screen and (min-width: 600px) {
  /* 针对平板电脑: */
  .col-s-1 {width: 8.33%;}
  .col-s-2 {width: 16.66%;}
  .col-s-3 {width: 25%;}
  .col-s-4 {width: 33.33%;}
  .col-s-5 {width: 41.66%;}
  .col-s-6 {width: 50%;}
  .col-s-7 {width: 58.33%;}
  .col-s-8 {width: 66.66%;}
  .col-s-9 {width: 75%;}
  .col-s-10 {width: 83.33%;}
  .col-s-11 {width: 91.66%;}
  .col-s-12 {width: 100%;}
}

@media only screen and (min-width: 768px) {
  /* 针对桌面: */
  .col-1 {width: 8.33%;}
  .col-2 {width: 16.66%;}
  .col-3 {width: 25%;}
  .col-4 {width: 33.33%;}
  .col-5 {width: 41.66%;}
  .col-6 {width: 50%;}
  .col-7 {width: 58.33%;}
  .col-8 {width: 66.66%;}
  .col-9 {width: 75%;}
  .col-10 {width: 83.33%;}
  .col-11 {width: 91.66%;}
  .col-12 {width: 100%;}
}

典型的设备断点

css
/* mobile portrait:竖屏移动设备,< 640px */
@media only screen and (max-width: 640px) {...} 

/* mobile landscape:横屏移动设备,> 640px */
@media only screen and (min-width: 640px) {...} 

/* tablet portrait:竖屏平板设备,> 768px */
@media only screen and (min-width: 768px) {...} 

/* tablet landscape:横屏平板设备,> 1024px */
@media only screen and (min-width: 1024px) {...} 

/* laptop:PC电脑,> 1280px */
@media only screen and (min-width: 1280px) {...}

分辨率

在移动端我们通常需要考虑两种分辨率

  • Device resolution:真实设备分辨率,也可以称之为物理分辨率
  • CSS resolution:CSS分辨率,也可以称之为逻辑分辨率

在过去,移动设备的屏幕分辨率都很低,这两种分辨率其实是相同的,但是现在移动设备发展迅速,iPhone4 开始使用高分辨率屏幕,从那开始高分屏变得无处不在,包括平板、笔记本电脑、PC显示器等等,高分屏的出现也带来了CSS适配方面的问题,Device resolutionCSS resolution 变得不再相同,让我们先来理解一下两种分辨率的差别。

CSS分辨率是CSS规则里面用来测量的单位,设备分辨率是屏幕实际的像素点分辨率,这两种分辨率之间存在着一个像素密度的比例,在普通屏幕中这个比例是相同的,而在高分屏中不同。

例如:

  • iphone 8:每个CSS像素对应2个物理像素,它的显示密度为 2x,物理分辨率为 750 x 1334,逻辑分辨率为 375 x 667
  • iPhone 11:每个CSS像素对应2个物理像素,它的显示密度为 2x,物理分辨率为 828 x 1792,逻辑分辨率为 414 x 896
  • iPhone 12:每个CSS像素对应3个物理像素,它的显示密度为 3x,物理分辨率为 1170 x 2532,逻辑分辨率为 390 x 844

2x 屏幕我们也叫它 两倍屏,意味着CSS中一个 1x1 的像素点,将会占用 2x2=4 个物理像素点

3x 屏幕我们也叫它 三倍屏,意味着CSS中一个 1x1 的像素点,将会占用 3x3=9 个物理像素点

三倍屏和两倍屏是目前主流的移动设备屏幕

响应式图片

srcset属性

img 标签的 srcset 属性用来指定多张图像,适应不同像素密度的屏幕,它的值是一个逗号分隔的字符串,每个部分是一张图片的url,后面接一个空格,然后是像素密度描述符,请看下面的例子:

html
<img
  srcset="imgs/google-200w.png,
          imgs/google-400w.png 2x,
          imgs/google-600w.png 3x"
  src="imgs/google-400w.png">

这种像素密度适配的方式,只适合显示区域大小一样的图片,如果我们想要根据屏幕尺寸显示不同的图像,srcset 属性就不够用了,此时可以使用 picture 标签

html
<picture>
  <source srcset="imgs/banner-1920w.jpg" media="(min-width: 1200px)" />
  <source srcset="imgs/banner-1280w.jpg" media="(min-width: 640px)" />
  <img src="imgs/banner-750w.jpg" class="img" />
</picture>

上面代码中,<picture> 标签内部有两个 <source> 标签和一个 <img> 标签,<source> 标签中的 media 属性给出媒体查询表达式,srcset 就是 <img> 标签的 srcset 属性,给出加载的图片文件。

浏览器按照 <source> 出现的顺序,依次判断当前设备是否满足 media 属性的媒体查询表达式,如果满足就加载 srcset 指定的图片,并且不在执行后面的 <source><img><img> 是默认情况下加载的图像,用来满足上面所有 <source> 都不匹配的情况。

使用 width 属性

如果 width 属性设置为百分比,且高度设置为 "auto",则图像将进行响应来放大或缩小:

实例

css
img {
  width: 100%;
  height: auto;
}

使用 max-width 属性

如果将 max-width 属性设置为 100%,则图像将按需缩小,但绝不会放大到大于其原始大小:

实例

css
img {
  max-width: 100%;
  height: auto;
}

背景图像

  1. 如果将 background-size 属性设置为 "contain",则背景图像将缩放,并尝试匹配内容区域。不过图像将保持其长宽比(图像宽度与高度之间的比例关系)
  2. 如果将 background-size 属性设置为 "100% 100%",则背景图像将拉伸以覆盖整个内容区域
  3. 如果将 background-size 属性设置为 "cover",则背景图像将缩放以覆盖整个内容区域。请注意,"cover" 值保持长宽比,且可能会裁剪背景图像的某部分

线条优化

高分屏还带来一个问题,那就是边框的渲染,对于两倍屏来说,如果通过CSS设定了一个 1px 宽的边框,但实际上是占用了2个物理像素点的宽度,这样就会导致边框看起来偏粗,不够细腻,在以前要解决这个问题比较麻烦,通常需要借助于 transform 的缩放来实现,幸运的是,苹果在 iOS8 支持了 0.5px,如今主流平台浏览器都已经能够比较好的支持这个特性,在非高分屏被当作正常的 1px 边框,高分屏则渲染为一个物理像素,看起来非常细腻,无需关心2倍屏还是3倍屏。

css
.hairline {
  border: 0.5px solid #000;
}

rem的运用

现在移动设备种类繁多,而屏幕尺寸也有比较大的差异,像上面提到的几款iPhone分辨率都不一致,通常设计师在设计移动页面时都会有一个参考,比如以 iPhone8750px 宽度为基准来设计尺寸,其他尺寸的移动设备通常分辨率差别不会特别大,此时我们希望在这些设备的屏幕上尺寸可以自动等比例缩放,这样我们就不需要针对每一种移动设备来更改设计尺寸了。

上一次的课我们有讲到,rem 是一种相对于 html 根节点字体大小的尺寸单位,假如 html 标签设置的 font-size10px,那么 1rem 就等于 10px,如果我们把CSS中的绝对尺寸如 px 都换成 rem,然后我们再根据屏幕宽度和原设计图 750px 的比例,动态更改 htmlfont-size 大小,这样我们就可以做到尺寸等比例缩放了。

在我们的 demo 目录中有两个示例页面,基于第一周的任务设计图

  • layout-px.html:使用 px 绝对单位来进行布局,无法随分辨率缩放
  • layout-rem.html:使用 rem 相对单位来进行布局,可以随着分辨率的改变自动缩放

第二个页面相对于第一个页面的区别就是把CSS中的 px 都替换成了 rem,然后通过js脚本动态计算根节点的 font-size,让我们通过开发者工具,切换到响应式设计模式,调整视口大小,可以看到动态的变化。