scss 的 $dpr 变量无法实现响应式像素比适配,因其为编译时静态值;必须用 @media 结合 min-resolution 或 -webkit-min-device-pixel-ratio 在运行时判断,并通过 @import 或嵌套 & 内联高清规则。

直接用 @media 判断 min-resolution 或 -webkit-min-device-pixel-ratio,配合 @import 加载高清规则或内联写法,是最可靠、零 JS 依赖的方案。别指望 --dpr 变量在纯 SCSS 编译期生效——它根本不会动态更新。
为什么不能用 $dpr 变量做条件编译
SCSS 是编译时语言,$dpr: 2 这种写法只会输出固定值,无法感知真实设备的 window.devicePixelRatio。你写的 @if $dpr >= 2 在构建时就跑完了,生成的 CSS 对所有用户都一样。这不是“适配”,是硬编码。
- 常见错误:在
_variables.scss里定义$dpr: 2,然后@if $dpr == 2控制边框粗细 —— 构建后所有设备都走同一套 CSS - 真正需要的是运行时判断,而 SCSS 没有运行时能力
- 若强行用 JS 注入
--dpr,它只能用于calc()计算,不能驱动@media或选择器生成
@import 高清 CSS 文件的正确写法
@import 必须出现在样式表最顶部,且媒体条件要直接跟在 URL 后面,不能包在 @media 块里。否则整条语句被浏览器忽略。
- ✅ 正确:
@import "dpi-2x.css" only screen and (-webkit-min-device-pixel-ratio: 2); - ✅ 正确:
@import "dpi-2x.css" only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx); - ❌ 错误:
@media (-webkit-min-device-pixel-ratio: 2) { @import "dpi-2x.css"; }(语法非法) - 路径是相对于当前 SCSS 文件的位置,不是 HTML 页面;必须用引号包裹 URL
内联写高清规则:用 @media 套 & 嵌套
想把高清样式和组件逻辑写在一起?可以,但必须用 SCSS 原生支持的嵌套 + & 显式引用父级,避免生成错误的选择器。
- 示例:给
.card在 2x 屏下用更细的边框 .card { border: 1px solid #ccc; @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) { & { border-width: 0.5px; } } }- 关键点:
&确保编译后仍是.card,而不是孤立的{ border-width: 0.5px; } - 不要省略
&写成@media { border-width: 0.5px; },那会脱离上下文,变成全局重置
伪元素 + transform: scaleY() 实现物理 1px 边框
这是最轻量、兼容性最好(iOS 8+/Android 4.4+)、无需额外文件的方案,适合按钮、列表项等需高频复用的场景。
- 原理:用
::after画一条 1px 高的线,再用transform: scaleY(0.5)压缩到 0.5px 视觉高度,在 dpr=2 设备上正好占 1 物理像素 - 必须设
transform-origin: top;,否则缩放中心偏移导致位置错乱 - SCSS 封装示例:
@mixin border-1px($color: #e0e0e0) { position: relative; &::after { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 1px; background-color: $color; transform: scaleY(0.5); transform-origin: top; } } - 调用:
.list-item { @include border-1px(#ccc); }
真正容易被忽略的点是 viewport 设置——如果 <meta name="viewport"> 缺失或 initial-scale 不为 1,再精细的 DPI 判断也会失效,因为 CSS 像素和物理像素的映射关系已经乱了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











