Flexible适配方案
最早的文章,是15年阿里手淘团队的移动端适配方案。
设计师常选择iPhone6作为基准设计尺寸,交付给前端的设计尺寸是按750px * 1334px为准(高度会随着内容多少而改变)。
前端开发人员通过一套适配规则自动适配到其他的尺寸。
先了解一些基本概念
视窗viewport
简单理解,viewport是严格等于浏览器的窗口,在桌面浏览器中,viewport就是浏览器窗口的宽度高度。
但是在移动端的viewport太窄,为了能更好的为css布局服务,所以提供了两个viewport:虚拟的viewportvisualviewport和布局的viewportlayoutviewport(了解这两种viewport概念的可以查看这里)
设备像素比(device pixel ratio)
设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。
设备像素比 = 物理像素 / 设备独立像素
在JavaScript中,可以通过`window.devicePixelRatio`获取到当前设备的dpr。而在CSS中,可以通过`-webkit-device-pixel-ratio`,`-webkit-min-device-pixel-ratio`和 `-webkit-max-device-pixel-ratio`进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)
在不同的屏幕上,CSS像素所呈现的物理尺寸是一致的,而不同的是CSS像素所对应的物理像素具数是不一致的。在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素。
所以在移动端除了布局的适配外,还需要考虑到图片的显示质量,这就是我们所说的2倍图或者3倍图
meta标签
viewport的meta标签,主要是用来告诉浏览器如何规范渲染web页面,在开发移动端页面,我们需要设置meta标签为:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
css单位rem
font size of the root element. 来自w3c规范
简单的理解,rem就是相对于根元素<html>的font-size来做计算。而我们的方案中使用rem单位,是能轻易的根据<html>的font-size计算出元素的盒模型大小。
实现方案
手淘团队根据以上的概念,出了一套针对移动端的适配方案`amfe-flexible`库。
使用方法
前提是需要设置页面的viewport
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
然后引入功能文件
# 阿里CDN引入 <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script> # 下载对应的文件,直接在页面中引入。 # 当然也可以 npm i -S amfe-flexible
需要注意的一点那就是:在Flexible中,只对iOS设备进行dpr的判断,对于Android系列,始终认为其dpr为1。
lexible实际上就是能过JS来动态改写meta标签,类似这样:
# 动态改写<meta>标签# 给<html>元素添加data-dpr属性,并且动态改写data-dpr的值# 给<html>元素添加font-size属性,并且动态改写font-size的值
var metaEl = doc.createElement(‘meta‘); var scale = isRetina ? 0.5:1;metaEl.setAttribute(‘name‘, ‘viewport‘); metaEl.setAttribute(‘content‘, ‘initial-scale=‘ + scale + ‘, maximum-scale=‘ + scale + ‘, minimum-scale=‘ + scale + ‘, user-scalable=no‘); if (docEl.firstElementChild) { document.documentElement.firstElementChild.appendChild(metaEl); } else { var wrap = doc.createElement(‘div‘); wrap.appendChild(metaEl); documen.write(wrap.innerHTML); }
接下来要做的事情就是`px`->`rem`
1.可以通过在编辑器中安装插件实现单位的换算
2.可以通过配置postCSS进行自动的单位转换,还按照正常的px进行布局,代码执行后会自动转成对应的rem数值。(具体的配置方法,需要看另外的关于postCSS的文章(待完善))
这套方案,在实际构建M站的过程中,我遇到的一个问题是,1px的border无法正常显示,目前网上没有一个很完美的解决方案,更多提到的是转为svg的方式实现。
不同的终端,我们面对的屏幕分辨率、DPR、1px、2x图等一系列的问题。那么这个布局方案也是针对性的解决这些问题,只不过解决这些问题不再是使用Hack手段来处理,而是直接使用原生的CSS技术来处理的。
vw是基于viewport视窗的长度单位。指的是浏览器可视化的区域,也就是window.innerWidth/window.innerHeight的大小。
1vw = window.innerWidth 的 1%
目前出视觉设计稿,我们都是使用750px宽度的,从上面的原理来看,那么100vw = 750px,即1vw = 7.5px。那么我们可以根据设计图上的px值直接转换成对应的vw值。
这里当然我们也去可以手动去转化单位,但是我们可以在项目的配置项中添加`postCSS`相关的配置,可以为我们自动去转化。我们也只需要按照设计稿给的px去进行布局即可。
下面介绍在`grunt`上配置`postCSS`
安装postCSS插件
# grunt npm install grunt-postcss --save-dev #webpack npm install postcss-loader --save-dev
grunt中配置
在`gruntfile.js`中配置,通过`grunt.loadNpmTasks()`函数加载`grunt-postcss`插件
module.exports = function(grunt) { grunt.initConfig({ postcss:{ options:{ // 配置postCSS所需插件 processors:[ // 这是postCSS插件 // 自动添加前缀 require(‘autoprefixer‘), // 适配方案 require(‘postcss-px-to-viewport‘)({ viewportWidth: 750, viewportHeight: 1670, unitPrecision: 5, viewportUnit: ‘vw‘, selectorBlackList: [], minPixelValue: 1, mediaQuery: false }) ] }, dist:{ // 设置CSS的源文件和postCSS编译后的CSS文件 src: ‘src/style.css‘, // 源文件 dest: ‘dest/style.css‘ // 输出文件 } } }); grunt.loadNpmTasks(‘grunt-postcss‘); }
webpack中配置
配置webpack.config.js(即你的基本公用配置中)
module: { loaders: [ { test: /\.css$/, // 如果使用了 ExtractTextPlugin loader: ExtractTextPlugin.extract(‘style‘, ‘css!postcss‘) // 否则 // loader: "style-loader!css-loader!postcss-loader" } ] }, // 当然,你也可以在根目录下设置.postcssrc.js中添加对postCSS的配置,会自动识别。 postcss: function () { return [ // 里面是我们要用的插件 // 自动添加前缀 require(‘autoprefixer‘), // 适配方案 require(‘postcss-px-to-viewport‘)({ viewportWidth: 750, viewportHeight: 1670, unitPrecision: 5, viewportUnit: ‘vw‘, selectorBlackList: [], minPixelValue: 1, mediaQuery: false }) ]; }
注意的是,配置postCSS插件的时候,需要提前安装依赖。点击这里。看看postCSS的强大之处吧。
针对第二套适配方案,`vw`已经广泛被移动端浏览器良好的支持了。所以几乎是没有什么问题.
现有项目中的适配方案
现有的项目采用的适配方案,其实和第一种的原理是一样的。
// 动态计算px的大小,比如设计稿的尺寸宽是750px (function(dew){ var winW = document.documentElement.clientWidth; var ratio = winW/desW; document.documentElement.style.fontSize = ratio * 100 + ‘px‘; })(750); //在css中对根字体大小进行设置: // html,body{ // font-size:100px; // } // 这样我们在对UI给的尺寸直接除以100,就是对应的rem单位了。
当然,px和rem之间的转换,可以通过编辑器自己的插件,也可以去配置postCSS去自动转换。
总结
PostCSS是一种工具,一款已成长为像Sass和LESS一样主流的处理器,这一切都归功于它的强大、速度和易用性。
将 PostCSS 视为后处理器,或者将其视作是预处理器的相反处理,都是一种误导;PostCSS 有能力应对各种不同的使用场景,既可以处理已经被预处理器编译过的代码,也可以处理纯粹的 CSS 代码;它可以在开发者的开发工作流中处理更多的任务
postCSS其实算不上什么适配方案,1和3两套方案的本质是一样的。至于第2种适配方案,本质就是把我们经常用的rem变成了vw视窗单位。
对于postCSS,这个东西带给了我很多新的关于web自动化流程的设计感想。他可以实现很多我们针对CSS方面兼容性的处理。事实上页面的布局总是令人蛋疼的。但技术是不断革新的,我们可以随着保持对新技术的关注,尝试这些新特性运用到实际项目中,只有这样,我们解决问题的方案才会越来越完善。
原文地址:https://www.cnblogs.com/yangsg/p/10197212.html