移动端适配及1px问题探究
本文最后更新于 807 天前,其中的信息可能已经有所发展或是发生改变。

1. 概念

设备独立像素(逻辑像素、CSS 像素、直觉像素)

设备独立像素:又称为虚拟像素、CSS 像素或逻辑像素,也可以理解为直觉像素。是 Web 编程的概念,指的是 CSS 样式代码中使用的逻辑像素。比如 iPhone 6 的 CSS 像素数为 375 x 667px。

物理像素(设备像素)

设备像素(物理像素),顾名思义,显示屏是由一个个物理像素点组成的,通过控制每个像素点的颜色,使屏幕显示出不同的图像,屏幕从工厂出来那天起,它上面的物理像素点就固定不变了,单位pt。比如 iPhone 6 的物理像素数为 750 x 1334pt。

设备像素比

设备像素比device pixel ratio简称dpr,即物理像素和设备独立像素的比值。比如 iPhone 6 的设备像素比为 750 / 375 = 2。

目前移动端设备的一些参数

2 移动端适配

2.1 原因

在现在移动终端快速更新的时代,每个品牌的手机屏幕都有着不同的设备宽,一般情况下设计稿的设计师按照750px的尺寸设计,设计稿的1px与设备的1px并不等同,那如何能够让750的设计稿等比例的适配到不同的屏幕宽的手机设备呢,就引出了移动端适配的问题

2.2 如何适配

那么在移动端如何适配呢? 那就是viewport + rem实现

viewport

这里主要指布局视口,当我们以百分比来指定一个元素的大小时,它的计算值是由这个元素的包含块计算而来的。当这个元素是最顶级的元素时,它就是基于布局视口来计算的。

在移动端,布局视口被赋予一个默认值,大部分为980px,这保证PC的网页可以在手机浏览器上呈现,但是非常小,用户可以手动对网页进行放大。

我们可以通过调用document.documentElement.clientWidth来获取布局视口宽,document.documentElement.clientHeight来获取布局视口高。

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

各个属性含义如下

于是上述的meta设置,就是我们的理想设置,他规定了我们的视口宽度为屏幕宽度,初始缩放比例为1,就是初始时候我们的视觉视口就是理想视口!

rem

rem是相对于html元素的font-size来做计算的计算属性值。 通过设置documentElement的fontSize属性值就可以统一整个页面的布局标准。

rem的布局其实这是阿里早期开源的一个移动端适配解决方案flexible方案,引用flexible后,我们在页面上统一使用rem来布局。

rem 是相对于html节点的font-size来做计算的。所以在页面初始话的时候给根元素设置一个font-size,接下来的元素就根据rem来布局,这样就可以保证在页面大小变化时,布局可以自适应。

var deviceWidth = document.documentElement.clientWidth || document.body.clientWidth;
var rootFontSize = (deviceWidth / 750).toFixed(2);
document.documentElement.style.fontSize = rootFontSize  + 'px';

如此我们只需要给设计稿的px转换成对应的rem单位即可

所以综上,整体适配就是

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
var deviceWidth = document.documentElement.clientWidth || document.body.clientWidth;
var rootFontSize = (deviceWidth / 750).toFixed(2);
document.documentElement.style.fontSize = rootFontSize  + 'px';

3. 1px问题

3.1 原因

大家会发现有时候设计稿的1px在移动端显示不尽相同,那么为什么会产生这个问题呢?

从移动端的角度说个具体的场景,以iphone6为例。 iphone6的屏幕宽度为375px,设计师做的视觉稿一般是750px,根据 viewport + rem 计算得处目前页面根元素大小,也就是

document.documentElement.style.fontSize = deviceWidth / 750 = 0.5

在按照设计稿1px,我们在页面的样式文件中写成

div {
 border: 1rem;
}
// 其中 1rem = 1 * 0.5 = 0.5

注意:由于不同设备的浏览器不同,而不同的浏览器对于小于1px的处理方式不同。比如火狐对于小于1px的都当作0.5px处理,谷歌对于小于1px都是1px,导致在不同设备上1px的表现各不相同。

这就引出了1px兼容性问题。

3.2 怎么解决

那如何解决1px的问题,通过transform、动态viewport + rem实现

此次实现border为1px的边框

1). 动态 viewport + rem

上面我们说了viewport + rem 解决了移动端适配的问题,但是为什么这里还要再去说呢 注意看移动端适配的时候我们这里的 viewport 中 initial-scale = 1 为什么等于 1 呢,这里主要偷懒了一下,因为 initial-scale = 1 对于适配并无大影响,只会影响1px。

scale = 1 / dpr;

乔布斯在iPhone4的发布会上首次提出了Retina Display(视网膜屏幕)的概念,在iPhone4使用的视网膜屏幕中,把2×2个像素当1个像素使用,这样让屏幕看起来更精致,但是元素的大小却不会改变。

跟上面我们说的有关,DPR(devicePixelRatio) 设备像素比,它是默认缩放为100%的情况下,设备像素和CSS像素的比值。

window.devicePixelRatio=物理像素 /CSS像素

目前主流的屏幕DPR=2 (iPhone 8),或者3 (iPhone 8 Plus)。要想initial-scale的值更精确,那么就动态设置viewport,其中initial-scale 缩放值越大,当前 viewport 的宽度就会越小,反之亦然。比如:

其中设备宽375时,当dpr=1的时候,设备宽为375

rem = 375 / 750 = 0.5
(设计稿1px = 1rem = 0.5px)

其中当dpr=2的时候,设备宽为750

rem = 750 / 750 = 1
(设计稿1px = 1rem = 1px)

对于设备来说实际都是1px,但是利用动态 viewport 避免了出现 0.5 的数字,便避免了浏览器对于小于 1px 的兼容性问题。

所以,整体动态 viewport + rem如下

<script>    
    var viewport = document.querySelector("meta[name=viewport]");
    
    if (window.devicePixelRatio == 1) {
            viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
    }
    if (window.devicePixelRatio == 2) {
            viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
    }
    if (window.devicePixelRatio == 3) {
            viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
    }
    var docEl = document.documentElement;
    var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
    docEl.style.fontSize = fontsize;

</script>

此方法适用于新项目,老项目改动点过多。

2). transform

CSS transform 属性允许你旋转,缩放,倾斜或平移给定元素。这是通过修改CSS视觉格式化模型的坐标空间来实现的。

这里用到了scale属性

.setBorderAll{
     position: relative;
       &:after{
           content:" ";
           position:absolute;
           top: 0;
           left: 0;
           width: 200%;
           height: 200%;
           transform: scale(0.5);
           transform-origin: left top;
           box-sizing: border-box;
           border: 1px solid #E5E5E5;
           border-radius: 4px;
      }
    }

将伪元素设置绝对定位,并且和父元素的左上角对齐,为了只缩放 border 1px 的粗细,而保证 border 的大小不变,将width、hegiht 设置200%,height设置为1px,然后进行在Y方向缩小0.5倍。

该方案的优点在于,针对老项目使用缩放的形式可以快速实现 1px 的效果。

总结

所以1px兼容的话老项目整体修改 viewport 成本过高,可以采用第二种实现方案进行 1px 的处理;新项目的话可以采用动态设置 viewport 的方式,一键解决所有适配问题。

适配与兼容是工作中必不可少的一环,周全的适配与兼容也是将产品能做的能好。尤其对于紧急周期短的项目,往往对于视觉走查都要求较薄弱,这个部分便变成了我们在开发环节的自我把控,那么对于这些兼容的点慢慢形成自己的沉淀,做到拿来即用在项目中将会方便了许多。

标题:移动端适配及1px问题探究
地址:https://xiaodongxier.com/1237.html
作者:王永杰
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇