吃透移动端 Html5 响应式布局
Posted 前端大联盟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了吃透移动端 Html5 响应式布局相关的知识,希望对你有一定的参考价值。
茫茫人海中与你相遇
相信未来的你不会很差
来源:https://www.jb51.net/html5/706445.html
问题
全文将围绕下面几个问题进行论述和展开:
写移动端H5 相关页面,相比 PC 端有哪些值得注意的点?
关于H5 响应式布局有哪些解决方案?
什么是 rem?如何在项目中完美使用它?
vh/vw 是最佳解决方案吗?它有什么优势和缺陷 大型开源库里面常用解决方案是什么?
怎样快速搭建一套移动端布局解决方案?
概念
什么是 H5 技术?
这是我给公司同事普及 H5 知识绘制的图像。
移动端 web 和 PC web 的区别
PC 端我们是怎么布局的呢?一般采用两种方案,一种是 min-width 限制最小的宽度,浏览器宽度小于 min-width 就直接滚动。另外一种呢,就是留白。设置页面一个基础宽度,超出的部分留白。
但是这两种解决方案在移动端可行吗?
移动端手机的宽度,大多不一致,而且没办法进行窗口的缩放。让移动端产生滚动,体验更加糟糕,更别说和原生 app 性能相比较,基本页面展示体验就很差了。
那么留白呢?更不可行了,手机设备本身宽度就小,再留白就基本看不了什么了。
所以为了让这种 web 能够像原生 app 一样的体验,就出现了 H5 技术。进一步衍生了 Hybird , 虽然比不上 app 性能,但是在 热更新 上占有绝对优势,有着原生无法替代的地方。
下面我们来就来实践下 H5 最基本的技术之一 移动端响应式布局 。
实践
css 中用于计量的单位有两种,一种是 绝对单位 ,另一种是相对单位
绝对单位
对于绝对单位,一般来说常用的也就 px, 其他的可能打印需要用到
相对单位
对于相对单位来说, em 和 rem属于一对, vw 和 vh属于一对。
前一对相对于 字体大小 ,区别在于 rem 相对于 根字体 ,对于我们控制整体的大小相对容易些,所以我们可以使用它来控制整个页面的缩放。
后一对,相对于视窗的大小,这个将在下一个节中发挥主要作用。
解决方案一:rem + pxToRem
原理
监听屏幕视窗的宽度,通过一定比例换算赋值给 html 的 font-size 。此时,根字体大小就会随屏幕宽度而变化。
将px转换成 rem , 常规方案有两种,一种是利用 sass / less 中的自定义函数 pxToRem ,写 px 时,利用 pxToRem 函数转换成 rem 。另外一种是直接写 px ,编译过程利用插件全部转成 rem 。这样 dom 中元素的大小,就会随屏幕宽度变化而变化了。
实现
动态更新根字体大小
const MAX_FONT_SIZE = 420
// 定义最大的屏幕宽度
document.addEventListener('DOMContentLoaded', () => {
const html = document.querySelector('html')
let fontSize = window.innerWidth / 10
fontSize = fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : fontSize
html.style.fontSize = fontSize + 'px'
})
px 转 rem
pxToRem 方案一
$rootFontSize: 375 / 10;
// 定义 px 转化为 rem 的函数
@function px2rem ($px) {
@return $px / $rootFontSize + rem;
}
.demo {
width: px2rem(100);
height: px2rem(100);
}
pxToRem 方案二
vue-cli3 中配置 装 postcss-pxtorem 插件就可以了,其他平台大致差不多
const autoprefixer = require('autoprefixer')
const pxtorem = require('postcss-pxtorem')
module.exports = {
// ...
css: {
sourceMap: true,
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtorem({
rootValue: 37.5,
propList: ['*']
})
]
}
}
}
}
继续探索postcss-pxtorem 插件源码,查看它实现的原理
function createPxReplace (rootValue, unitPrecision, minPixelValue) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels < minPixelValue) return m;
var fixedVal = toFixed((pixels / rootValue), unitPrecision);
return (fixedVal === 0) ? '0' : fixedVal + 'rem';
};
}
px 变换成 rem 主要是这个函数,当然里面有很多可配置的参数, 核心原理和我们方案一差不多,方便在于,不需要每次写 px 都要加上一个函数,代码也清晰很多
是不是所有元素 px 都要转换成 rem 呢?,那可不一定哦, border 中的 px 不应该转 rem,涉及到另外一个 1px 的问题,上一篇文章详细论述过,避免 px 转 rem ,将 border 中的 px 大写成 PX/Px/pX
解决方案二:vh + vw
原理
vw相对于视窗宽度的单位,随宽度变化而变化。由此看来,方案一其实是方案二的一种 Hack, 通过使用监听实现了方案二的效果
实现
与rem类似做法,直接使用postcss-px-to-viewport 插件进行配置, 配置方式也是和 postcss-pxtorem 大同小异
我们看看插件的原理是不是也是一样的
function createPxReplace(opts, viewportUnit, viewportSize) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels <= opts.minPixelValue) return m;
var parsedVal = toFixed((pixels / viewportSize * 100), opts.unitPrecision);
return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
};
}
果然呢,连方法名、变量名、代码逻辑,都一摸一样哈哈哈,谁抄谁,我就不指出来啦 - -
方案 | 缺陷 | |
---|---|---|
1 | 百分比 | 高度无法百分比 |
2 | 媒体查询 + meta 中 viewport | 不同设备宽度不同,缩放比无法完全确定 |
3 | flex | 还是无法解决宽度超出问题 |
上面方案均存在致命缺陷,不推荐使用它完成移动端布局计算。
flex 与 rem 结合使用更佳
兼容性
上述两种方案, 兼容性主要在于 rem,vh,vw 关键词上
rem 在移动端表现高达 100%,令人惊叹!
vh vw表现还是比较令人满意,低版本的 safari 情况下会有兼容性问题,但不影响它会成为一种比较好的移动端布局解决方案。
vant 组件库
px
做计量单位,如果需要使用
rem
,直接使用插件完美适配。
vw
方案,vant 也是可以通过插件将
px
转成
vw
,对于
vw
可能会存在一些坑点。
px
单位
vant
组件一样, 还是由开发者来决定到底用哪一种方案 这种把选择权交给开发者,算是一种开源库的最灵活的做法了 。我们在虚拟的空间与你相遇,期待可以碰撞出不一样的火花
以上是关于吃透移动端 Html5 响应式布局的主要内容,如果未能解决你的问题,请参考以下文章