在 Viewport 等比适配始末 说过使用 Viewport 来实现等比适配的例子,本文详解等比适配的另外一种方式javascript
拿到一个宽度为 vWidth 的视觉稿
设设备屏幕宽度为 dWidth
在视觉稿上量得一个元素的宽度为 eleVWidth
那么要实现按照宽度等比适配,在各类设备中元素的实际宽度 x 将知足公式css
//等比
eleVWidth/vWidth = X/dWidth;
//咱们的目的是求X
X = (eleVWidth/vWidth)dWidth;复制代码
拿到视觉稿以后,eleVWidth 和 vWidth 都已经固定了,可是 dWidth 在不一样的设备中确实不一样的,并且须要实际运行的时候咱们才能拿到 dWidth,这个时候就要利用 rem 的特性了,咱们经过阻塞运行的 js 动态设置 rem,使得rem=dWdith/10
,套入刚才的公式:html
X=(eleVWidth/vWidth)*10*rem
//体如今css中
.className {
width: (eleVWidth/vWidth)*10 rem
}复制代码
为何设置是 dWdith/10 呢?方便计算而已,固然也能够除以别的基数,可是尽可能不要让 rem 过小,有兼容性问题java
这段 css 须要放在 body 标签的开始位置,由于 rem 值要尽量早的设置成功,避免无谓的重排重绘(有些设备中若元素样式已经生效,动态改变 rem 未必能起做用,因此这个动做更须要提早)android
<body>
<script> (function() { var ua = window.navigator.userAgent; var docEl = document.documentElement; var html = document.querySelector('html'); var isAndorid = /Android/i.test(ua); var dpr = window.devicePixelRatio || 1; var rem = docEl.clientWidth / 10; // 设置 rem 基准值 html.style.fontSize = rem + 'px'; // Nexus 5 上 rem 值不许, // 如:设置100px,getComputedStyle 中的值却为 85px,致使页面错乱 // 这时须要检查设置的值和计算后的值是否同样, // 不同的话从新设置正确的值 var getCPTStyle = window.getComputedStyle; var fontSize = parseFloat(html.style.fontSize, 10); var computedFontSize = parseFloat(getCPTStyle(html)['font-size'], 10); if (getCPTStyle && Math.abs(fontSize - computedFontSize) >= 1) { html.style.fontSize = fontSize * (fontSize / computedFontSize) + 'px'; } // 设置 data-dpr 属性,留做的 css hack 之用 html.setAttribute('data-dpr', dpr); // 安卓平台额外加上标记类 if (isAndorid) { html.setAttribute('data-platform', 'android'); } })(); </script>
...
</body>复制代码
若是每在视觉稿上量出一个值,在写到样式文件以前都得经过那个公式计算一翻,那绝对不是一个好策略,咱们但愿量到啥就写啥webpack
使用 less,sass 等 css 预处理器的函数web
//设计稿为640
@function rem($val) {
@return $val/64 * 1rem;;
}
//设计稿为750
@function rem750($val) {
@return $val/75 * 1rem;
}
//使用
.className {
width: @rem(100);
}复制代码
也可使用 webpack-loader,例如:change-rem-loader,这个 loader 代码作的事也是上述的转化计算(写一个 webpack loader 并不复杂,你能够本身写一个符合本身状况的 loader)npm
'use strict';
module.exports = function(source) {
source = source.replace(/rem(\d*)\((.*?)\)/g, function(match, type, value) {
var divVal;
// 不作 try catch,及早发现错误以避免形成故障
switch (type) {
// 1080宽度的设计稿,rem1080(value)
case '1080':
divVal = 108;
break;
// 默认为750宽度的设计稿,rem(value)
case '750':
divVal = 75;
break;
default:
divVal = 64;
}
return (value / divVal).toFixed(6) + 'rem';
});
return source;
}复制代码
这样以后,咱们 css 一样能够这样写(如何让 loader 起做用不是本文的范围)sass
.className {
width: rem(100);
}复制代码
也许你的工程技术栈里面,使用的不是 webpack,也没有使用 less、sass 等预处理器,那你能够根据你的实际状况去寻找一种预处理方案,只要达到推导公式的效果就能够了。
什么?没有合适的方案,那你是时候充充电了less
期待您的关注~~