响应式设计和自适应设计
响应式
响应式设计即 RWD(Responsive Web Design),理论上响应式界面能够适配不同的终端,一切能用来为各种分辨率和设备性能优化视觉体验的技术。
自适应
自适应设计即 AWD(Adaptive Web Design),有可能会针对移动端减去内容,减去功能。
两者对比
基础概念
设备独立像素(DIP)
设备独立像素 = CSS像素(px) = 逻辑像素
打开 Chrome 浏览器的开发者工具,使用 Ctrl + Shift + M:
如图所示:375 * 667
就是 iPhone 6/7/8 的设备独立像素。
物理像素
物理像素 = 设备屏幕分辨率
显示屏是由一个个物理像素点组成的,从制成的时刻就固定不变的。
设备像素比(DPR)
设备像素比描述的是未缩放状态下,物理像素和设备独立像素的初始比例关系。
DPR = 物理像素 / 设备独立像素
由此计算公式可以简单计算出 iPhone 6 的 DPR = 1334 / 375 = 2
苹果公司将 dpr > 1
的屏幕称为视网膜屏幕(Retina)
H5 适配的两个维度:
- 适配不同屏幕大小,也就是适配不同屏幕下的 CSS 像素
- 适配不同像素密度,也就是适配不同屏幕下 dpr 不一致导致的一些问题
移动端屏幕适配方案
rem 适配
等比放大(相当于更大的屏幕只是看到更大的内容而不是更多的内容)
rem 就是相对于根元素 html 的 font-size 来做计算,配合 JavaScript 模拟 vw 的特性,属于等比缩放。
当初用于浏览器支持 viewport 特性程度低。
将屏幕宽度等分为 100 份,每一份的宽度用 x 表示;如果将 x 根元素的 font-size
数值,那么子元素的相关属性数值使用 rem
即可随着屏幕等宽变化。
通过使用 Javascript
动态设置 html
的字体大小恒等于屏幕宽度的百分之一,一般需在页面 dom ready、resize
和屏幕旋转中设置:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 100 + 'px';
假设给出的设计图为 750 * 1334
,其中一个元素宽度为 200px
:width: 200 / 750 * 100 = 26.67 rem
优缺点
优点:rem 的兼容性能低到 ios 4.1、android 2.1
缺点:
-
字体大小不能使用 rem(一般使用媒体查询控制
font-size
大小) -
1px 边框在高清屏下的显示问题,需要自行处理
-
在 PC 端浏览会崩坏,一般设置一个最大宽度
let clientWidth = document.documentElement.clientWidth;
clientWidth = clientWidth < 780 ? clientWidth : 780;
document.documentElement.style.fontSize = clientWidth / 100 + 'px';
body {
margin: auto;
width: 100rem;
}
相关技术方案:flexible(amfe-flexible
或者 lib-flexible
) + postcss-pxtorem
vw 适配
- 等比缩放(相当于更大的屏幕只是看到更大的内容而不是更多的内容)
- rem 需要借助 Javascript 进行动态修改根元素的
font-size
,而 vw/vh(vmax/vmin) 的出现则很好弥补 rem 需要 Javascript 辅助的缺点。
根据 CSS Values and Units Module Level 4: vw 等于初始包含块(html元素)宽度的1%,也就是
1vw
等于window.innerWidth
的数值的 1%1vh
等于window.innerHeight
的数值的 1%
rem
适配中的例子:26.67 rem
可换成 26.67 vw
优缺点
优点:CSS 原生支持,而且目前兼容性大多数手机是支持的,也不需要加载 Javascript
缺点:
- 1px 边框在高清屏下的显示问题,需要自行处理
- 在 PC 端浏览会崩坏,一般设置一个最大宽度
相关技术方案:postcss-px-to-viewport
px 适配
px + calc + clamp
适合新闻、社区等可阅读内容较多的场景;大屏用户想要看到更多的内容
按照 750 的设计稿,300 是在 750 中 header
的高度:
/* style.css */
:root {
--ideal-viewport-width: 750;
--current-viewport-width: 100vw;
--min-viewport-width: 320px;
--max-viewport-width: 1440px;
--clamped-viewport-width: clamp(var(--min-viewport-width),
var(--current-viewport-width),
var(--max-viewport-width));
}
body {
width: 100vw;
}
header {
height: calc(300 * var(--clamped-viewport-width) / var(--ideal-viewport-width));
line-height: calc(300 * var(--clamped-viewport-width) / var(--ideal-viewport-width));
text-align: center;
background-color: #f2f2f2;
}
优缺点
优点:解决失去像素的完美性;屏幕低于或高于某个阈值,通常就会出现布局的移动或文字内容的溢出
1px线
UI 稿中 1像素指在 Retina 屏显示1 物理像素宽度,而不是1 CSS 像素宽度
- 在 dpr = 1 时,此时 1 物理像素等于 1 CSS 像素宽度
- 在 dpr = 2 时,此时 1 物理像素等于 0.5 CSS 宽度像素,可以认为
border-width: 1px
这里的 1px 其实是 1 CSS像素宽度,等于 2 像素物理宽度,设计师其实想要的是border-width: 0.5px
- 在 dpr = 3 时,此时 1 物理像素等于 0.33 CSS 宽度像素,设计师其实想要的是
border-width: 0.333px
使用 0.5px
吗?iOS 8及以上,苹果系统支持;但是 iOS 8以下和 Android(部分低端机),会将0.5px
显示为 0px
方案
渐变实现
- background-image: linear-gradient()
使用缩放实现
- transform: scaleY()
使用图片实现
- base64
使用 SVG 实现
- 嵌入 background url
border-image
- 低端机下支持度不好
以上都是通过 CSS 的媒体查询来实现的
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min-device-pixel-ratio: 2) {}
@media only screen and (-webkit-min-device-pixel-ratio: 3),
only screen and (min-device-pixel-ratio: 3) {}
图片适配
- 消除多余的图像资源
- 尽可能利用 CSS3\SVG 矢量图像替代某些光栅图像(jpg\png)
- 谨慎使用字体图标,使用网页字体取代在图像中进行文本编码
- 选择正确的图片格式
- 为不同 DPR 屏幕提供最适合的图片尺寸
srcset
<div class='illustration'>
<img src='illustration-small.png'
srcset='images/illustration-small.png 1x,
images/illustration-big.png 2x'
style='max-width: 500px'/>
</div>
上面 srcset
里的 1x,2x 表示 像素密度描述符,表示
- 当屏幕的 dpr = 1 时,使用
images/illustration-small.png
- 当屏幕的 dpr = 2 时,使用
images/illustration-big.png
字体适配
字体大小
浏览器有最小字体限制
- PC上最小
font-size = 12px
- 手机上最小
font-size = 8px
字体的选择展示
- 使用系统字体能更好的与当前操作系统使用的相匹配
- 使用各个支持平台上的默认系统字体