🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 移动端适配方案 尽管我们可以使用设备独立像素来保证各个设备在不同手机上显示的效果类似,但这并不能保证它们显示完全一致,我们需要一种方案来让设计稿得到更完美的适配。 <br> # flexible方案 `flexible`方案是阿里早期开源的一个移动端适配解决方案,引用`flexible`后,我们在页面上统一使用`rem`来布局。 <br> 它的核心代码非常简单: ~~~ // set 1rem = viewWidth / 10 function setRemUnit () { var rem = docEl.clientWidth / 10 docEl.style.fontSize = rem + 'px' } setRemUnit(); ~~~ <br> `rem` 是相对于`html`节点的`font-size`来做计算的。 <br> 我们通过设置`document.documentElement.style.fontSize`就可以统一整个页面的布局标准。 <br> 上面的代码中,将`html`节点的`font-size`设置为页面`clientWidth`(布局视口)的`1/10`,即`1rem`就等于页面布局视口的`1/10`,这就意味着我们后面使用的`rem`都是按照页面比例来计算的。 <br> 这时,我们只需要将`UI`出的图转换为`rem`即可。 <br> 以`iPhone6`为例:布局视口为`375px`,则`1rem = 37.5px`,这时`UI`给定一个元素的宽为`75px`(设备独立像素),我们只需要将它设置为`75 / 37.5 = 2rem`。 <br> 当然,每个布局都要计算非常繁琐,我们可以借助`PostCSS`的`px2rem`插件来帮助我们完成这个过程。 <br> 下面的代码可以保证在页面大小变化时,布局可以自适应,当触发了`window`的`resize`和`pageShow`事件之后自动调整`html`的`fontSize`大小。 <br> ~~~ // reset rem unit on page resize window.addEventListener('resize', setRemUnit)window.addEventListener('pageshow', function (e) { if (e.persisted) { setRemUnit() } }) ~~~ <br> 由于`viewport`单位得到众多浏览器的兼容,上面这种方案现在已经被官方弃用: <br> > lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方案。 <br> 下面我们来看看现在最流行的`vh、vw`方案。 <br> <br> # vh、vw方案 `vh、vw`方案即将视觉视口宽度 `window.innerWidth`和视觉视口高度 `window.innerHeight` 等分为 100 份。 <br> 上面的`flexible`方案就是模仿这种方案,因为早些时候`vw`还没有得到很好的兼容。 <br> * `vw(Viewport's width)`:`1vw`等于视觉视口的`1%` * `vh(Viewport's height)` :`1vh` 为视觉视口高度的`1%` * `vmin` : `vw` 和 `vh` 中的较小值 * `vmax` : 选取 `vw` 和 `vh` 中的较大值 ![](https://box.kancloud.cn/8f67bc4543260bf64816fabf3bd6d80c_639x686.png) <br> 如果视觉视口为`375px`,那么`1vw = 3.75px`,这时`UI`给定一个元素的宽为`75px`(设备独立像素),我们只需要将它设置为`75 / 3.75 = 20vw`。 <br> 这里的比例关系我们也不用自己换算,我们可以使用`PostCSS`的 `postcss-px-to-viewport` 插件帮我们完成这个过程。写代码时,我们只需要根据`UI`给的设计图写`px`单位即可。 <br> 当然,没有一种方案是十全十美的,`vw`同样有一定的缺陷: <br> * `px`转换成`vw`不一定能完全整除,因此有一定的像素差。 * 比如当容器使用`vw`,`margin`采用`px`时,很容易造成整体宽度超过`100vw`,从而影响布局效果。当然我们也是可以避免的,例如使用`padding`代替`margin`,结合`calc()`函数使用等等... <br> <br> # 参考资料 [关于移动端适配,你必须要知道的](https://juejin.im/post/5cddf289f265da038f77696c)