参考文章

  1. 移动前端自适应解决方案和比较
  2. css 中的长度
  3. IOS 适应性和布局

简单描述一下需求: 首先是传统的移动端自适应,即无论是大屏还是小屏手机,看到的排版应该是一样的,只是根据屏幕尺寸做等比缩放。第二点是仿照youtube的排版方式,在手机处于横屏的时候,页面元素内容的尺寸大小必须和竖屏的时候一样(这里就不是单纯的缩放就能解决的)。

由于第二个需求点,如果直接使用网易的方案,会在横屏时将页面元素放大,不符合需求。
引用某 UI 的话:更大的屏幕是为了可以看到更多的内容,而不是更大的内容

1.准备

head中添加一下meta属性。这是为了禁用页面缩放。

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />

兼容性。由于vw单位只能在IE9+上使用,如果需要兼容IE8,那此方案不适合。

2.原理

  1. 先判断当前屏幕是竖屏还是横屏
const w = window.innerWidth;
const h = window.innerHeight;
const isVertical = w / h < 1;
  1. 获取要使用的由 UI 提供的设计尺寸
const designWidth = isVertical ? V_DESIGN_WIDTH : H_DESIGN_WIDTH;
  1. 计算在设计稿中,1px占设计稿宽度的百分百dvw
// 这里保留4位小数
const dvw = Math.floor((10000 * 100) / designWidth) / 10000;
  1. dvw转化为html中对应的大小fontSize(使用 vw 单位)
const fontSize = dvw + "vw";
document.getElementsByTagName("html")[0].style.fontSize = fontSize;
  1. 使用rem单位,将设计稿中元素的尺寸转化为html页面中的尺寸
.target_element {
  // width: 200px; 只需要将'px'换成'rem'即可
  width: 200rem;
}
  1. 最后,只需要 UI 小姐姐另外提供横屏的设计稿即可

3.完整的 demo

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
    />
    <title>Document</title>

    <style>
      html,
      body {
        padding: 0;
        margin: 0;
      }

      .container {
        display: flex;
        flex-wrap: wrap;
        margin-top: 10px;
      }

      .box {
        /* width: 150px; */
        /* height: 150px; */

        /* 将原来的'px'替换成'rem' */
        width: 150rem;
        height: 150rem;
      }

      .box:nth-child(even) {
        background-color: rgb(65, 162, 218);
      }

      .box:nth-child(odd) {
        background-color: rgb(255, 151, 151);
      }
    </style>
  </head>
  <body>
    <p>设计稿中,竖屏方向时,每个方块的宽度占屏幕总宽的1/5</p>
    <p>
      由于指定的横屏方向的宽度是竖屏的2倍(便于观察),当切换成横屏时,每个方块的宽度应该为总宽的1/10
    </p>
    <div class="container">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>

    <script>
      const V_DESIGN_WIDTH = 750;
      const H_DESIGN_WIDTH = 1500; //这里先假设横屏时,尺寸是竖屏的两倍

      function getSize() {
        const w = window.innerWidth;
        const h = window.innerHeight;
        const isVertical = w / h < 1;
        const designWidth = isVertical ? V_DESIGN_WIDTH : H_DESIGN_WIDTH;

        // 750px = 100vw -> 1px = ?vw
        const dvw = Math.floor((10000 * 100) / designWidth) / 10000;
        const fontSize = dvw + "vw";

        document.getElementsByTagName("html")[0].style.fontSize = fontSize;
      }

      window.addEventListener("load", getSize);
      window.addEventListener("resize", getSize);
    </script>
  </body>
</html>

darcrand
637 声望20 粉丝