直接用 window.devicePixelRatio 动态加载对应 CSS 文件最稳妥,核心是取整拼文件名(如 base-dpr2.css)并用 createElement('link') 插入 head 顶部;media query 无法触发新资源加载,仅控制已加载样式的启用,且兼容性不如 JS 获取可靠。

直接用 window.devicePixelRatio 判断并加载对应 CSS 文件是最稳妥的做法,不依赖任何第三方库,也不需要改构建流程。
如何用 JS 动态加载不同 DPR 的 CSS 文件
核心逻辑是:获取 window.devicePixelRatio,四舍五入取整(避免小数干扰),拼出文件名后通过 document.createElement('link') 插入。
- 实际中
devicePixelRatio值常见为1、2、3,极少出现1.5或2.75;iOS 通常只取2或3,安卓多数按1处理 - 文件命名建议统一为
base-dpr1.css、base-dpr2.css、base-dpr3.css,避免用小数(如dpr2.5)导致路径错误 - 必须在
<head>中尽早执行,最好放在<head>最顶部的内联<script>里,否则可能闪动或样式错乱 - 不要用
fetch+innerHTML注入样式 —— 会破坏 CSSOM,且无法被浏览器预加载器识别
为什么不能靠 media query 区分 DPR 加载 CSS
@media (-webkit-min-device-pixel-ratio: 2) 这类查询只能控制「已加载」CSS 内部规则的启用,无法触发新文件加载。它本质是条件渲染,不是资源调度。
- 如果你把所有 DPR 的规则都写进一个 CSS 文件里,靠媒体查询切换,会导致无用样式冗余,白占带宽和解析时间
- 某些安卓 WebView 对
-webkit-device-pixel-ratio支持不稳定,比如返回0或undefined,而window.devicePixelRatio更可靠 - 媒体查询无法区分「DPR=2 但 scale=0.5」这类缩放后场景,JS 获取的是真实设备能力,更贴近适配意图
配合 flexible.js 时的常见冲突点
如果项目已引入 lib-flexible,它会动态设置 data-dpr 和 font-size,此时再手动加载 DPR CSS 容易重复干预字体/边框等基础尺寸。
立即学习“前端免费学习笔记(深入)”;
- 优先停用
lib-flexible的 font-size 动态逻辑(注释掉docEl.style.fontSize = ...那行),只保留data-dpr属性设置 —— 这样你仍可用[data-dpr="2"]做精细化控制,又不和外部 CSS 冲突 - 若必须保留 flexible 的缩放逻辑(如解决 1px 边框),则 DPR CSS 应专注处理图片、图标、阴影等不受缩放影响的属性,避免再设
font-size或border -
lib-flexible在部分安卓低端机上会把dpr错判为1,建议加兜底:const dpr = Math.min(3, Math.round(window.devicePixelRatio || 1))
DPR 是设备固有属性,但它的实际影响只在像素级细节(1px、图标清晰度、文字锐度)上才明显;多数布局用 rem/vw 就够了,真要切 DPR CSS,只该用于高保真还原设计稿的少数关键模块,别全量套用。


















