响应式是一种网页设计的方式,让一个网站在不同的设备(PC、手机等)上查看时,分辨率都能有一个合适的呈现。
由此我们可以知道,响应式的核心,在于知道当前浏览网站的设备的分辨率,从而针对不同的分辨率作出不同的处理。
基本的处理逻辑
既然核心在于得知浏览设备的分辨率,那么我们可以考虑两种方式获取:
- JavaScript
- CSS
JS监听获取分辨率
JS可以通过操作DOM
,获取到根元素的宽度,并通过DOM事件
监听窗口尺寸的变化,动态获取到当前视窗的宽度。
window.addEventListener("resize", () => {
console.log(document.documentElement.clientWidth);
});
CSS媒体查询
相比于JS的DOM事件
监听,CSS的媒体查询是实现响应式布局的主要方案,即使用@media
,指定设备宽度的最大/最小值,从而实现不同分辨率设备下的不同样式。
一般来说,屏幕样式遵循移动端优先的原则,即优先考虑小尺寸屏幕,设置min-width
。
// 基础的字体大小为12px
font-size: 12px;
// 大于640px,字体14px
@media screen and (min-width: 640px) {
font-size: 14px;
}
// 大于1080px,字体20px
@media screen and (min-width: 1080px) {
font-size: 20px;
}
移动端多分辨率处理方案
在移动端中,因为机型尺寸太过于丰富,有时候如果我们只是根据分辨率,简单的做几个适配,可能也会出现一些展示的问题。
对于尺寸近似的iPhone6和iPhone6 plus,如果设置font-size都是16px,有可能出现这样的问题:
iPhone6 plus:文字可以一行展示
iPhone6:屏幕宽度不够,需要折行展示
这从设计上来说样式并没有统一,而且用户的体验也并不友好
针对此,单纯使用媒体查询并不太奏效,我们能想到的是:能不能根据屏幕的宽度,计算出一个font-size
相对值,从而让所有屏幕宽度都可以一行展示文字
对于这种相对值,目前CSS中提供了两种单位可供选择
rem
rem
这个相对值,参考的是当前页面html根元素的font-size,即
1rem = html的font-size
对于上面提到的根据屏幕宽度调整font-size,那我们需要动态修改1rem
的值,实现的步骤如下
- 监听
html
文档解析完成(DOMContentLoaded
) - 为根标签设置
font-size
(一般是window.innerWidth / 10
),需要注意的是由于存在pad这种横屏宽度大的设备,所以还要设置一个上限(一般是42px
)
// 定义font-size最大值
const MAX_FONT_SIZE = 42;
// 监听html文档被解析完成的事件,根据屏幕宽度设置rem
document.addEventListener('DOMContentLoaded', () => {
const html = document.querySelector('html');
let fontSize = window.innerWidth / 10;
fontSize = fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : fontSize;
html.style.fontSize = fontSize + 'px';
});
可以看出,rem方案结合使用了JS和CSS,相对比较麻烦
vw/vh
CSS3提供了一个新的相对单位vw
和vh
,这两个单位都是以视窗宽度/高度为100来计算的,即window.innerWidth
/window.innerHeight
在使用vw
/vh
的时候,注意设置好meta标签属性,即宽度为设备宽度,初始的缩放比例为1
<meta name="viewport" content="width=device-width, initial-scale=1.0">
相比于rem
方案,vw
/vh
方案是纯的CSS,简单易操作,只是计算时候有点麻烦
异形屏适配方案
自iPhoneX后,手机进入了全面屏的时代,但随之而来的问题是:屏幕中出现了一些展示不了内容的区域:比如iPhone的刘海、安卓的侧边等等,还有iPhone底部的横杠。如果不做适配,会导致一些新的展示和体验问题。
安全区域
针对这些内容不可见的区域,我们要做的是,在设计网页内容时,排除这些危险区域,为此,诞生了“安全区域”这一概念,即排除了四周圆角、上下左右不可见区域
viewport-fit属性
iOS11新增了一个viewport-fit属性
,如果需要设置安全区域,需要把viewport-fit
设置为cover
(内容覆盖可视窗口)
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
/>
距离变量&CSS函数
iOS11新增了距离变量,用来表示安全区域和窗口边界的距离,用safe-area-inset-(left/right/tom/bottom)
表示
此外,还新增了constant
(兼容iOS<11.2)和env
(iOS>=11.2)两个函数
具体到留出安全距离,用如下CSS代码表示
.safe-area-bottom {
position: fixed;
// 先写constant,后写env
bottom: constant(safe-area-inset-bottom);
bottom: env(safe-area-inset-bottom);
}