阅读 2547

移动端适配深度探究

我在网上看过很多相关的资料,都在说淘宝适配方案和网易适配方案。说了dpr,meta等好多概念,说实话我感觉写的都好复杂,跟我自己想的有出入。新学东西我总想找到这个东西设计的出发点,但我没在这些文章中找出来。在看了些现在主流网站的代码后,觉得自己有了一点心得,所以献丑拿来分享下,希望对你有点帮助

准备

既然是适配我们开始肯定要有一个参考屏幕,这里我们先提前确定下面所有的例子都是以iphone6的屏幕(宽度为375px)为参照。通常设计稿是2倍的设计稿,所以我们拿到的设计稿设计稿最终宽度为750px

屏幕适配

屏幕适配最终的目标或者说本质就是实现 等比缩放

现在各大网站虽然方案有差异,但步骤和目的其实是一样的,主要分为以下几步:

  1. 找到一个基准,基准能随屏幕宽度变化
  2. 确定基准的值
  3. 根据基准的值来写我们的样式

为什么要有个基准?因为我们不希望每种屏幕写一种布局样式,所以我们需要有一个基准来随屏幕宽度变化,我们只要根据基准来确定我们的css值,就可以适配所有的屏幕了。

这就是适配的全部了,下面我们来看看这几步可以用什么方案来解决。

基准是什么?为了简单基准我们看成单位,所以我们需要找一个能变化的单位,思考下,css中哪些单位可以变化?rem是以根字体的大小来确定自己的值的,符合条件。所以我们可以让根字体随屏幕变化而变化,我们直接用rem进行布局可以了。

下一步就是确定基准值,我们这里就是确定根字体的值。为了方便我们计算我们可以设置一个很容易计算的值,比如我们可以让设计稿中1rem=100px,那么写起来就是

// 屏幕宽度 / 7.5 = 1rem

// 或

// 100vw  / 7.5 = 1rem
复制代码

这两种在这个例子中是一样的,然后我们写样式的时候用rem做为单位就可以了,比如设计稿上有一个宽度为80pxdiv元素,我们只需要这样写:

div {
  width: .8rem;
}
复制代码

如果你还是嫌每次手动计算麻烦,可以用现在样式预处理器(如less、sass)中的mixin的来帮你或者使用js来动态计算。

到这里我们的适配就说完了。你可能会问dpr、meta头设置视图宽度那些东西怎么没看到,我明明在很多文章看到这些概念。别急,其实这些都是为了解决一个问题,下面我们就来说说这个问题

hairline

hairline是啥?hairline其实就是很细的线,很多设计师特别喜欢用这种线,让我们前端头大🙄。这种线直接用0.5px行吗?这在以前一些旧的屏幕上是不行的,会被自动修正为1px,我们都知道。

但是现代很多手机都是高倍屏,即一个css像素会有多个物理像素,这样显示的图像更细腻并且更清晰,有的已经支持css使用小数,这种情况下我们可以直接使用像0.5px来写出这种宽度的线了。这里有个概念,物理像素数和css像素被称为设备像素比,也就是我们经常说的dpr了

物理像素数 / css像素数 = dpr
复制代码

dpr的值可以通过window.devicePixelRadio来获取。

问题好像已经解决了。但是我们前端还有很重要的一部分的工作是兼容,如果遇到不支持这种小数css写法的怎么办?我们想个很通用的解决方案,那就是缩放,比如我们把1px宽度的线缩小一半就能得到0.5px宽度的线了。

为了让我们所有1px宽度缩为一个物理像素宽,我们就需要让页面宽度为屏幕css宽度 * dpr。然后我们在这个宽度下写1px宽度的线,最后再缩小dpr倍我们就可以得得到1物理像素宽度了。

为了实现让页面变为屏幕css宽度 * dpr的宽的目的,我们需要按比例改变我们上面的适配方案。

假如现在dpr=3,我们就需要让页面宽度为 375 * 3 = 1125,而我们的设计稿是750。我们就需要让我们的基准值成比例变化

// 屏幕宽度 / 7.5 => 屏幕宽度 / 7.5 / 2 * 3
复制代码

现在我们得到尺寸为屏幕css宽度 * dpr的页面了,为了让页面完全显示在屏幕中我们需要在html中设置meta头(不了解这些的自己查下,有很多资料)

<meta name="viewport" content="width=屏幕css宽度 * dpr">
复制代码

然后缩小dpr倍变成

<meta name="viewport" content="width=屏幕css宽度 * dpr,initial-scale=1/dpr,minimum-scale=1/dpr,maximum-scale=1/dpr,user-scalable=no">
复制代码

到这里,我们所有东西都讲完了,希望你已经理解了为什么会有那么多写法不同的适配方案了,他们都是殊途同归。

思考题

最后附上现在淘宝和网易的部分代码,你可以自己直接去他们网站找到这些代码。你应该能根据这些代码分析他们的方案了,这些留给你自己思考和分析了

手机淘宝网部分适配代码

! function (e, t) {
  var n = t.documentElement,
    d = e.devicePixelRatio || 1;

  function i() {
    var e = n.clientWidth / 3.75;
    n.style.fontSize = e + "px"
  }
  if (function e() {
      t.body ? t.body.style.fontSize = "16px" : t.addEventListener("DOMContentLoaded", e)
    }(), i(), e.addEventListener("resize", i), e.addEventListener("pageshow", function (e) {
      e.persisted && i()
    }), 2 <= d) {
    var o = t.createElement("body"),
      a = t.createElement("div");
    a.style.border = ".5px solid transparent", o.appendChild(a), n.appendChild(o), 1 === a.offsetHeight && n.classList.add("hairlines"), n.removeChild(o)
  }
}(window, document)
复制代码

手机网易新闻网部分适配代码

html {
    font-size: 13.33333vw
}

@media screen and (max-width: 320px) {
    html {
        font-size:42.667px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 321px) and (max-width:360px) {
    html {
        font-size:48px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 361px) and (max-width:375px) {
    html {
        font-size:50px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 376px) and (max-width:393px) {
    html {
        font-size:52.4px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 394px) and (max-width:412px) {
    html {
        font-size:54.93px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 413px) and (max-width:414px) {
    html {
        font-size:55.2px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 415px) and (max-width:480px) {
    html {
        font-size:64px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 481px) and (max-width:540px) {
    html {
        font-size:72px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 541px) and (max-width:640px) {
    html {
        font-size:85.33px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 641px) and (max-width:720px) {
    html {
        font-size:96px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 721px) and (max-width:768px) {
    html {
        font-size:102.4px;
        font-size: 13.33333vw
    }
}

@media screen and (min-width: 769px) {
    html {
        font-size:102.4px;
        font-size: 13.33333vw
    }
}
复制代码

本文原文更新在我的github上,这里是原文链接。如果文章有任何错误或不准确之处,欢迎指出,非常感谢!