适配移动端不同屏幕尺寸是移动 H5 开发的关键环节,下面提到的四种主流方案分别做详细讲解、适用场景分析与代码示例。
viewport
设置缩放(基础适配)控制页面在不同设备上的初始缩放、缩放行为。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
width=device-width
:页面宽度为设备宽度initial-scale=1.0
:初始缩放为 100%user-scalable=no
:禁止双指缩放rem
+ flexible.js
或 postcss-pxtorem
rem
的 font-size,CSS 用 rem 编写// flexible.js,iPhone 375px 下 = 1rem = 37.5px
(function () {
const setRem = () => {
const width = document.documentElement.clientWidth
document.documentElement.style.fontSize = (width / 10) + 'px'
}
setRem()
window.addEventListener('resize', setRem)
})()
/* 等价于 16px 字体 */
.title {
font-size: 0.4267rem;
}
// postcss.config.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5, // iPhone 375px 为基准
propList: ['*'],
},
},
}
media query
根据屏幕宽度设置不同的样式,适配多个断点(响应式设计)。
/* 小屏幕(<=375px) */
@media screen and (max-width: 375px) {
.box {
font-size: 14px;
}
}
/* 中等屏幕(<=768px) */
@media screen and (max-width: 768px) {
.box {
font-size: 18px;
}
}
vw
/ vh
百分比布局1vw = 1%
的视口宽度,1vh = 1%
的视口高度.banner {
width: 100vw;
height: 50vh;
font-size: 4vw; /* 自适应字体 */
}
场景 | 推荐方案组合 |
---|---|
设计稿精细适配 | ✅ viewport + rem + flexible 或 postcss-pxtorem |
响应式 PC + 移动 | ✅ viewport + media query + vw |
营销页、展示页 | ✅ vw/vh + 视觉还原,适配成本低 |
与 UI 框架共用 | ✅ postcss-pxtorem + Vant UI(默认 rem 单位) |
以下是一个基于 Vite + Vue 3 + postcss-pxtorem + Vant UI 的移动端 H5 项目适配模板结构,适配方式为 设计稿宽度 375px → rem 单位,用于高保真还原设计图的移动页面开发。
my-h5-app/
├─ public/
├─ src/
│ ├─ assets/
│ ├─ components/
│ ├─ pages/
│ │ ├─ Home.vue
│ ├─ App.vue
│ ├─ main.ts
├─ index.html
├─ vite.config.ts
├─ postcss.config.js
├─ package.json
postcss.config.js
– 设置 px → rem 转换module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5, // 设计稿为 375px 时,1rem = 37.5px
propList: ['*'],
selectorBlackList: ['ignore-'], // 忽略特定类名
},
},
}
vite.config.ts
– 自动引入 Vant 样式(按需加载)import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
],
})
main.ts
– 引入 lib-flexible
设置根 font-sizeimport { createApp } from 'vue'
import App from './App.vue'
import 'lib-flexible/flexible' // 自动根据屏幕宽度设置 font-size
import 'vant/lib/index.css'
createApp(App).mount('#app')
Home.vue
– 页面示例(使用 rem 单位)<template>
<div class="home">
<van-button type="primary">主要按钮</van-button>
<p class="desc">欢迎来到移动端页面</p>
</div>
</template>
<style scoped>
.home {
padding: 1rem;
}
.desc {
font-size: 0.4267rem; /* ≈16px */
}
</style>
1rem = 37.5px
rem
单位(自动由 postcss-pxtorem
转换)lib-flexible
自动设置 html 的 font-size
.ignore-padding
规避某些元素转换页面 | 显示尺寸 | 缩放效果 |
---|---|---|
iPhone 12 | 375 x 812 | 完全 1:1 高保真适配 |
小米 / 安卓机 | 360 x 800 | 自动按比例缩放 |
iPad / 横屏 | 响应式居中 | 根据屏幕缩放适应 |
rem
相关原理详解(H5 适配核心)rem
(root em)是相对于根元素
的字体大小进行缩放的单位。html { font-size: 37.5px }
,那么 1rem = 37.5px
。<style>
html { font-size: 37.5px }
.box { width: 2rem }
style>
当设备宽度变化时,通过动态修改 的
font-size
,从而让所有使用 rem 的元素按比例缩放,实现屏幕适配。
// flexible.js 简化版
function setRem() {
const designWidth = 375
const width = document.documentElement.clientWidth
document.documentElement.style.fontSize = (width / designWidth) * 37.5 + 'px'
}
window.addEventListener('resize', setRem)
setRem()
原理是:设计稿尺寸 ➗ 10 = 每屏 10rem,每个 rem 就是视口宽度的 1/10
特性 | 优势说明 |
---|---|
适配灵活 | 不同屏幕上字体、间距自动缩放 |
样式结构清晰 | 无需频繁写媒体查询 |
兼容 UI 框架 | 与 Vant 等框架天然配合使用 |
的 font-size
对比项 | rem + flexible | vw/vh |
---|---|---|
原理 | 设置 html font-size,rem 缩放 | 使用 viewport 宽高百分比单位 |
灵活性 | 高,需要 JS 设置字体 | 高,纯 CSS 无需 JS |
兼容性 | 高,兼容旧安卓、Safari | 部分旧设备或 iOS 微信可能失效 |
项目适用 | 设计稿还原度要求高(B 端/C 端) | 展示页、横屏适配(营销页) |
// postcss.config.js
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*'],
}
px(设计稿) | 换算公式 | 结果(rem) |
---|---|---|
16px | 16 ÷ 37.5 = 0.4267rem | 0.4267rem |
75px | 75 ÷ 37.5 = 2rem | 2rem |
可以,推荐策略:
.card {
width: 90vw;
padding: 0.5rem;
font-size: 0.4rem;
}
selectorBlackList
忽略样式转换:selectorBlackList: ['van-', 'ignore-']
class="ignore"
,不参与 px → rem 转换rem + postcss-pxtorem + flexible.js
做移动端适配时常见的坑和排查指南,包括渲染异常、缩放不一致、组件错位、字体偏大偏小等典型问题。
rem
,但
没有设置 font-size
或设置不生效。lib-flexible
或自行实现动态设置:document.documentElement.style.fontSize = window.innerWidth / 10 + 'px'
postcss-pxtorem
:npm install postcss-pxtorem -D
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*'], // 转换所有属性
}
}
}
vant
, element-plus
中某些样式不兼容 rem。selectorBlackList
忽略转换:selectorBlackList: ['van-', 'el-']
.ignore-*
类名过滤clientWidth
计算 rem 值,不同设备分辨率计算偏差viewport
结合 lib-flexible
且不要设置 maximum-scale
:<meta name="viewport" content="width=device-width, initial-scale=1.0">
viewport-fit=cover
需额外适配刘海屏/安全区font-size
存在系统默认缩放html {
-webkit-text-size-adjust: 100% !important;
text-size-adjust: 100% !important;
}
vh
,iOS 微信 Webview 中 vh
表现异常100vh
,改为动态计算实际可视高度:document.documentElement.style.setProperty('--vh', window.innerHeight * 0.01 + 'px')
然后在 CSS 中用:
.modal {
height: calc(var(--vh, 1vh) * 100);
}
场景 | 建议方案 |
---|---|
rem 不生效 | 检查是否动态设置了 html 的 font-size |
px 没被转 rem | 检查 postcss-pxtorem 安装和配置 |
第三方样式错乱 | 添加 selectorBlackList 忽略转换 |
字体放大、偏移 | 添加 text-size-adjust: 100% 防止缩放干扰 |
微信中滚动问题、全屏异常 | 避免使用 100vh,动态计算可视高度 |