移动端总结1

像素相关的基本概念

物理像素、逻辑像素、CSS像素、PPI、设备像素比是什么?

  • 物理像素代表屏幕上有多少个点,比如1080x2340表示屏幕水平方向一排有1080个物理像素点。
  • 逻辑像素表示屏幕展示物体的视觉尺寸是多少。逻辑像素相同表示物体看起来或者打印出来大小一样,物理像素点越小,一个逻辑像素包含点物理像素点就越多,看起来就越清晰。
  • 一般情况下CSS像素等同于逻辑像素,但浏览器可以放大,手机也有放大模式,此时就不再相等。
  • PPI是屏幕对角线的物理像素的个数除以对角线英寸数。
  • 设备像素比是在水平或者垂直方向,在同一排一个逻辑像素能放几个物理像素。
    • window.devicePixelRatio
    • @media (-webkit-min-device-pixel-ratio: 2)

CSS像素

浏览器使用的单位,用来精确度量网页上的内容,比如 div { width: 100px; }。 在一般情况下(页面缩放比为1),1个CSS像素 等于 1个设备独立像素。比如,假设把屏幕独立像素分辨率设置为1440x900,给页面元素设置为宽度720px,则视觉上元素的宽度是屏幕宽度的一半。这也解释了为什么当我们把独立像素分辨率调高后网页的文字感觉变小了。

当页面缩放比不为1时,CSS像素和设备独立像素不再对应。比如当页面放大200%,则1个CSS像素等于4个设备独立像素。

0.5px 和 1px

目的: 希望在设备中能看到更细的边框和细线

transform + 伪元素

这种方法兼容性最好,4个边框都能一次性设置,能正常展示圆角。

步骤: 给标准盒模型的伪元素添加样式(0.5px):实践open in new window

  1. 定位 bottom:0
  2. 宽高设200%
  3. border: 1px solid #000;border-radius: 10px;
  4. transform: scale(0.5);

细线而非边框可以将border置为border-bottom

其他方法

设备像素比-媒体查询(1px)

@mixin border1px($color: #ddd, $direction: 'top') {
  @if $direction == 'all' {
    border: 1PX solid $color;
  } @else {
    border-#{$direction}: 1PX solid $color;
  }
  
  @media (-webkit-min-device-pixel-ratio: 2) {
    @if $direction == 'all' {
      border: 0.5PX solid $color;
    } @else {
      border-#{$direction}: 0.5PX solid $color;
    }
  }
  
  @media (-webkit-min-device-pixel-ratio: 3) {
    @if $direction == 'all' {
      border: 0.333333PXPX solid $color;
    } @else {
      border-#{$direction}: 0.333333PXPX solid $color;
    }
  }
}
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

meta设置viewport的作用

  1. 我们页面本身是移动端设计风格的页面,设计师在设计页面时按移动端通用的375px或者428px来做设计,我们需要在head标签里加<meta name="viewport" content="width=device-width">。如果原本就是针对PC浏览器设计的页面未适配过移动端,不建议加此meta。
  2. 这句话的意思是让页面的布局视口的宽度等于视觉视口的宽度,此时页面元素会以设备逻辑像素宽度做为文档宽度进行布局。
  3. 如果不加,则页面元素会以980px的文档宽度进行布局,然后980px的宽度再缩小填充整个屏幕。会导致页面元素看起来比较小。

默认情况下,文档宽度(980px)要大于移动端的视窗。移动端页面必须使用name为viewport的meta标签,PC端页面不加,起码能用。

加不加meta一行能展示几个字?

  • 375px 除以 font-size

  • 980px 除以 font-size

HTML页面的body里有很多汉字,每个文字占据的宽度是15px,这个页面分别在手机浏览器和PC浏览器上展示一行大约能展示多少汉字?以 在IPhone 12 mini (逻辑像素宽度是375px)为例,假设HTML的head标签里加了<meta name="viewport" content="width=device-width"> ,一排大约能展示375/15 = 25个字。假设head标签里没加这个meta,一排大约能展示980/15 = 65 个字。

移动端适配的思路

移动端适配的目标是让页面在不同的移动设备上都合理展示。一般来说有两种方向:

  1. 0适配,使用合理的flex布局+媒体查询做微调
  2. 基于一个尺寸的屏幕做设计,其他屏幕等比缩放

0适配:响应式。

手机屏幕的逻辑像素一般在320px~428px这个范围,手机页面最常见的布局就是水平均分排列和两栏布局(如下图所示)。使用flex布局实现的水平均分排列原本就是响应式的,不管是320还是428的屏幕都是均分排列。

缺点:需要对展示有问题的地方用媒体查询做微调

等比缩放适配

优点: 能对不同屏幕尺寸手机的展现效果做绝对的把控。

等比缩放适配的三种方案

适配方案对比

小结

viewport缩放方案需要使用JS直接使用设计稿标注无需换算方案死板只能实现页面级别整体缩放
动态REM方案需要使用JS设计稿标注的px换算到CSS的rem计算简单方案灵活既能实现整体缩放又能实现局部不缩放
vw方案不需要JS即可适配设计稿标注的px换算到CSS的vw计算复杂方案灵活既能实现整体缩放又能实现局部不缩放

viewport缩放方案

页面整体放大缩小,对于不想缩放的元素无法控制。

示例:

设置布局视口(layout viewport)的宽度为750px(此时页面一般会超出屏幕),再缩放页面(initial-scale)使其恰好撑满屏幕。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script>
    const WIDTH = 750
    const mobileAdapter = () => {
      let scale = screen.width/WIDTH
      let content = `width=${WIDTH}, initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}`
      let meta = document.querySelector('meta[name=viewport]')
      if(!meta) {
        meta = document.createElement('meta')
        meta.setAttribute('name', 'viewport')
        document.head.appendChild(meta)
      } 
      meta.setAttribute('content', content)
    }
    mobileAdapter()
    window.onorientationchange = mobileAdapter
  </script>
</head>
<body>
 ...
</body>
</html>
复制成功
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

动态rem适配方案

核心

  • 1rem 等于html标签font-size的1倍。
  • 计算document.documentElement.style.fontSize = 100*屏幕宽度/设计稿宽度

例子:

设计稿宽度为750, 前端需要搞一个375的div(正好占一半)
  1. 提前定好html的fontSize
  2. 计算时用设计稿标注值除以100. 前端给这个div设`3.75rem`的宽度
> 假设用户在逻辑像素宽度是375px的设备上打开页面,则html的font-size是100*375/750 = 50px,div的宽度是3.75rem ,即187.5px 正好是屏幕宽度的一半。*
> 假设用户在逻辑像素宽度是428px的设备上打开页面,则html的font-size是100*428/750 = 57.07px,div的宽度是3.75rem ,即214px 正好是屏幕宽度的一半。

vw方案

核心

  • vw是相对单位,1vw表示屏幕宽度的1%。
  • 样式使用font-size: calc(100vw*28/750); 尺寸 = 100vw*设计稿标注大小/设计稿宽度
    • 例:设计师交付的设计稿宽度是750px,设计稿上一个标题的fontSize标注尺寸是32px。(32/750)*100% = 4.27% ,换句话说这个标题的尺寸占屏幕宽度的4.27%,不管任何屏幕都是如此。 4.27% 即 4.27vw。

例子

假设设计稿尺寸是750px,页面有一个按钮,按钮文字标注大小28px,按钮高度标注为48px,宽度为120px,边框为1px。
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    .button {
      width: 16vw;        /*  100vw*120/750  */
      font-size: 3.73vw;  /*  100vw*28/750  */
      line-height: 6.4vw; /*  100vw*48/750  */
      border: 1px solid #000; /*不需要缩放的部分用px*/
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="button">按钮</div>
</body>
</html>

复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

CSS

:root {
  --ratio: calc(100vw/750);
}

.button {
  font-size: calc(100vw*28/750);  /* 直接用calc */
  line-height: calc(100vw*48/750);

  width: calc(120*var(--ratio));  /* 可以用calc配合var使用,IE不支持 */     
  border: 1px solid #000; /*不需要缩放的部分用px*/
  text-align: center;
}
复制成功
1
2
3
4
5
6
7
8
9
10
11
12

SCSS

:root {
  --ratio: calc(100vw/750);
}

.button {
  font-size: calc(100vw*28/750);  /* 直接用calc */
  line-height: calc(100vw*48/750);

  width: calc(120*var(--ratio));  /* 可以用calc配合var使用,IE不支持 */     
  border: 1px solid #000; /*不需要缩放的部分用px*/
  text-align: center;
}

复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
晓露寝安浅云逍遥十漾轻拟