我在网上看过很多相关的资料,都在说淘宝适配方案和网易适配方案。说了dpr,meta等好多概念,说实话我感觉写的都好复杂,跟我自己想的有出入。新学东西我总想找到这个东西设计的出发点,但我没在这些文章中找出来。在看了些现在主流网站的代码后,觉得自己有了一点心得,所以献丑拿来分享下,希望对你有点帮助
准备
既然是适配我们开始肯定要有一个参考屏幕,这里我们先提前确定下面所有的例子都是以iphone6的屏幕(宽度为375px
)为参照。通常设计稿是2倍的设计稿,所以我们拿到的设计稿设计稿最终宽度为750px
。
屏幕适配
屏幕适配最终的目标或者说本质就是实现 等比缩放。
现在各大网站虽然方案有差异,但步骤和目的其实是一样的,主要分为以下几步:
- 找到一个基准,基准能随屏幕宽度变化
- 确定基准的值
- 根据基准的值来写我们的样式
为什么要有个基准?因为我们不希望每种屏幕写一种布局样式,所以我们需要有一个基准来随屏幕宽度变化,我们只要根据基准来确定我们的css值,就可以适配所有的屏幕了。
这就是适配的全部了,下面我们来看看这几步可以用什么方案来解决。
基准是什么?为了简单基准我们看成单位,所以我们需要找一个能变化的单位,思考下,css中哪些单位可以变化?rem
是以根字体的大小来确定自己的值的,符合条件。所以我们可以让根字体随屏幕变化而变化,我们直接用rem
进行布局可以了。
下一步就是确定基准值,我们这里就是确定根字体的值。为了方便我们计算我们可以设置一个很容易计算的值,比如我们可以让设计稿中1rem=100px
,那么写起来就是
// 屏幕宽度 / 7.5 = 1rem
// 或
// 100vw / 7.5 = 1rem
复制代码
这两种在这个例子中是一样的,然后我们写样式的时候用rem
做为单位就可以了,比如设计稿上有一个宽度为80px
的div
元素,我们只需要这样写:
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 / dpr
复制代码
现在我们得到尺寸为屏幕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上,这里是原文链接。如果文章有任何错误或不准确之处,欢迎指出,非常感谢!