meta viewport
首先要给项目的 index.html 添加 meta viewport:
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
rem 适配方案
核心原理
- 根据屏幕宽度,使用 JS 动态设置根元素(
html)的font-size,让rem单位随屏幕宽度等比例变化。 - 开发时写
px单位,通过 PostCSS 插件自动转换为rem。
实现步骤
-
安装并配置 PostCSS,将
px转成rem。npm install -D postcss postcss-pxtorem// postcss.config.ts export default { plugins: { 'postcss-pxtorem': { rootValue: 37.5, // 设计稿宽度的 1/10(375px/10=37.5) propList: ['*'], // 需要转换的 CSS 属性,* 表示全部 exclude: /node_modules/i, // 排除第三方库(如 UI 组件库) minPixelValue: 1 // 最小转换像素值,小于 1px 不转换 } } } -
动态设置根元素字体大小。
方式一:手写 JS 计算逻辑。
// 动态计算并设置 html 的 font-size function setRemUnit() { const docEl = document.documentElement; // 获取视口宽度,限制最大宽度避免大屏设备元素过大 const width = Math.min(docEl.clientWidth, 750); docEl.style.fontSize = (width / 10) + 'px'; } // 初始化执行 setRemUnit(); // 屏幕旋转、窗口大小变化时重新计算 window.addEventListener('resize', setRemUnit); // 页面从后台切换到前台时重新计算 window.addEventListener('pageshow', (e) => { if (e.persisted) setRemUnit(); });方式二:使用 lib-flexible。
npm install amfe-flexible// main.ts 引入 import 'amfe-flexible/index.js'
vw 适配方案
核心原理
- 使用 CSS 原生支持的视口单位(
vw),纯 CSS 实现适配。 - 开发时写
px,通过 PostCSS 自动转换为vw。
实现步骤
安装并配置 PostCSS,将 px 转换为 vw。
npm install -D postcss-px-to-viewport
// postcss.config.ts
export default {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px', // 需要转换的单位(默认 px)
viewportWidth: 375, // 设计稿宽度(必须与设计稿一致)
unitPrecision: 6, // 转换后的精度(保留 6 位小数)
propList: ['*'], // 需要转换的 CSS 属性
viewportUnit: 'vw', // 目标转换单位
fontViewportUnit: 'vw', // 字体的目标转换单位
selectorBlackList: ['.ignore', '.hairlines'], // 忽略转换的类名
minPixelValue: 1, // 最小转换像素值
mediaQuery: false, // 是否转换媒体查询中的 px
exclude: /node_modules/i, // 排除第三方库
landscape: false // 是否处理横屏场景
}
}
}
1px 边框问题
原因:物理像素(屏幕上的实际像素点)与 CSS 像素(写 CSS 时的 px 单位)不匹配。
- 在普通屏(dpr = 1)上:1 个 CSS 像素 = 1 个物理像素,视觉上 1px 就是 1px 的边框。
- 在高清屏(dpr = 2)上:1 个 CSS 像素 = 2 个物理像素,视觉上 1px 就是 2px 的边框。
dpr 是“设备像素比”,
dpr = 物理像素宽度 / CSS 像素宽度。如 iPhone 6/7/8(Retina 屏),
dpr = 750(物理宽度)/ 375(CSS 宽度)= 2。
实现:利用 伪元素 + 缩放 实现 1px 边框。
.card {
position: relative;
&::after {
content: '';
position: absolute;
width: 200%;
height: 200%;
border: 1px solid red;
transform: scale(0.5);
transform-origin: 0 0;
}
}
大屏适配限制
现象:由于页面元素大小会根据屏幕宽度动态缩放,导致在平板等大屏幕设备上页面元素显示得很大,不利于美观和使用的便利性。
解决方案:可配合使用媒体查询固定页面最大宽度(如 max-width: 750px),rem 方案还需要限制根元素字体大小,避免元素过大。
@media (min-width: 750px) {
html {
// !important 覆盖 JS 动态设置
font-size: 75px !important;
}
#root {
max-width: 750px;
margin: 0 auto;
}
}