1.3 响应式网页呈现
1.3.1 屏幕可视区域viewport
我们往往可以在响应式网页的<head>标签中看到类似这样的语句:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
这个语句中的viewport表示的是屏幕的可视区域。通俗地说,viewport指的就是除去所有工具栏、状态栏、滚动条等之后用于显示网页的区域,这个语句的主要作用就是让当前屏幕可视区域的宽度等于设备的宽度,同时不允许用户手动缩放。这样可以避免浏览器的自动缩放功能给页面浏览带来的不便,因为在很多移动设备上的浏览器都会把自己默认的viewport设为一些大于设备本身屏幕宽度的数值,超过了屏幕本身的默认宽度,例如在iPhone上默认显示的网页区域是980像素。常见设备的默认viewport如表1-4所示。
表1-4 常见设备的默认viewport(屏幕可视区域)
viewport默认值一般大于设备本身屏幕宽度可以增加浏览器显示的范围(见图1-4),这样做虽然可以增加浏览器显示的范围,但因为浏览器可视区域的宽度比默认的viewport值要大,将使得浏览器会出现横向滚动条,有的浏览器会对页面进行自动缩小,使得网页浏览的效果不好。
图1-4 默认的viewport与设备尺寸的对比
为了避免滚动条的出现或页面的自动缩小,可以对viewport的属性进行设置。表1-5列出了viewport的常用属性。其中,width和height属性分别表示窗口显示的最大宽度和高度,initial-scale表示页面的初始缩放值,minimum-scale和maximum-scale则分别表示用户允许的最小和最大缩放值,而user-scalable则用于设置是否允许用户进行缩放操作。所以,以下的语句表示窗口显示的宽度为设备本身宽度,以原始尺寸显示,并且页面不允许缩放,这段代码往往被添加到响应式网页的<head>标签内:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
这种设置可以保证响应式页面能自动根据设备本身的宽度显示最佳的浏览效果,而不至于在某些设备上出现横向滚动条或自动缩小。
表1-5 viewport常用属性
1.3.2 相对大小与绝对大小
页面元素大小的设置也是在响应式网页设计中需要注意的一个问题。我们在以往固定布局的页面中设置页面元素时,往往使用的是绝对大小单位px(像素),但在响应式页面中要适配不同显示环境的显示效果,使用绝对大小显然不能满足需要。因此,页面的元素大小设置最好采用相对大小单位,比如百分比、em、rem等。
这还涉及屏幕物理像素和CSS设置的像素的对应问题。在PC端的浏览器中,CSS的1个像素确实往往都是对应着电脑屏幕的1个物理像素,这可能会造成我们的错觉,让我们觉得对于所有的设备,CSS中的像素都是跟设备的物理像素是一样的。但实际情况却并非如此。在早期的移动设备,比如iPhone 3中,屏幕像素的密度都比较低,那个时候一个CSS像素也是等于1个屏幕物理像素。但后来随着设备显示技术的发展,移动设备的屏幕像素密度越来越高,比如iPhone 4的分辨率比iPhone 3提高了一倍,变成了640像素×960像素,但屏幕尺寸却没变化,这就意味着在同样大小的屏幕上,像素多了一倍,也就是说在iPhone 4中1个物理像素就等于2个CSS像素了。随着移动设备的发展,特别是各种高性能显示设备的出现,像iPhone 6S、三星Galaxy Note 3等设备的屏幕像素密度可以达到3,即1个物理像素等于3个CSS像素,图像的显示会更加精细。所以,现在移动设备的CSS像素与屏幕物理像素的对应关系,因设备的不同而会有差异,而且缩放的操作也可能导致像素的不统一。如果继续使用固定像素作为字体大小,不能保证在不同的设备上网页的显示都能达到较好效果。
em是一个相对字体大小单位。其中“相对”的计算会有一个参考物,一般“相对”所指的是相对于元素父元素的font-size。比如说,如果在一个<div>设置字体大小为“16px”,此时这个<div>的后代元素将继承它的字体大小,除非重新在其后代元素中进行过显示的设置。此时,如果将其子元素的字体大小设置为“0.75em”,那么其字体大小计算出来后就相当于0.75×16px = 12px。
但是使用em也存在一个问题,就因为em是相对于它的父元素来设置字体大小的,这样在进行任何元素设置的时候,都需要参考其上一级父元素的font-size。该元素将继承其父元素的font-size来进行计算,而当前这个父元素又会继承它的上一级父元素的font-size。因此,以em为单位的元素字体大小会受到其任何上一级父元素的影响,如果在当前元素的任意一级父元素中有相关的大小设置,都会使得这个计算变得混乱。
比如,如果在图1-5所示的页面结构中,对于main的div设置了font-size,而这个main的div又在另一个container的div中,如果container也有font-size的设置5em,那么假如当前浏览器默认的字体大小是16px,在container中的字体大小就为16×5=80px,而在main中的字体大小就应该是16×5×5=400px了。实际的显示效果类似图1-6所示。如果div的层次及设置更复杂,这些计算将会更混乱。
图1-5 相对大小em设置示例
图1-6 相对大小em设置的显示效果示例
所以,对于字体的设置可以使用另一个相对大小的单位rem,因为rem是相对于根元素<html>而言的,这样就意味着在计算时只需要参考根元素<html>的相关设置就可以了。
同样是上面这个例子,如果把单位换成rem,每个div的font-size设置如图1-7所示,假如当前浏览器默认的字体大小还是16px,那么在main中的字体大小计算也只是需要参考其根元素16px,也就是16×5=80px,而container中的字体大小是5rem,实际也是16×5=80px。实际显示效果类似图1-8所示。使用rem作为单位,网页中任何字体大小的设置不会对其下一级元素的字体大小的计算和显示造成任何影响,也不会受到除了根元素以外的父元素的设置影响,因为rem这个单位的计算只需要参考其根元素,也就是浏览器本身的默认字体大小。
图1-7 相对大小em设置示例
图1-8 相对大小rem设置的显示效果示例
1.3.3 响应式图像适配
图像是网页中非常重要的元素。如果我们希望网页中的图像在所有的设备上都能达到较好的显示效果,在不同的设备上所显示的图像文件应有所区分。比如对于高像素密度的屏幕,应尽量以高精度的图像显示;而如果是屏幕较小、分辨率较小的屏幕,显示的图像文件的尺寸可以稍微小一点。
实现响应式的图像适配的方法有多种,如果要实现比较复杂的响应式效果,可以借助Bootstrap等已有的响应式框架,而最简单的实现方式,就是使用HTML 5中<img>标签的srcset和sizes属性。
其中,srcset属性用于根据屏幕像素密度或屏幕宽度来匹配不同的图像文件,比如下面这个语句:
<img srcset ="img/1_1280.jpg 3x,img/1_640.jpg 2x,img/1_320.jpg 1x"/>
这个语句表示在屏幕像素密度分别为3倍、2倍和1倍的时候,在这个图像的位置将分别下载对应不同的图像文件。其中,1x、2x和3x分别表示屏幕像素密度的大小,即多少个CSS设置的像素对应屏幕上显示的1个像素,这个倍数越高,屏幕显示的图像精度越大。
除了可以根据屏幕密度来进行图像适配,还可以根据屏幕的宽度来实现。比如这个语句:
<img src="img/1_1280.jpg" srcset ="img/1_1280.jpg 1280w,img/1_640.jpg 640w,img/ 1_320.jpg 320w"/>
这个语句表示将根据屏幕的宽度来进行图像文件的适配,指定了在屏幕宽度分别达到1280wpx、640wpx和320wpx的时候将怎样适配图像文件。
而sizes属性表示可以使用类似媒体查询语句来设置图像的大小。比如以下语句:
<img src="img/1_1280.jpg" sizes="(min-width:1200px) calc(43vw), 50vw"/>
这里表示当屏幕的宽度大于等于1200px时,图像宽度将显示为当前屏幕宽度的43%,就是说假如当前屏幕是1200px,那么图像将显示为1200px的43%,也就是516像素;而后面的50vw则表示当不适配前面的所有条件的显示设置,将图像宽度显示为当前屏幕的50%,比如,当前屏幕宽度如果是1000px,那么图像宽度将显示为1000px的50%,也就是500px。
准备两组图像,图像的宽度分别为1280px、640px和320px。下面是实现图像适配的一个简单示例。
1. 建立页面的主体结构
新建一个空白页面,建立网页的主体结构。为了突出重点,这里先尽量简化网页的结构,在网页中只包含一个导航栏和两个显示图像的区域。HTML页面的代码如下:
<body> <div id="container"> <nav><ul type="none">导航 <li>主页</li> <li>介绍</li> <li>关于</li> <li>联系我们</li> </ul></nav> <main> <div class="pic" ></div> <div class="pic"> </div> </main> </div> </body>
2. 设置每个页面元素的基本CSS样式
添加以下代码到<head>标签中:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> <!-- 响应式网页的可视区域设置 --> <style type="text/css"> / * container的div是最外层的布局。设置它的宽度属性,并设置它居中显示* / #container { width:95%; margin:auto; } / * nav是导航栏。设置它的宽度和左侧间距,并设置它的背景颜色和浮动* / nav{ width:15%; padding-left:1%; background:silver; float:left; } / * main用于显示页面主要内容。设置它的宽度和浮动形式* / main{ width:80%; float:left; } / * pic类用于设置要显示的图像。* / .pic{ width:50%; float:left; } </style>
3. 添加响应式图像
把预先准备的两组图像按存放在特定文件夹(例如当前网站的img文件夹下),在<main>标签的两个div中插入要显示的响应式图像。最好按规律对预先准备的两组图像重命名以方便在网页中调用(比如第1组的3个图像按大小分别命名为1_1280.jpg、1_640.jpg、1_320.jpg)。修改<main>标签对里的代码,具体参考如下:
<!--第1个图像 --> <div class="pic"><img src="img/1_1280.jpg" srcset ="img/1_1280.jpg 1280w,img/1_640.jpg 640w,img/1_320.jpg 320w" sizes="(min-width:1200px) calc(43vw),(max-width:640px) calc(80vw), 60vw"/> <!--可根据需要修改图像存放的位置和图像名称 --> </div> <!--第2个图像 --> <div class="pic" ><img src="img/2_1280.jpg" srcset ="img/2_1280.jpg 1280w,img/2_640.jpg 640w,img/2_320.jpg 320w" sizes="(min-width:1200px) calc(43vw),(max-width:640px) calc(80vw),60vw"/> </div>
其中,<img>的srcset属性设置了在不同的屏幕宽度下图像的适配的图像文件,而sizes属性则设置了在不同屏幕宽度下图像的宽度显示。
4. 添加媒体查询
在<style>标签里原来的样式设置下面添加以下媒体查询设置:
@media screen and (max-width:640px){ / * 当屏幕宽度小于等于640px时,导航栏在页面顶端显示 * / nav{ width:80%; padding-left:2%; background:silver; float:left; } / * 让导航栏中的列表项显示在一行,增加一个display的属性并设置为inline * / #container nav ul li{ display:inline; } / * 清除图像浮动的设置,让每个图像占一行显示 * / .pic{ float:none; } } / * 屏幕宽度不大于1200px时 * / @media screen and (max-width:1200px){ / * 清除图像浮动并设置宽度 * / .pic{ float:none; width:60%; } }
可以在浏览器中查看显示效果。先打开浏览器窗口,把窗口宽度拉到最小。关闭浏览器再重新打开,这时可以看到,在以最小宽度显示网页时网页将先加载最小尺寸的图片。慢慢把浏览器窗口拉宽,可以看到在窗口宽度足够大时,将加载更大尺寸的图片。继续拖动浏览器窗口,当浏览器窗口宽度达到1280px及以上时将加载最大尺寸的图片。使用Google Chrome浏览器测试的效果类似图1-9所示(宽度为1280px的图像没有特别标注)。
图1-9 响应式图像测试结果
5. 按屏幕密度显示对应图片的设置
除了可以根据显示窗口的大小设置图像的显示,还可以根据设备的屏幕像素密度来设置响应式图像。可分别修改两个图像显示的网页代码如下:
<div class="pic" ><img srcset ="img/1_1280.jpg 3x,img/1_640.jpg 2x,img/1_320.jpg 1x" alt="pic1" sizes="(min-width:1200px) calc(43vw),(max-width:640px) calc(80vw),60vw"/> </div> <div class="pic"> <img srcset ="img/2_1280.jpg 3x,img/2_640.jpg 2x,img/2_320.jpg 1x" alt="pic2" sizes="(min-width:1200px) calc(43vw),(max-width:640px) calc(80vw),60vw"/>
这里srcset属性的设置表示,当设备屏幕像素密度为1的时候,将显示320px宽的图像;当屏幕像素密度为2的时候,显示640px宽的图像;当屏幕像素密度为3的时候,显示1280px宽的图像。
在一般的PC屏幕下,都将显示宽为320px的图像。如果要测试按屏幕像素密度设置的响应式图像,可使用浏览器的一些特定设置,比如Google Chrome浏览器的开发者工具。
保存网页并在Google Chrome浏览器打开。如果要测试屏幕密度为2或3的情形,使用组合键【Ctrl+Shift+I】打开“开发者工具”视图,单击“开发者工具”菜单栏中的“Toggle device toolbar”图标,打开模拟移动设备的调试工具,就可以在设备栏切换设备类型,比如iPhone 5、的屏幕像素密度是2,而iPhone 6 Plus的屏幕像素密度是3。切换设备并刷新,就可以测试在不同屏幕密度下的图像显示情况。测试效果如图1-10所示。
图1-10 不同屏幕像素密度下的响应式图像测试结果