Responsive 响应式设计思路
目录
屏幕基础知识
viewport (视口)
DP为UI设计中的唯一可用单位
-------解决不同设备下具有不同屏幕尺寸和分辨率的问题
Android 的逻辑像素单位是 dp(用于元素)和 sp(用于字体),iOS 的逻辑像素单位是 pt
问题原因
选用DP的理由
-
**像素密度PPI:**指每英寸包含的像素(Px)个数
-
同一物理尺寸(肉眼所见尺寸)下,低密度显示器的像素个数明显小于高密度显示器的像素个数,所以像素(PX)在多变的设备和分辨率下不是一个稳定可用的单位
-
**与密度无关的像素(DP):**设备独立像素
DP与PX的对比可见,DP可以自适应屏幕的密度,不管屏幕密度怎么变化,实际显示的物理尺寸相同**,DP可以保证物理尺寸的一致性,DP是目前最适合UI设计的单位**,同时也是使代码语言相通的尺寸。
转换公式
当屏幕的PPI为160时,1DP=1PX;例:Iphone4,Iphone5,Iphone6,PPI为326,在这些屏幕之下1DP=2PX
DP=(PX*160)/PPI
PX=DP*(PPI/160)
设置DP单位的好处
如图可知,通过将 DP 设置为 UI 元素唯一单位后,对于不同设备的屏幕尺寸大小和分辨率问题,
我们可以大致认为: 屏幕的逻辑分辨率越大,对应的屏幕尺寸越大
屏幕尺寸大小( viewport )约等于 分辨率大小
这样对于我们在设置断点时,可以只通过 viewport 来规定断点的值
Responsive 响应式
响应式设计是页面布局和内容的设计&开发,根据用户设备环境进行相应的响应和调整。其采用流体栅格,并自动探测屏幕宽度,CSS3’s media queries特性可以帮助实现。
为了实现不同屏幕分辨率的终端上浏览网页的不同展示方式,有一下两种思路:
- 自适应布局:通过检测视口分辨率来判断当前访问的设备是:PC端、平板端、手机端、从而请求服务器返回不同的页面
- 响应式布局:通过检测视口分辨率来设置不同断点,在不同断点中使用不同的 CSS 样式,来响应不同设备的布局方法
断点
根据目前设备,将主流终端浏览设备划分为手机、平板、PC三种。
断点设置方法
断点设置的方式有: CSS 的@media属性 and 使用 JavaScript 的 matchMedia 方法
媒体查询(Media Query)
JavaScript 实现媒体查询
使用 window 对象上的 matchMedia
方法,基本上所有的浏览器都支持 matchMedia
使用 matchMedia
的基本思路:
// 判断 viewport 大小
var mql = [
window.matchMedia('(max-width: 768px)'),
window.matchMedia('(max-width: 992px)'),
window.matchMedia('(max-width: 1200px)')
]
// 定义回调函数
function mediaMatchs() {
var html = document.getElementsByTagName('html')[0]
if (mql[0].matches) {
html.style.fontSize = '16px';
} else if (mql[1].matches) {
html.style.fontSize = '18px';
} else if (mql[2].matches) {
html.style.fontSize = '20px';
} else {
html.style.fontSize = '22px';
}
}
// 执行调用监听的回调函数
mediaMatchs()
// 状态改变时添加监听器
for (var i = 0; i < mql.length; i++) {
mql[i].addListener(mediaMatchs);
}
在 React 中使用 matchMedia
实现媒体查询
function CssTest() {
const [mediastate,setMediastate] = useState<boolean>(false);
//监听浏览器窗口变化
useEffect(()=>{
// 在window对象中添加监听事件
window.addEventListener('resize',handleReiwportChange)
// 移除监听窗口变化的事件
return ()=> window.removeEventListener('resize',handleReiwportChange)
},[mediastate])
function handleReiwportChange():any{
let result = window.matchMedia('(min-width:320px) and (max-width:766px)')
let result2 = window.matchMedia('(min-width:768px) and (max-width:900px)')
let result3 = window.matchMedia('(min-width:901px)')
if(result.matches){
setMediastate(true);
console.log('小屏幕');
}else if(result2.matches){
setMediastate(true);
console.log('中等屏幕');
}else if(result3.matches){
setMediastate(true);
console.log('大屏幕');
}else if(result.matches||result2.matches||result3.matches === false){
setMediastate(true);
console.log('超小屏');
}
}
resize
事件是窗口大小改变时发生的事件,可以在窗口开启、最大化、最小化、窗口大小改变(如拖拉改变窗口大小、move 语句改变窗口大小、改变 width 或 height 属性以改变窗口大小)时发生。
布局
使用一些自适应的方法,比如 flex弹性布局、grid网格布局、浮动、绝对定位与相对定位、表格或者框架等
flex 布局
思维导图(总的概述):
Gird 网格布局
Grid 网格布局分为两部分:网格容器 和 网格元素
当一个 HTML 元素将 display 属性设置 grid 或 inline-grid 后,它就变成了一个网格容器,这个元素的所有直系子元素将成为网格元素
思维导图:
大小
思路:
rem 适配
Rem( font size of the root element)适配方案是当下流行并且兼容性最好的移动端适配解决方案,它支持大部分的移动端系统和机型。
使用 rem 为元素设定字体大小时,它是相对大小,相对的只是 html 根元素,只需要修改 html 根元素的字号大小,就可以做到页面的大小都会随之改变。
原理
将我们之前写px的单位换成rem单位,然后根据屏幕大小动态设置根元素 font-size 大小,那么只要根元素的 font-size 改变,对应的元素大小就会改变,从而达到不同屏幕下的适配目的
动态设置根元素 font-size 的值
- 通过媒体查询设置
@media screen and (min-width:468px){
html{ font-size:16px; }
}
@media screen and (max-width:467px){
html{ font-size:12px; }
}
- 通过 js 来设置
// 获取屏幕视窗宽度
let htmlWidth = document.documentElement.clientWidth || document.body.clientwidth
//获取宽度最好有个兼容的方案,避免某些情况下第一种获取不到可以选择第二种
//获取 html
let htmlDom = document.getElementsByTagName('html')[0];
html.style.fontSize = htmlWidth/10 + 'px'
上面代码中,得到屏幕宽度后,一般要除以一个系数,这里使用的系数是10,这样得到的 font-size 的值更加灵活,适配性更强。所以在实际应用当中,大多数采用 JavaScript 来动态设置。
如果想要实时监听屏幕大小的变化动态修改 font-size,可以引入 resize 事件,代码如下
window.addEventListener('resize',function(){
/* 上面设置 font-size 的代码*/
})
em
em ( font size of element) 的值不是固定的,em 会继承父级元素的字体大小,任何浏览器的默认字体高度为 16px,所有未经调整的浏览器都符合:1em = 16px
Rem适配与 vw 适配兼容性
从上面的对两种相关的适配方案讲解,可以知道vw适配方案要优于Rem适配方案的,但是没有Rem流行就在于vw的兼容性问题,我们从caniuse(caniuse是一个当下流行的前端技术兼容性查询网站,地址是:https://www.caniuse.com/ )中查询到兼容性
Rem适配方案在主流浏览器中整体支持性98.93%,而vw适配方案在主流浏览器中整体支持性94.44%,并且对于Android4.4之前的机型来说vw不支持是硬伤,毕竟这部分机型的市场占有率还是有一部分的。所以在选取适配方案时,要根据自己业务的场景来选择合适的方案,避免出现兼容性问题。
总结
在我的思路中,我认为响应式布局分为2个部分
- 使用CSS @media 或 JS 来获取设备信息
- 使用 自适应布局(控制布局)+ rem等(控制大小)
(结束语:可能大家都认为使用 flex… 或者 rem… 中的任何一个都可以实现适配,但我认为这两个东西应该是一起使用的,所以我会把它们放一起,我觉得二者缺一不可,最后如果我写的地方有所错误,欢迎大家指出,一起探讨)
参考资料
优快云—JavaScript 媒体查询
CSS—CSS媒体查询
阿里 fusion design----Fusion-Viewport 设计原理