移动端三种像素
markdown
- `物理像素 (设备像素)`:屏幕硬件上真实存在的发光点;特点:固定不变(比如 iPhone 15 的物理像素是 1179×2556)。
- `CSS 像素 (逻辑像素)`:网页代码中写的`px`单位;特点:可被 Viewport 缩放,是相对单位。
- `设备像素比 (DPR)`:DPR = 物理像素 / CSS 像素;特点:高清屏 (DPR=2/3) 下,1 个 CSS 像素对应多个物理像素。
Viewport(视口)
markdown
Viewport 是浏览器显示网页的区域,移动端默认的布局视口(layout viewport)宽度约 980px,直接导致网页缩放显示。我们需要通过 meta 标签设置**理想视口**,让 CSS 像素和设备尺寸匹配:
xml
<!-- 核心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:初始缩放比例为 1user-scalable=no:禁止用户缩放(可选,根据需求调整)
⚠️所有适配生效都要先配置好正确的Viewport(width=device-width, initial-scale=1.0)
实现真实的 1px 边框
问题根源:高清屏(DPR=2)下,CSS 写的1px会被渲染成 2 个物理像素,导致边框看起来比设计稿粗。
方案 1:利用 transform 缩放(推荐,兼容性好)
原理:先设置1px边框,再通过transform: scale()按 DPR 比例缩小,同时用transform-origin控制缩放原点。
css
/* 通用1px边框样式 */
.border-1px {
position: relative;
/* 防止缩放后的边框超出容器 */
overflow: hidden;
}
/* 给容器添加伪元素实现边框 */
.border-1px::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 1px solid #e5e5e5;
/* 根据DPR缩放,这里以DPR=2为例,DPR=3则scale(0.333) */
transform: scale(0.5);
* 让缩放原点在左上角,避免边框偏移 */
transform-origin: 0 0;
/* 防止伪元素覆盖内容 */
pointer-events: none;
}
方案 2:动态计算(适配所有 DPR)
结合 JS 获取设备 DPR,动态设置缩放比例:
js
// 获取设备DPR
const dpr = window.devicePixelRatio || 1;
// 动态设置Viewport的initial-scale
const metaViewport = document.querySelector('meta[name="viewport"]'); metaViewport.content = `width=device-width, initial-scale=${1/dpr}, maximum-scale=${1/dpr}, user-scalable=no`;
// 给1px边框元素设置对应缩放
const borderElements = document.querySelectorAll('.border-1px'); borderElements.forEach(el => {
const after = window.getComputedStyle(el, '::after');
el.style.setProperty('--scale', 1/dpr);
el.querySelector('::after').style.transform = `scale(${1/dpr})`;
// 简化写法:直接修改伪元素样式(实际开发可结合CSS变量) el.style.cssText += `--scale: ${1/dpr};`;
});
实现真实的 12px 字体大小
问题根源:很多移动端浏览器(如微信内置浏览器、Safari)默认限制最小字号为 12px,直接写font-size: 12px在低 DPR 设备上可能被强制放大,或在高 DPR 设备上显示偏小。
方案 1:Viewport 缩放配合 rem(推荐)
- 先通过 JS 动态计算 rem 基准值
js
// 设计稿基准宽度(比如750px设计稿)
const designWidth = 750;
// 基准字号(1rem = 100px,方便计算)
const baseFontSize = 100;
function setRem() {
// 获取设备宽度
const deviceWidth = document.documentElement.clientWidth;
// 计算当前rem对应的像素值
const rem = (deviceWidth / designWidth) * baseFontSize;
// 设置html根元素字号
document.documentElement.style.fontSize = rem + 'px';
}
// 初始化执行
setRem();
// 窗口大小变化时重新计算
window.addEventListener('resize', setRem);
- 写 12px 字体(基于 750px 设计稿):
css
/* 12px = 12/100 = 0.12rem */
.text-12px {
font-size: 0.12rem;
/* 禁止浏览器自动调整最小字号 */
-webkit-text-size-adjust: none;
text-size-adjust: none;
}
方案 2:transform 缩放(兼容极端场景)
如果 rem 适配不生效,可通过缩放实现真实 12px:
css
.text-12px {
/* 先放大到24px(避开最小字号限制),再缩放到50% */
font-size: 24px;
transform: scale(0.5);
/* 缩放后不占原空间 */
transform-origin: left center;
/* 行高也要对应调整 */
line-height: 1.2; /*
防止文字模糊 */
-webkit-font-smoothing: antialiased;
}