
每次面试前端问到屏幕分辨率适配十个人里有八个能背出 rem 和 vw但真到项目里设计稿一给、测试机一换页面要么横向滚动要么字体大得离谱要么大屏图表鼠标悬浮位置对不上。屏幕分辨率适配不是背几个 CSS 单位就完事它牵扯到物理像素、CSS 像素、设备像素比、视口、断点、缩放策略以及不同端之间的取舍。我做前端这些年从官网、后台管理系统、移动端 H5 到大屏可视化都踩过坑下面就把 PC 和手机常见分辨率、前端到底该怎么适配以及几个能直接抄作业的方案一次讲透。不管你是刚入行的前端还是正在准备 2026 前端面试题或者手头正接了一个 vue3 element plus 自适应大屏方案这篇内容都能让你少走弯路。1. 分辨率基础物理像素、CSS像素与DPR的三角关系1.1 PC与手机常见分辨率速查表很多人第一次接触适配是被设计稿搞懵的设计师给了一张 750px 宽的图可手机明明写着 1920×1080这俩到底啥关系要回答这个问题得先把“分辨率”拆成三层来看。第一层是物理分辨率也就是屏幕硬件上真实存在的发光点数量。比如 iPhone 12 的 1170×2532意思是横向有 1170 个物理像素点纵向有 2532 个。第二层是逻辑分辨率也叫 CSS 像素分辨率是浏览器布局时用的单位。iPhone 12 的逻辑宽度是 390px高度 844px。第三层就是设备像素比 DPR它等于物理像素除以 CSS 像素。1170 ÷ 390 3所以 iPhone 12 的 DPR 是 3。前端在 CSS 里写 1px在 DPR3 的屏幕上实际占用了 3 个物理像素这也是为什么 Retina 屏上 1px 边框看起来比设计稿粗的原因。下面这张表是我平时做项目时整理的常见设备分辨率建议收藏设备类型代表设备物理分辨率DPRCSS 视口宽度PC 普通屏办公显示器1920×108011920PC 普通屏笔记本1366×76811366PC 高分屏2K 显示器2560×14401 或 1.252560 / 2048Mac 笔记本MacBook Air2560×160021280Mac 笔记本MacBook Pro 143024×196421512手机iPhone SE750×13342375手机iPhone 12/131170×25323390手机iPhone 14 Pro Max1290×27963430安卓手机常见 1080P1080×23402.75393安卓手机常见 2K1440×32003.5411大屏拼接屏单屏1920×108011920大屏4K 大屏3840×216021920从表里能看出一个关键点物理分辨率高不代表 CSS 视口宽。iPhone 14 Pro Max 物理宽度 1290但 CSS 宽度只有 430。前端做移动端适配时真正要关心的是 CSS 视口宽度而不是物理分辨率。你写width: 375px在 iPhone 12 上刚好占满在 iPhone 14 Pro Max 上就会空出一截因为它的 CSS 宽度是 430。那怎么在代码里拿到 DPR 和视口宽度很简单// 获取设备像素比 const dpr window.devicePixelRatio || 1; // 获取 CSS 视口宽度 const viewportWidth document.documentElement.clientWidth; console.log(DPR:, dpr, CSS视口宽度:, viewportWidth);这两个值在适配中会反复用到。DPR 决定了 1px 边框怎么处理、图片要不要上 2x/3x视口宽度决定了 rem 基准值和大屏缩放比例。1.2 为什么设计稿总是750或375做过移动端的人一定见过 750px 的设计稿尤其早几年设计师默认就出 750。这个数字不是拍脑袋来的它对应的是 iPhone 6/7/8 的物理宽度 750px。这几款设备的 DPR 是 2所以 CSS 宽度是 375px。设计师用 750 出图是为了在 Retina 屏上让标注更精细前端拿到标注后统一除以 2 就能得到 CSS 像素值。后来 iPhone X 及以后机型 CSS 宽度变成 375、390、414、430 不等设计稿也开始出现 375、390、414 等宽度。现在比较规范的做法是移动端设计稿以 375 为基准或者以 750 为基准但明确标注倍率。如果设计师给的是 750前端在写样式时心里要有一根弦标注 100px实际 CSS 写 50px。这也是为什么早期 rem 方案里rootValue 经常设成 37.5——因为 750 设计稿下1rem 37.5px 设计稿像素对应 CSS 像素就是 37.5 / 2 18.75这里容易绕后面讲 rem 时会详细算。PC 端设计稿则通常是 1920px 宽因为主流桌面显示器 CSS 宽度就是 1920。后台管理系统、官网、大屏可视化大多以 1920 为基准。也有用 1440 或 1366 的但 1920 最通用。如果设计师给的是 2560 的设计稿那就要在 1920 屏幕上做等比缩放或者用响应式断点重新布局。注意拿到设计稿第一件事不是打开编辑器写代码而是问清楚设计稿宽度、基准设备、是否需要适配到 1366 这种低分辨率。这三个问题问完方案基本就定了。1.3 视口viewport前端适配的起点移动端适配绕不开meta viewport。在 PC 浏览器里视口就是窗口大小但在手机浏览器里视口有三层概念布局视口、视觉视口、理想视口。布局视口是浏览器默认用来布局页面的宽度早期手机浏览器默认布局视口是 980px所以那时候用手机打开 PC 网站页面会缩得很小需要手动放大。视觉视口是用户当前看到的区域。理想视口则是让布局视口等于设备 CSS 宽度的那个状态。我们写meta nameviewport contentwidthdevice-width, initial-scale1.0就是告诉浏览器布局视口宽度等于设备宽度初始缩放为 1。这样一来在 iPhone 12 上布局视口就是 390px你写width: 390px就能占满屏幕。现在更完整的写法会加上maximum-scale、user-scalable和viewport-fitmeta nameviewport contentwidthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalableno, viewport-fitcoverviewport-fitcover是为了适配 iPhone 刘海屏和底部小黑条配合env(safe-area-inset-*)使用。user-scalableno可以禁止用户缩放但要注意可访问性争议很多团队现在不再强制禁止缩放除非是游戏或特定交互场景。maximum-scale1.0在 iOS 10 之后会被忽略所以别把它当成万能锁。在 PC 端meta viewport基本不需要因为浏览器窗口就是视口。但如果你在做响应式官网希望同一套页面在手机和 PC 都能看那就必须加上。PC 端更依赖的是媒体查询和弹性布局后面会展开。2. 移动端适配meta viewport、rem与vw的选型实操2.1 meta viewport的正确写法和常见坑移动端适配第一步永远是meta viewport。我见过不少项目CSS 写得花里胡哨结果忘了加这行页面在手机上直接以 980px 布局用户体验极差。正确的写法前面已经给了这里重点说几个坑。第一个坑在 Vue/React 项目里index.html只写一次但微前端子应用可能重复写。如果你在用 qiankun 微前端入门主应用已经设置了 viewport子应用就不要再设置否则可能冲突。主应用统一设置子应用只管在自己的根元素里做样式隔离。第二个坑viewport-fitcover不是所有浏览器都支持。写的时候要同时写constant()和env().footer { padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); }constant()是 iOS 11.0-11.2 的写法env()是 11.2 的标准写法。两个都写上兼容性最好。第三个坑横竖屏切换时视口宽度会变但页面不会自动重新计算 rem。如果你用 rem 方案需要监听orientationchange或resize延迟重新设置根字号。代码window.addEventListener(orientationchange, () { setTimeout(() { setRem(); }, 300); });延迟 300ms 是因为部分安卓机在横竖屏切换时clientWidth更新有延迟立即读取会拿到旧值。2.2 rem适配动态font-size与postcss-pxtoremrem 是移动端最经典的适配方案。它的核心思想是把设计稿里的 px 按比例转换成 rem然后根据设备宽度动态设置根元素 font-size。这样设计稿上 100px 的元素在 375 屏幕上占 50px在 430 屏幕上占 57.3px整体等比缩放。具体怎么算假设设计稿宽度 750px我们设一个基准值 100意思是设计稿上 100px 等于 1rem。在 375px 的屏幕上我们希望 1rem 等于 50px因为 375 / 750 × 100 50。所以根字号计算公式是const designWidth 750; const baseFont 100; const clientWidth document.documentElement.clientWidth; document.documentElement.style.fontSize (clientWidth / designWidth) * baseFont px;在 375 屏幕上font-size 375 / 750 × 100 50px。设计稿上 100px 的元素CSS 里写 1rem实际渲染就是 50px正好是设计稿的一半。在 750 物理像素的屏幕上DPR250 CSS 像素对应 100 物理像素和设计稿完全对齐。完整代码(function () { const designWidth 750; const baseFont 100; function setRem() { const docEl document.documentElement; const clientWidth docEl.clientWidth; // 限制最大宽度防止 PC 端打开时字体过大 const width Math.min(clientWidth, 750); docEl.style.fontSize (width / designWidth) * baseFont px; } setRem(); window.addEventListener(resize, setRem); window.addEventListener(pageshow, function (e) { if (e.persisted) { setRem(); } }); })();接下来要解决的是怎么把设计稿上的 px 自动转成 rem手动算太累用postcss-pxtorem// postcss.config.js module.exports { plugins: { postcss-pxtorem: { rootValue: 100, propList: [*], selectorBlackList: [.no-rem, .el-], minPixelValue: 2, mediaQuery: false, }, }, };这里rootValue: 100必须和 JS 里的baseFont一致。selectorBlackList用来排除不需要转换的选择器比如 Element Plus 的.el-开头的类名否则第三方组件样式会被转换导致样式错乱。minPixelValue: 2表示小于 2px 的不转换避免 1px 边框被转成 rem 后出现小数像素。mediaQuery: false表示不转换媒体查询里的 px。实操心得如果你用的是 Vant、Element Plus 这类组件库它们的样式默认按 375 设计稿、rootValue 37.5 来。你的项目如果 rootValue 是 100就会出现组件变小或变大的问题。解决办法是在selectorBlackList里排除组件库前缀然后单独覆盖组件样式。更省事的办法是直接用 vw 方案后面会讲。2.3 vw适配postcss-px-to-viewport实战vw 是视口宽度单位1vw 等于视口宽度的 1%。在 375px 屏幕上1vw 3.75px在 750px 屏幕上1vw 7.5px。用 vw 做适配不需要 JS 动态设置根字号纯 CSS 就能搞定这是它比 rem 更省心的地方。配置postcss-px-to-viewport// postcss.config.js module.exports { plugins: { postcss-px-to-viewport: { unitToConvert: px, viewportWidth: 750, unitPrecision: 5, propList: [*], viewportUnit: vw, fontViewportUnit: vw, selectorBlackList: [ignore-, .el-], minPixelValue: 1, mediaQuery: false, replace: true, exclude: [/node_modules/], landscape: false, }, }, };viewportWidth: 750表示设计稿宽度。exclude: [/node_modules/]一定要加上否则 node_modules 里的第三方库样式也会被转换。selectorBlackList排除不想转换的类名。写一个设计稿上 100px 的元素转换后就是100 / 750 * 100vw 13.33333vw在 375 屏幕上渲染为 50px和 rem 方案效果一样。但 vw 方案有两个注意点第一PC 端打开时字体可能过大。因为 PC 视口宽度可能是 19201vw 19.2px设计稿上 16px 的字体转成 2.133vw在 PC 上就是 40.9px大得离谱。解决办法是给页面加max-width或者用媒体查询限制根容器宽度body { max-width: 750px; margin: 0 auto; }但 vw 是相对视口的max-width并不能限制 vw 的计算。更彻底的办法是在 JS 里判断如果是 PC 端就切换到固定宽度布局。或者直接用postcss-px-to-viewport的landscape配置和媒体查询配合。第二iOS Safari 的 vh 问题。vh 在移动端浏览器地址栏显示/隐藏时会变化导致布局跳动。vw 没有这个问题因为宽度不变。但如果你的设计稿里有全屏高度建议用100dvh或 JS 动态设置高度。2.4 1px边框、安全区与横竖屏细节移动端适配除了整体缩放还有三个细节经常被忽略1px 边框、安全区、横竖屏。1px 边框在 DPR2 或 3 的屏幕上会变粗。因为 CSS 的 1px 会被渲染成 2 或 3 个物理像素。解决方案是用伪元素加transform: scaleY().hairline-bottom { position: relative; } .hairline-bottom::after { content: ; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background-color: #e5e5e5; transform: scaleY(0.5); transform-origin: 0 0; } media (-webkit-min-device-pixel-ratio: 3) { .hairline-bottom::after { transform: scaleY(0.333); } }transform-origin: 0 0保证从顶部开始缩放否则线条会偏移。DPR2 时缩放 0.5DPR3 时缩放 0.333这样视觉上就是真正的 1 物理像素。安全区主要针对刘海屏和底部小黑条。除了前面说的safe-area-inset-bottom还有safe-area-inset-top、safe-area-inset-left、safe-area-inset-right。通常底部操作栏需要加.bottom-bar { padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); background: #fff; }顶部导航栏如果使用position: fixed也要加padding-top: env(safe-area-inset-top)否则在刘海屏上会被遮挡。横竖屏切换时除了重新计算 rem还要注意图片和布局。有些页面只支持竖屏可以在 CSS 里加media screen and (orientation: landscape) { .rotate-tip { display: flex; } }提示用户旋转屏幕。如果页面需要支持横屏就要用媒体查询或者 JS 监听orientationchange重新布局。实测下来安卓机在横竖屏切换时clientWidth更新有延迟所以前面说的setTimeout 300ms很有必要。3. PC端与后台系统适配断点、栅格与弹性布局3.1 断点设计与媒体查询PC 端适配和移动端最大的区别是移动端通常等比缩放PC 端更倾向于响应式布局。因为 PC 屏幕从 1366 到 3840 都有如果无脑等比缩放在 4K 屏上字体会大得夸张在 1366 上又太小。所以 PC 端一般用断点 流式布局。常见断点参考 Bootstrap 和 Element Plus 的栅格系统断点尺寸范围适用设备xs 576px手机sm≥ 576px大手机md≥ 768px平板lg≥ 992px小桌面xl≥ 1200px普通桌面xxl≥ 1600px大桌面媒体查询写法.container { width: 100%; padding: 0 16px; } media (min-width: 576px) { .container { max-width: 540px; margin: 0 auto; } } media (min-width: 768px) { .container { max-width: 720px; } } media (min-width: 992px) { .container { max-width: 960px; } } media (min-width: 1200px) { .container { max-width: 1140px; } } media (min-width: 1600px) { .container { max-width: 1400px; } }为什么选这些断点因为它们对应了主流设备的 CSS 宽度。比如 768 是 iPad 竖屏宽度992 是小笔记本1200 是普通桌面。后台管理系统一般以 1200 以上为主但也要兼容 1366 和 1920。如果设计稿是 1920在 1366 屏幕上可以通过侧边栏折叠、表格横向滚动来适配。3.2 流式布局、flex与gridPC 端布局优先用 flex 和 grid少用绝对定位。后台管理系统最常见的布局是左侧固定侧边栏右侧内容区自适应。用 flex 实现.layout { display: flex; height: 100vh; } .sidebar { width: 220px; flex-shrink: 0; background: #001529; transition: width 0.3s; } .sidebar.collapsed { width: 64px; } .main { flex: 1; min-width: 0; overflow: auto; padding: 16px; background: #f0f2f5; }这里min-width: 0非常关键。flex 子项默认min-width: auto如果内容区里有表格或长文本会撑破容器导致整个页面出现横向滚动。加上min-width: 0后内容区才能正确收缩表格内部再滚动。grid 适合做卡片式布局.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }auto-fill和minmax组合可以自动计算每行能放几张卡片屏幕宽就多放屏幕窄就少放不需要写断点。3.3 表格、表单与弹窗在低分辨率下的处理后台系统最头疼的是表格。Element Plus 的el-table默认宽度自适应但列多了会撑出横向滚动。在 1366 屏幕上如果侧边栏展开内容区只剩 1100 左右表格很容易溢出。解决办法给表格父容器设置overflow: hidden和min-width: 0。表格本身设置height100%或固定高度开启内部滚动。操作列使用fixedright保证按钮始终可见。非关键列设置min-width允许横向滚动。template div classtable-wrapper el-table :datatableData height100% stylewidth: 100% el-table-column propname label名称 min-width120 / el-table-column propstatus label状态 width100 / el-table-column label操作 width160 fixedright template #defaultscope el-button link typeprimary clickhandleEdit(scope.row)编辑/el-button /template /el-table-column /el-table /div /template style scoped .table-wrapper { flex: 1; min-height: 0; overflow: hidden; } /style弹窗在低分辨率下容易超出屏幕。Element Plus 的el-dialog可以设置width为百分比并加上max-widthel-dialog v-modelvisible width50% :style{ maxWidth: 800px } !-- 内容 -- /el-dialog如果屏幕宽度小于 768可以动态改成 90%const dialogWidth computed(() { return window.innerWidth 768 ? 90% : 50%; });表单布局用el-row和el-col的响应式属性el-row :gutter16 el-col :xs24 :sm12 :md8 :lg6 el-form-item label姓名 el-input v-modelform.name / /el-form-item /el-col /el-row:xs24表示手机上一行一个:sm12表示平板一行两个:md8表示桌面一行三个。这样不用写媒体查询也能响应式。3.4 高DPI屏幕下图片与字体清晰度PC 端也有高分屏比如 MacBook 的 DPR24K 显示器的 DPR 可能是 1.5 或 2。如果图片只准备了 1x在高分屏上会模糊。解决方案是用srcsetimg srclogo-1x.png srcsetlogo-2x.png 2x, logo-3x.png 3x altLogo /CSS 背景图可以用image-set.logo { background-image: image-set( url(logo-1x.png) 1x, url(logo-2x.png) 2x ); }字体方面避免使用小于 12px 的字号高分屏上小字会发虚。优先使用系统字体栈body { font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif; }如果设计稿用了特殊字体建议用font-display: swap避免文字闪烁同时提供 woff2 格式体积更小。4. 大屏可视化适配scale缩放、remvw与ECharts联动4.1 大屏常见分辨率与设计稿选择大屏可视化是适配问题最集中的场景。常见大屏分辨率有 1920×1080、2560×1440、3840×2160还有拼接屏比如 2×2 拼接后是 3840×2160但每个单屏还是 1920×1080。设计稿通常以 1920×1080 为基准因为这是最常见的大屏单屏分辨率。大屏适配和移动端、PC 端都不一样。移动端要照顾各种手机宽度PC 端要响应式断点大屏则通常要求整体等比缩放保持设计稿的布局比例不能因为屏幕变宽就把图表拉变形。所以大屏方案主要有两种transform: scale和rem vw。4.2 transform scale方案等比缩放与容器居中scale 方案的思路很简单把整个大屏内容固定成 1920×1080然后用transform: scale()缩放到实际屏幕大小保持宽高比多余部分留黑边。这样设计师给的绝对定位、图表位置都不会乱。HTML 结构div classscreen-wrapper div classscreen refscreenRef !-- 大屏内容宽高固定 1920×1080 -- /div /divCSS.screen-wrapper { width: 100vw; height: 100vh; overflow: hidden; position: relative; background: #000; } .screen { width: 1920px; height: 1080px; position: absolute; left: 50%; top: 50%; transform-origin: left top; background: #0b1a33; }JS 计算缩放比例function setScale() { const wrapper document.querySelector(.screen-wrapper); const screen document.querySelector(.screen); const width wrapper.clientWidth; const height wrapper.clientHeight; const scaleX width / 1920; const scaleY height / 1080; const scale Math.min(scaleX, scaleY); screen.style.transform translate(-50%, -50%) scale(${scale}); } setScale(); window.addEventListener(resize, setScale);注意transform-origin: left top和translate(-50%, -50%)的配合。因为translate在scale之前执行所以元素会先移动到中心再以左上角为原点缩放。这样缩放后元素仍然居中。如果顺序反过来缩放原点会不对导致位置偏移。scale 方案的优点是实现简单布局完全按设计稿来不用考虑 rem 计算。缺点是文字缩放后可能模糊因为浏览器是先渲染 1920×1080 的内容再整体缩放。在高分屏上如果缩放比例不是整数文字边缘会发虚。另外ECharts 的鼠标事件在缩放后可能偏移后面会讲。4.3 remvw方案字体与图表跟随缩放rem vw 方案更适合大屏尤其是需要 ECharts 交互的场景。核心思路是设置根字号随视口宽度变化所有尺寸用 rem这样布局和字体都是实时计算不会模糊。设置根字号function setRootFont() { const width document.documentElement.clientWidth; const designWidth 1920; document.documentElement.style.fontSize (width / designWidth) * 100 px; } setRootFont(); window.addEventListener(resize, setRootFont);在 1920 屏幕上根字号 100px在 2560 屏幕上根字号 133.33px。设计稿上 100px 的元素写 1rem在 1920 上是 100px在 2560 上是 133.33px等比放大。配合postcss-pxtorem// postcss.config.js module.exports { plugins: { postcss-pxtorem: { rootValue: 100, propList: [*], selectorBlackList: [.no-rem], minPixelValue: 2, }, }, };这样设计稿上的 px 会自动转成 rem。ECharts 的字体大小也可以用 rem但 ECharts 配置里通常写 px需要手动转换或者监听 resize 后重新设置。更常见的做法是ECharts 容器用百分比或 rem 设置宽高图表初始化后监听resizeconst chart echarts.init(document.getElementById(chart)); window.addEventListener(resize, () { chart.resize(); });如果根字号变了ECharts 内部字体不会自动变需要重新setOption或者使用chart.resize()配合media配置。ECharts 5 支持media响应式配置const option { baseOption: { // 基础配置 }, media: [ { query: { minWidth: 1920 }, option: { title: { textStyle: { fontSize: 24 } }, }, }, { query: { minWidth: 2560 }, option: { title: { textStyle: { fontSize: 32 } }, }, }, ], };但更简单的办法是在resize事件里重新计算字体大小然后setOption更新。实操心得大屏项目如果 ECharts 图表多强烈建议用 rem vw 方案。scale 方案虽然写起来快但 ECharts 的 tooltip 在缩放后位置会偏移鼠标悬浮到柱子上提示框可能出现在别的地方。这是因为 ECharts 内部坐标系还是 1920×1080而鼠标事件经过 CSS transform 后坐标变了。解决偏移需要手动转换坐标麻烦且容易出错。rem vw 方案下ECharts 容器尺寸就是实际渲染尺寸resize()后一切正常。4.4 高DPI下的字体与图片清晰度大屏也有高分屏比如 4K 大屏 DPR2或者 Retina 显示器。如果图片只用了 1x在 4K 屏上会模糊。大屏背景图、图标建议使用 2x 图或者用 SVG。SVG 矢量图在任何分辨率下都清晰适合大屏的边框、图标、装饰元素。如果使用 scale 方案文字模糊的问题可以通过will-change: transform稍微缓解但根本解决办法还是 rem vw。另外transform: scale()缩放后如果比例不是整数尽量避免使用text-shadow和细边框因为它们会被缩放得模糊。大屏字体建议不小于 12px重要数据字体不小于 24px。在 1920 设计稿下标题 32px、正文 16px、数据 48px 是比较常见的比例。用 rem 方案时这些尺寸会自动跟随屏幕缩放不用单独处理。5. 常见问题与排查技巧实录5.1 分辨率适配常见问题速查表适配问题五花八门但大多数都逃不出下面这些。我整理了一张速查表遇到问题先对号入座问题现象可能原因解决方案手机打开页面很小需要手动放大缺少 meta viewport加上widthdevice-width, initial-scale1.0Retina 屏上 1px 边框变粗DPR 导致 1px 被放大用伪元素 transform: scaleY(0.5/0.333)rem 方案在 PC 端字体巨大根字号按 PC 宽度计算限制clientWidth最大值或 PC 端切固定布局vw 方案在横屏时字体过大横屏视口宽度变大监听orientationchange或限制根容器max-width大屏 ECharts tooltip 偏移scale 方案坐标未转换改用 rem vw或手动转换鼠标坐标低分辨率下表格横向滚动内容区宽度不足侧边栏折叠、表格min-width、操作列fixed弹窗超出屏幕固定宽度过大宽度用百分比 max-width小屏改 90%图片在高分屏模糊只有 1x 图用srcset或image-set提供 2x/3xqiankun 子应用样式错乱子应用重复设置 viewport主应用统一设置子应用不写 meta横竖屏切换后 rem 未更新未监听orientationchange监听事件延迟 300ms 重设根字号这张表基本覆盖了日常开发中 80% 的适配问题。遇到问题时先看现象再查原因最后套方案比盲目改代码效率高得多。5.2 实操避坑心得最后分享几条我在实际项目里踩过的坑都是文档里不会写的。第一条设计稿宽度一定要问清楚。我遇到过设计师给了一张 750 的图但标注用的是 375 的尺寸前端按 750 算 rem结果所有元素小了一半。后来学乖了拿到设计稿先问宽度多少基准设备是哪款标注是物理像素还是 CSS 像素这三个问题问完方案就清晰了。第二条postcss 插件一定要排除 node_modules。有一次项目里用了 Element Pluspostcss-pxtorem没排除 node_modules结果组件库的样式全被转成了 rem按钮变得巨大。加上exclude: [/node_modules/]后问题解决。另外如果组件库本身用了 rem你的根字号和它的不一致也会出问题。所以用组件库时要么排除它的样式要么用 vw 方案。第三条flex 子项记得加 min-width: 0。这个问题在后台管理系统里特别常见。内容区用了 flex: 1里面放了表格结果表格把内容区撑破整个页面横向滚动。加上min-width: 0后内容区才能正确收缩表格内部滚动。同样min-height: 0在垂直方向也有类似作用。第四条大屏项目别轻易用 scale。我最早做大屏时用 scale布局确实快但 ECharts 的 tooltip 偏移让人抓狂。后来换成 rem vw虽然写样式时要多用 rem但图表交互完全正常。如果大屏没有交互只是展示scale 可以用如果有 ECharts、地图、点击事件建议 rem vw。第五条真机测试比 Chrome 模拟器可靠。Chrome 的设备模拟器能模拟 DPR 和视口但和真机还是有差异。尤其是一加、华为等安卓机默认字体大小、显示大小设置会影响页面。华为前端面试全解析里也常提到安卓机的font-size可能被系统设置影响导致 rem 基准不准。解决办法是在根字号计算时结合window.devicePixelRatio和screen.width做校正或者用 vw 方案减少 JS 依赖。第六条面试时别只背概念。2026 前端面试题里屏幕适配依然是高频考点。面试官问“rem 和 vw 的区别”不要只答“rem 是相对根元素vw 是相对视口”。要结合实际项目说rem 需要 JS 动态设置根字号适合需要限制最大宽度的场景vw 纯 CSS适合移动端但 PC 端要小心字体过大。再补一句“大屏项目我选了 rem vw因为 ECharts resize 更自然”面试官会觉得你真的做过项目。第七条pyqt5 适配分辨率也有类似逻辑。虽然这篇文章主要讲 Web 前端但如果你在做 pyqt5 桌面端也会遇到高分屏适配问题。Qt 里有Qt.AA_EnableHighDpiScaling和devicePixelRatio思路和 Web 的 DPR 类似。需要手动缩放控件尺寸或者使用布局管理器别用绝对坐标。这一点在跨端项目里经常被问到。第八条微前端里 viewport 只写一次。如果你在用 qiankun 微前端入门主应用设置好meta viewport子应用不要再设置。子应用只需要关注自己的根元素样式隔离比如加 scoped 或者用 CSS Modules。否则子应用加载后可能覆盖主应用的 viewport导致页面缩放异常。第九条安全区要测试刘海屏和底部横条。iPhone 12 以后的机型都有底部横条如果底部按钮没加safe-area-inset-bottom会被横条遮挡。测试时用真机或者 Chrome 的 iPhone 12 模拟器打开“显示设备边框”查看。另外viewport-fitcover必须加否则env()不生效。第十条别把适配做成万能公式。没有一种方案能通吃所有场景。移动端 H5 用 vw 或 remPC 后台用断点 flex大屏用 rem vw 或 scale。项目开始前先确定目标设备范围再选方案比中途换方案成本低得多。我在最近一个 vue3 element plus 大屏项目里最终选了 rem vw 方案配合 ECharts 的 resize在 1920 和 2560 下表现都很稳。踩过的坑是 postcss 插件把 Element Plus 的组件样式也转了后来用selectorBlackList排除掉.el-前缀才解决。如果你也在做类似项目建议先在postcss.config.js里把排除规则写好再开始写业务样式。