为所有用户获得最佳体验的设计
可以使用许多不同的设备来查看网页:台式机、平板电脑和手机。无论使用哪种设备,您的网页都应该看起来美观且易用。
网页不应舍弃信息来适合较小的设备,而应使其内容适合任何设备: 如果您使用 CSS 和 HTML 调整大小、隐藏、缩小、放大或移动内容,以使其在任何屏幕上看起来都很好,则称为响应式 Web 设计。
始终移动优先设计
移动优先(Mobile First)指的是在对台式机或任何其他设备进行设计之前,优先针对移动设备进行设计(这将使页面在较小的设备上显示得更快)。
简单来说,你可以采用两种方式来实现响应式设计,你可以从桌面或者最宽的试图开始,然后随着视口变得越来越小,加上断点,把物件挪开;也可以从最小的视图开始,随着视口变得越来越大,增添布局内容,这种移动优先的设计方式,很多时候是最值得仿效的做法。
什么是视口?
视口(viewport)是用户在网页上的可见区域。
视口随设备而异,在移动电话上会比在计算机屏幕上更小。
在平板电脑和手机之前,网页仅设计为用于计算机屏幕,并且网页拥有静态设计和固定大小是很常见的。
然后,当我们开始使用平板电脑和手机上网时,固定大小的网页太大了,无法适应视口。为了解决这个问题,这些设备上的浏览器会按比例缩小整个网页以适合屏幕大小。
这并不是完美的!勉强是一种快速的修正。
设置视口
HTML5 引入了一种方法,使 Web 设计者可以通过 标签来控制视口。
您应该在所有网页中包含以下 视口元素:
<meta name="viewport" content="width=device-width, initial-scale=1.0">它为浏览器提供了关于如何控制页面尺寸和缩放比例的指令。
width=device-width 部分将页面的宽度设置为跟随设备的屏幕宽度(视设备而定)。
当浏览器首次加载页面时,initial-scale=1.0 部分设置初始缩放级别。
把内容调整到视口的大小
用户习惯在台式机和移动设备上垂直滚动网站,而不是水平滚动!
因此,如果迫使用户水平滚动或缩小以查看整个网页,则会导致不佳的用户体验。
还需要遵循的一些附加规则:
请勿使用较大的固定宽度元素 - 例如,如果图像的宽度大于视口的宽度,则可能导致视口水平滚动。请务必调整此内容以适合视口的宽度。
不要让内容依赖于特定的视口宽度来呈现好的效果 - 由于以 CSS 像素计的屏幕尺寸和宽度在设备之间变化很大,因此内容不应依赖于特定的视口宽度来呈现良好的效果。
使用 CSS 媒体查询为小屏幕和大屏幕应用不同的样式 - 为页面元素设置较大的 CSS 绝对宽度将导致该元素对于较小设备上的视口太宽。而是应该考虑使用相对宽度值,例如 width: 100%。另外,要小心使用较大的绝对定位值,这可能会导致元素滑落到小型设备的视口之外。
构建响应式网格视图
响应式网格视图通常有 12 列,总宽度为 100%,并且在调整浏览器窗口大小时会收缩和伸展。计算一列的百分比:100% / 12 列 = 8.33%。
首先,确保所有 HTML 元素的 box-sizing 属性设置为 border-box。这样可以确保元素的总宽度和高度中包括内边距(填充)和边框。
然后,我们为 12 列中的每一列创建一个类,即 class="col-" 和一个数字,该数字定义此节应跨越的列数
.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:
<div class="row">
<div class="col-3">...</div> <!-- 25% -->
<div class="col-9">...</div> <!-- 75% -->
</div>媒体查询
什么是媒体查询?
媒体查询是 CSS3 中引入的一种 CSS 技术。
仅在满足特定条件时,它才会使用 @media 规则来引用 CSS 属性块。
/*如果浏览器窗口是 600px 或更小,则背景颜色为浅蓝色*/
@media only screen and (max-width: 600px) {
body {
background-color: lightblue;
}
}媒体查询基础
上面我们已经简单体验了一下媒体查询的用法,最简单的媒体查询语法看起来像是这样子的:
@media media-type and (media-feature-rule) {
/* CSS rules go here */
}它由以下部分组成:
一个媒体类型,告诉浏览器这段代码是用在什么类型的媒体上的(例如屏幕或者印刷品)
一个媒体表达式,是一个被包含的CSS生效所需的规则或测试
一组CSS规则,会在测试通过且媒体类型正确的时候应用
媒体类型
常见的媒体类型有:
all:所有类型设备print:打印预览模式screen:屏幕设备,是我们最常用的类型
下面的媒体查询会在页面被打印的时候把 body 设定为 12pt 大小,当页面在浏览器载入的时候,他将不会生效
@media print {
body {
font-size: 12pt;
}
}更复杂的媒体查询
前面的例子我们看到,每次只使用了一个媒体特征,但实际上不同的媒体特征可以组合来用,支持“或与非”逻辑判断。
媒体查询中的“与”逻辑
你可以使用 and 来组合媒体类型和特征,例如,我们想要测得 min-width 和 orientation,而 body 的文字只会在视口至少400像素宽,且设备横放时变为蓝色,那么规则可以这么来写:
@media screen and (min-width: 400px) and (orientation: landscape) {
body {
color: blue;
}
}媒体查询中的“或”逻辑
如果你有一组查询,且要其中任何一个都可以匹配的话,那么你可以使用逗号分开这些查询。在下面的例子中,文本会在视口至少400像素宽的时候,或者设备处于横放状态的时候变为蓝色,如果其中一项满足,那么查询就匹配上了。
@media screen and (min-width: 400px), screen and (orientation: landscape) {
body {
color: blue;
}
}媒体查询中的“非”逻辑
你可以用 not 操作符让整个媒体查询失效,这样就直接反转了整个媒体查询的含义,在下面的例子中,文本值会在竖向的时候变为蓝色。
@media not all and (orientation: landscape) {
body {
color: blue;
}
}添加断点
在稍早前,我们制作了一张包含行和列的网页,但是这张响应式网页在小屏幕上看起来效果并不好。
媒体查询可以帮助您。我们可以添加一个断点,其中设计的某些部分在断点的每一侧会表现得有所不同。
/* 针对手机: */
[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%;}
}典型的设备断点
/* 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 resolution 和 CSS 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,后面接一个空格,然后是像素密度描述符,请看下面的例子:
<img
srcset="imgs/google-200w.png,
imgs/google-400w.png 2x,
imgs/google-600w.png 3x"
src="imgs/google-400w.png">这种像素密度适配的方式,只适合显示区域大小一样的图片,如果我们想要根据屏幕尺寸显示不同的图像,srcset 属性就不够用了,此时可以使用 picture 标签
<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",则图像将进行响应来放大或缩小:
实例
img {
width: 100%;
height: auto;
}使用 max-width 属性
如果将 max-width 属性设置为 100%,则图像将按需缩小,但绝不会放大到大于其原始大小:
实例
img {
max-width: 100%;
height: auto;
}背景图像
- 如果将
background-size属性设置为 "contain",则背景图像将缩放,并尝试匹配内容区域。不过图像将保持其长宽比(图像宽度与高度之间的比例关系) - 如果将
background-size属性设置为 "100% 100%",则背景图像将拉伸以覆盖整个内容区域 - 如果将
background-size属性设置为 "cover",则背景图像将缩放以覆盖整个内容区域。请注意,"cover" 值保持长宽比,且可能会裁剪背景图像的某部分
线条优化
高分屏还带来一个问题,那就是边框的渲染,对于两倍屏来说,如果通过CSS设定了一个 1px 宽的边框,但实际上是占用了2个物理像素点的宽度,这样就会导致边框看起来偏粗,不够细腻,在以前要解决这个问题比较麻烦,通常需要借助于 transform 的缩放来实现,幸运的是,苹果在 iOS8 支持了 0.5px,如今主流平台浏览器都已经能够比较好的支持这个特性,在非高分屏被当作正常的 1px 边框,高分屏则渲染为一个物理像素,看起来非常细腻,无需关心2倍屏还是3倍屏。
.hairline {
border: 0.5px solid #000;
}rem的运用
现在移动设备种类繁多,而屏幕尺寸也有比较大的差异,像上面提到的几款iPhone分辨率都不一致,通常设计师在设计移动页面时都会有一个参考,比如以 iPhone8 的 750px 宽度为基准来设计尺寸,其他尺寸的移动设备通常分辨率差别不会特别大,此时我们希望在这些设备的屏幕上尺寸可以自动等比例缩放,这样我们就不需要针对每一种移动设备来更改设计尺寸了。
上一次的课我们有讲到,rem 是一种相对于 html 根节点字体大小的尺寸单位,假如 html 标签设置的 font-size 为 10px,那么 1rem 就等于 10px,如果我们把CSS中的绝对尺寸如 px 都换成 rem,然后我们再根据屏幕宽度和原设计图 750px 的比例,动态更改 html 的 font-size 大小,这样我们就可以做到尺寸等比例缩放了。
在我们的 demo 目录中有两个示例页面,基于第一周的任务设计图
layout-px.html:使用px绝对单位来进行布局,无法随分辨率缩放layout-rem.html:使用rem相对单位来进行布局,可以随着分辨率的改变自动缩放
第二个页面相对于第一个页面的区别就是把CSS中的 px 都替换成了 rem,然后通过js脚本动态计算根节点的 font-size,让我们通过开发者工具,切换到响应式设计模式,调整视口大小,可以看到动态的变化。