JS综合解决方案1——多端响应式

129 阅读4分钟

响应式是一种网页设计的方式,让一个网站在不同的设备(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提供了一个新的相对单位vwvh,这两个单位都是以视窗宽度/高度为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底部的横杠。如果不做适配,会导致一些新的展示和体验问题。

安全区域

针对这些内容不可见的区域,我们要做的是,在设计网页内容时,排除这些危险区域,为此,诞生了“安全区域”这一概念,即排除了四周圆角上下左右不可见区域

screen-safe-area.png

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);
  }