# 移动端响应式布局方案
# 媒体查询
@media media-type and (media-feature-rule) {
/* CSS rules */
}
1
2
3
2
3
其中
- media-type(媒体类型):指定媒体类型(屏幕screen、打印稿print)
- media-feature-rule:查询规则
# 百分比
width
: 相对于父容器width内容宽的百分比;height
: 相对于父容器height内容宽的百分比padding、margin
: 相对于父容器width内容宽的百分比(任意方向)border
: 不能使用百分比
# rem
rem
是相对于html
的字体大小
默认:1rem = 16px
有 2 种实现方式: js实现
、纯css
实现。
# 动态计算rem
实现:1rem = 100px。
通过头部内嵌一段脚本,监听设备宽度的变化来动态改变根字体大小。
1、先通过viewport tag
来设置视窗大小为内容大小,同时禁止缩放(否则按照默认预设值)。
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1;">
1
2、嵌入JS脚本。
// 一般为了方便计算,会设置成:1rem = 100px。
(function() {
function _setRootSize() {
// a、获取根元素
let rootHTML = document.documentElement;
// b、获取当前设备宽度deviceWidth
let deviceWidth = rootHTML.getBoundingClientRect().width || rootHTML.clientWidth;
// c、设置当前设备宽度最大值为750px(750px为视觉稿宽度)
// 因为deviceWidth > 750,物理分辨率大于 1500(devicePixelRatio = 2时),正常应该是PC访问
deviceWidth = deviceWidth > 750 ? 750 : deviceWidth;
// d、计算比率。(假设750px设计图也是一个设备,希望1rem = 100px,则需在其根节点字体大小设置100px,得出比率)
let ratio = 750 / 100;
// e、当前设备宽度 / 比率,算出当前设备的根节点字体大小
let rootFontSize = deviceWidth / ratio;
// f、设置根节点字体大小
rootHTML.style.fontSize = rootFontSize + 'px';
}
_setRootSize();
if (document.body) {
_setRootSize();
} else if (document) {
document.addEventListener('DOMContentLoaded', _setRootSize);
}
window.addEventListener('resize', _setRootSize)
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 纯CSS实现rem
实现:1rem = 100px
html {
font-size: calc(100vw/3.75);
}
1
2
3
2
3
# vw/vh
vw
、vh
都是视口单位,分别等于视口宽度、高度的百分比。
兼容性:ios8、android 4.4以上
# 4种响应式方案的区别
媒体查询:
- 优点:1、多套规则,适配更精细
- 缺点:1、多套规则,定义繁琐;2、响应断点,体验性较差
百分比:
- 缺点:1、不同属性的参考基准不一;2、并非所有属性都支持百分比(如:
font-size
、border
)
rem:
- 优点:1、全局性的基准单位;2、动态计算,可限定最大宽度
- 缺点:1、需额外借助JS;2、安卓4.4以下不支持viewport缩放
vw/vh:
- 好处:1、全局性的基准单位;2、无需额外借助JS
- 缺点:无法限定最大宽度
可以根据实际情况采取合适的方案,也可采用多套配合(如网易新163就是:媒体查询 + rem + vw)
但以上都 无法解决1px问题。
# css样式适配Trick:通过js计算
# 起因
在还原样式(广播电台)时,发现:在原工程里使用了大量媒体查询进行样式定位。
# 分析
处理样式适配的一贯作法是通过媒体查询,目的是尽可能适配到大众型号场景。但对于某些特殊场景,也可以尝试用js来计算目标节点定位。
同时搭配
position: fiexed
,可以省去很多css适配工作。
例子:需要处理 图中绿色DOM节点 在页面定位适配。
# 解决
发现,“绿色节点”距离上、下节点(皆为fixed定位
的节点)的距离相同
- 先通过上、下DOM节点的
getBoundingClientRect()
,获取y
定位 - 再通过
((顶部y + 顶部height) + 底部y) / 2
,得到中位数,设为绿色节点的y
、height
数值 - 绿色节点再通过
transform: translateY(-50%)
可定位至上、下DOM节点中间
# 注意
有时可能需要处理在个别小屏手机进行粗粒度较大的适配(如针对绿色节点中的图片进行缩放等)。
# 业务反馈
在业务中使用还是谨慎考虑,可能出现:
- 渲染时机一旦错误就会导致最终定位错误
- 部分机型还是需要媒体查询进行更加精准的适配
# 日后参考
- 先实现一款(如ipx)比较完美适配
- ipx其它系列(ip6/7/8 -> ip6/7/8p -> ip5/5se -> ipx/xs & ipxr & ipxs max)
- 1080P安卓 -> 常用测试机
1px问题 →