适配问题

说起适配,就不得不提到“ 响应式 ”。而说起响应式,可能很多人下意识就会脱口而出:css @media媒体查询
可能还有些人会进一步说出:“利用css的em、rem单位”。

是的,但是你有没有想过一个问题:​​em​​​、​​rem​​​是根据​​px​​​计算得来的;而​​media​​​又“足够复杂” —— 放在一般的项目中还好,如果将css自适应放到淘宝、京东这种极度复杂的场景下,就显得有些束缚了:
因为我们知道,元素大小、位置甚至颜色等的改变都会引起回流重绘!导致页面重新渲染…这对性能是不友好的。

拿​​rem​​​来说,按照 750 宽设计稿基准,rem 的方案为 ​​(尺寸 / (750/等份) ) * html font size​

css单位

上面说到​​em​​​和​​rem​​​是响应式中的一大助力。其实css响应式中还可以用​​vw​​​、​​vh​​​和​​vm​​来实现。这几个单位也是比较常用的几个。但是它们都是有缺点的:

使用px单位

  1. px看似是固定值,但在不同的设备上展现的却是不同的像素。
  2. 带来理解成本,需理解此时的 px 所代替的含义,此时的 px 其实为相对单位。
  3. 不利于后续升级
  • 替换成到其他适配方案。
  • 设计稿基准值变化。

使用 vw 单位

  1. 视窗单位,依赖视口大小;无法单独使用在响应式中(需结合rem等单位进行控制子级)。
  2. 带来理解成本,需理解此时的 vw 所代替的含义。
  3. 目前设计稿采用的是像素单位,开发时需将 px 转换为 vw,会出现无法除尽的浮点数。
  4. 不利于后续升级。

使用 em / rem 单位

  1. 目前设计稿采用的是像素单位,开发时需按照指定的等份将 px 转换为 em / rem。不利于等份的统一管理。
  2. 不利于后续升级。
  3. 兼容性:IE6-8不支持

背景:rpx

在笔者所在的公司有一套内部的“基础库”。里面有一个单位让我非常感兴趣 —— ​​rpx​​​。是一个模仿微信小程序自适应单位的。
开发手册上大概是这么写的:
在你使用​​​rpx​​​时,内部利用 CSS 插件(​​postcss​​​ 插件)将 ​​rpx​​​ 单位转换为 ​​rem​​​,使用 ​​vw​​​ 单位替代 flexible ,结合 ​​media query​​ 适配指定设备。

将 rpx 单位转换为 rem 单位,以 750px 设计稿为基准,转换公式为:原始像素尺寸(rpx) / 100

其实内部还是非常麻烦的。

另一个背景:淘宝

nginx适配杂谈_css

可以看到,淘宝网的页面并不是响应式的(你刷新后相当于是换了个设备重新打开此网页),而是在 PC 和 移动端适配的结果 —— 两套页面,根据环境决定使用不同方案。
它虽然不像响应式那样流畅和足够舒适,但是确实非常方便!

这种方式是由服务器配置实现的。它的关键在于:服务器监控当前环境,如果是 PC 端,则展示一套页面;如果是移动端,则展示另一套。(如果你还想进一步细分,比如 Android 和苹果,也可以再去匹配)
这时,一个轻量高性能的服务器 —— nginx就进入了我的视线!

nginx实现网页适配

首先,我们要在项目目录下同级建立两个文件夹 —— 分别表示pc和移动端:

mkdir pc
mkdir mobile

然后将两套页面代码分别放入两个文件夹下。我们假定html文件名都是​​index.html​​。

然后回到 nginx 服务器根目录的 ​​etc/nginx/conf.d​​文件夹下:

cd etc/nginx/conf.d

建立一个配置文件:

vim shipei.conf
server{
listen 80; # 监听端口
server_name nginx2.jspang.com; # 域名
location / { # 控制访问网站的路径
# root是最上层目录的定义,文件的绝对路径等于 root+location
root /usr/share/nginx/pc;
if (!!($http_user_agent ~* /AppleWebKit.*Mobile.*/)) {
root /usr/share/nginx/mobile;
}
# 在前后端分离的基础上,通过Nginx配置,指定网站初始页。
index index.html;
}
}

​!!($http_user_agent ~* /AppleWebKit.*Mobile.*/)​​​这里是正则表达式,​​$http_user_agent​​​是 nginx 内置指令,表示当前的​​user-agent​​​头。
这里其实也是借鉴了笔者所在公司内部基础库中的一个方法。其实​​​if​​​里还可以这么写:​​$http_user_agent ~* ' Android | webOS | iPhone| iPad | BlackBerry ')​

然后搭配上 viewport 在没有达到页面替换时机时进行缩放:

<meta name="viewport" content="width=320,maximum-scale=1.3,user-scalable=no">

天猫的web app的首页就是采用这种方式去做的,以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416。基本缩放到416都就可以兼容到iphone6 plus的屏幕了,简单粗暴、又高效。