1px适配
在 Retina 屏(DPR ≥ 2)上,CSS 的 1px 在物理上其实是 2px 或 3px,看起来比设计稿粗一圈。下面是几种常用的解决方案。
用伪元素画一条 1px 的线,然后通过 scaleY(0.5) 在垂直方向压缩一半:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| .hairline { position: relative; } .hairline::after { content: ''; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: #ccc; transform: scaleY(0.5); transform-origin: 0 0; }
|
同理,scale(0.5) 可以做完整的 1px 边框:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| .border-1px { position: relative; } .border-1px::after { content: ''; position: absolute; left: 0; top: 0; width: 200%; height: 200%; border: 1px solid #ccc; border-radius: 4px; transform: scale(0.5); transform-origin: left top; pointer-events: none; }
|
方案二:用 0.5px
部分现代浏览器(iOS 8+)支持 0.5px 写法,但兼容性有限:
1 2 3
| .border-thin { border-width: 0.5px; }
|
方案三:viewport 缩放(不推荐)
通过修改 viewport 的 scale 来让 1px 对应 1 个物理像素。但会影响整个页面的布局和 rem 计算,副作用大,很少用。
系统软键盘对 fixed 布局影响
移动端最头疼的问题之一。当页面底部有个 fixed 定位的输入框/按钮时,软键盘弹出会导致布局错乱。
问题表现
点击底部固定输入框 → 软键盘弹出 → position: fixed 的元素不再相对视口定位,而是相对键盘上方的可视区域定位。导致:
- 底部固定栏被顶到键盘上方
- 键盘收起后底部固定栏没有回到原位
- Android 上表现尤其混乱(不同厂商差异大)
解决思路
1. 避免在底部 fixed 元素中使用输入框
最简单的方案:将底部固定栏改为 position: static,在键盘弹出时自动滚动到可视区域。或者让输入框在获得焦点时固定在顶部。
2. 用视口单位 + 页面滚动代替 fixed
1 2 3 4 5 6 7 8 9 10 11 12
| .fixed-bottom { position: fixed; bottom: 0; left: 0; right: 0; }
@media screen and (max-height: 500px) { .fixed-bottom { position: static; } }
|
3. 监听 resize 或 focusin/focusout
1 2 3 4 5 6 7 8 9 10 11 12 13
| const bottomBar = document.querySelector('.fixed-bottom');
window.addEventListener('resize', () => { if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') { bottomBar.style.position = 'static'; } });
document.addEventListener('focusout', () => { bottomBar.style.position = 'fixed'; window.scrollTo(0, document.body.scrollHeight); });
|
4. 使用 VisualViewport API(现代方案)
1 2 3 4 5 6 7 8 9 10 11
| if (window.visualViewport) { window.visualViewport.addEventListener('resize', () => { const diff = window.innerHeight - window.visualViewport.height; if (diff > 100) { bottomBar.style.position = 'static'; } else { bottomBar.style.position = 'fixed'; bottomBar.style.bottom = '0'; } }); }
|
经验总结
- iOS:相对友好,键盘弹出后 fixed 元素的定位还比较稳定
- Android:碎片化严重,不同厂商(华为、小米、三星)表现差异大,建议在真机上测试
- 最稳妥的做法还是不要让输入框放在 fixed 栏里,改成随页面滚动