如何适配不同分辨率和不同屏幕尺寸的手机
2023-12-11 07:00:45发布 浏览634次 信息编号:87636
友情提醒:凡是以各种理由向你收取费用,均有骗子嫌疑,请提高警惕,不要轻易支付。
如何适配不同分辨率和不同屏幕尺寸的手机
背景
开发移动H5页面
面对不同分辨率的手机
面对不同屏幕尺寸的手机
视觉模型
在前端开发之前, MM会给我们一个psd文件,称为视觉稿。
对于移动开发来说,为了实现页面的高清效果,视觉稿的规范往往会遵循以下两点:
首先,选择手机的屏幕宽度和高度作为基准(以前是320×480,现在更多的是375×667)。
对于屏幕(例如:dpr=2),为了达到高清效果,视觉稿的画布尺寸会是基线的两倍,也就是说像素数会是原来的4倍(例如:原来的375×667,会变成750×1334)。
问题:
对于dpr=2的手机,为什么尺寸×2就能解决高清问题呢?
对于两倍大小的视觉稿,如何在具体的CSS编码中恢复每个块的真实宽度和高度(即布局问题)?
带着疑问往下看……
一些概念
在进行具体分析之前,首先要了解以下关键的基本概念(术语)。
物理像素
物理像素是显示器(手机屏幕)上最小的物理显示单元。 在操作系统的调度下,每个设备像素都有自己的颜色值和亮度值。
设备独立像素(-pixel)
设备无关像素(也称为密度无关像素)可以被视为计算机坐标系中的一个点。 该点代表程序可以使用的虚拟像素(例如:CSS像素),然后由相关系统转换为物理像素。
因此,物理像素和设备无关像素之间存在一定的对应关系。 这就是我们接下来要讲的设备像素比。
设备像素比(像素比)
设备像素比(简称dpr)定义了物理像素和设备独立像素之间的对应关系。 其值可根据以下公式求得:
设备像素比 = 物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向
在 中,可以通过获取当前设备的dpr。
在css中,可以使用--pixel-ratio、--min--pixel-ratio和--max--pixel-ratio来执行媒体查询,并对不同DPR的设备进行一些样式适配(这仅适用于内核浏览器和)。
结合上面的概念,我们用例子来说明一下:
例如:
设备宽度和高度为375×667,可以理解为设备独立像素(或CSS像素)。
dpr为2,根据上面的计算公式,其物理像素应该为×2,即750×1334。
用图片来表达就是这样的(原谅我盗图):
如上图所示,对于这样的css样式:
width: 2px; height: 2px;
在不同的屏幕上(普通屏 vs 屏幕),CSS像素所呈现的尺寸(物理尺寸)是相同的,但不同的是,1个CSS像素对应的物理像素数量不一致。
在普通屏幕上,1 个 CSS 像素对应 1 个物理像素(1:1)。 在屏幕下,1个css像素对应4个物理像素(1:4)。
位图像素
位图像素是光栅图像(如 png、jpg、gif 等)的最小数据单元。 每个位图像素都包含一些自己的显示信息(如显示位置、颜色值、透明度等)。
说到这里就不得不说说下面图片的显示?
理论上,1个位图像素对应1个物理像素,这样图片才能完美、清晰地显示。
正常屏幕下没有问题,但屏幕下会出现位图像素不够,导致图片模糊的情况。
用一张图片来表示:
如上图:对于dpr=2的屏幕,1个位图像素对应4个物理像素。 由于单个位图像素无法进一步划分,因此只能从最近的位置取颜色,导致图片模糊(注意上面几个颜色值)。
因此,对于高清图片的问题,更好的解决方案是图片加倍(@2x)。
例如:200×300(css像素)img标签,您需要提供400×600的图片。
这样,位图像素数就变成了原来的4倍。 在屏幕下,位图像素数可以与物理像素数形成1:1的比例,图片自然就清晰了(这也解释了回答之前留下的一个问题,为什么视觉稿的画布大小是× 2?)。
这里还有一个问题。 如果在普通屏幕上使用两倍的图像会发生什么?
显然,在普通屏幕上,200×300(css像素)img标签对应的物理像素数为200×300,两倍图片的位图像素数为200×300*4,所以看起来一个物理像素对应四个位图像素,因此它的颜色选择只能经过一定的算法(显示结果是一张只有原图像总像素数四分之一的图片,我们称这个过程),虽然图片肉眼看上去不会模糊,会感觉图片缺乏一些清晰度或者有轻微的色差(但还是可以接受的)。
用一张图片来表示:
针对以上两个问题,我做了一个demo(内网访问),点击这里。
演示中将100×100张图片分别放入100×100、50×50、25×25的img容器中,并在屏幕上显示显示效果。
在条形图中,实际上可以通过放大镜看到边界像素值的差异:
图1,选择最接近的颜色,颜色值介于红色和白色之间,颜色越浅,图片就会显得模糊(可以理解为图片拉伸)。
图2,附近没有颜色,颜色值不是红色就是白色,图片看起来很清晰。
图3,取最接近的颜色,色值介于红白之间,偏重。 画面看上去有色差,缺乏清晰度(可以理解为画面挤压)。
有了爱字图片,你可以通过看“爱”字来判断图片是模糊还是清晰。
(ps:如果看起来不明显,可以用手机扫描网页(内网地址)或者点击原图看更清楚。
一些问题
下面讲一下移动H5开发在不同分辨率、屏幕的手机上会遇到的几个经典问题。
接下来,图片高清问题
上面已经介绍过这个问题的解决方案:将镜像加倍(@2x),然后将镜像容器缩小50%。
例如:图片尺寸,400×600;
1.img标签
width: 200px; height: 300px;
2.背景图片
width: 200px; height: 300px; background-image: url(image@2x.jpg); background-size: 200px 300px; // 或者: background-size: contain;
这样的缺点是显而易见的。 普通屏幕下:
我还下载了@2x的图片,造成资源浪费。
由于这个原因,图片会失去一些清晰度(或色差)。
所以最好的解决方案是:在不同的dprs下加载不同尺寸的图片。
无论是通过css媒体查询还是条件判断,都是可以的。
那么问题来了,这样的话,我们是不是需要准备两组图片呢? (@1x 和 @2x)
我想任何好的公司都会有这样的图片服务器,可以通过URL获取参数,然后控制图片的质量,或者将图片裁剪成不同的尺寸。
所以我们只需要上传大图(@2x),其他小图将由图片服务器处理。 我们只需要负责URL的拼接即可。
比如这张原图:
https://img.alicdn.com/tps/TB1AGMmIp**afXp****XX.jpg // 原图
您可以像这样裁剪图像:
// 200×200 https://img.alicdn.com/tps/TB1AGMmIp**afXp****XX.jpg_200x200.jpg // 100×100 https://img.alicdn.com/tps/TB1AGMmIp**afXp****XX.jpg_100x100.jpg
(ps:当然,裁剪只是对原图按比例裁剪,你要保证图像清晰~)
下一篇:1px问题
这可能是设计师最敏感、最关心的问题。
首先我要说一下为什么会有:1px这个东西?
我们正常写css,像这样:1px;,在屏幕下面会不会有问题呢?
首先我们看一下下面这张图:
上面两张图分别是(dpr=1)和(dpr=2)下的测试结果。 相比之下,对于1px的显示,它们是一致的,没有差异。
那么显示屏的优点是什么? 为什么设计师认为高清屏幕下的线条(如右图)很粗? 明显是左右都是一样的~
我通过一张图来解释一下(原谅我又盗图了):
上图中,对于1px宽的直线,它们在屏幕上的物理尺寸(灰色区域)确实是相同的。 区别其实就是屏幕上最小的物理显示单元,也就是物理像素,所以对于一条直线来说,它能显示的最小宽度实际上就是图中红圈所画的灰色区域,用CSS来表示,理论上是0.5px。
因此,设计者想要的是:1px;,实际上是1个物理像素宽。 对于CSS来说,可以认为是:0.5px;,这是(dpr=2)下可以显示的最小单位。
不过遗憾的是并不是所有的手机浏览器都能识别:0.5px;,ios7以下,以及其他系统,0.5px会被当成0px,那么这个0.5px怎么实现呢?
最简单的方法是这样的(元素比例):
.scale{
position: relative;
}
.scale:after{
content:"";
position: absolute;
bottom:0px;
left:0px;
right:0px;
border-bottom:1px solid #ddd;
-webkit-transform:scaleY(.5);
-webkit-transform-origin:0 0;
}
我们写-:1px实体#ddd; 照常,然后缩小0.5倍:(.5),达到0.5px的效果。 不过这个hack通用性不够(比如圆角等),而且写起来比较麻烦。
当然,还有很多其他的破解方法,可以在网上搜索到,但每种方法都有自己的优点和缺点。 这里比较推荐的是页面缩放方案,它的通用性比较强,几乎可以满足所有场景。
对于 (dpr=2),添加以下元标记并设置(比例 0.5):
这样页面中的all:1px就会缩小0.5,从而达到:0.5px;的效果。
有人担心缩放后页面的性能会受到影响。 @做了一个性能测试,见这里(内网地址)。
看一下实现后的效果图对比(右图是优化后的):
(ps:图片经过压缩,可能看起来不太明显,可以用手机扫码或者点击这里(内网地址)进行对比)
然而,页面缩放不可避免地会带来一些问题:
字体大小将会缩放
页面布局会缩放(如:div宽度和高度等)
这两个问题稍后讨论……
多屏适配布局问题
对于移动布局,为了适应各种大屏手机,目前最好的解决方案是使用相对单位rem。
基于rem的原理,我们要做的是:根据不同的手机屏幕尺寸和dpr,动态改变根节点html的font-size大小(基值)。
这里我们提取一个公式(rem代表参考值)
rem = document.documentElement.clientWidth * dpr / 10
阐明:
乘以 dpr,因为页面可能会缩放 1/dpr 倍才能达到 1px(如果没有,则 dpr=1)。
除以10是为了四舍五入,方便计算(理论上可以是任意值)
所以像下面这样,html的font-size可能是:
: 320 像素 / 10 = 32 像素
/5: 320 像素 * 2 / 10 = 64 像素
: 375 像素 * 2 / 10 = 75 像素
对于动态改变根节点html的font-size,我们可以通过css来实现,也可以通过.
使用CSS,您可以通过设备宽度和媒体查询来更改html的字体大小:
html{font-size: 32px;}
//iphone 6
@media (min-device-width : 375px) {
html{font-size: 64px;}
}
// iphone6 plus
@media (min-device-width : 414px) {
html{font-size: 75px;}
}
*/
缺点:通过设备宽度范围等媒体查询动态改变rem参考值不够准确。 例如:宽度为360px和宽度为320px的手机,因为屏幕宽度在同一范围内(
方法,通过上面的公式,计算出参考值rem,然后编写样式,大致如下(代码引用自kimi的m-base模块)
var dpr, rem, scale;
var docEl = document.documentElement;
var fontEl = document.createElement('style');
var metaEl = document.querySelector('meta[name="viewport"]');
dpr = window.devicePixelRatio || 1;
rem = docEl.clientWidth * dpr / 10;
scale = 1 / dpr;
// 设置viewport,进行缩放,达到高清效果
metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no');
// 设置data-dpr属性,留作的css hack之用
docEl.setAttribute('data-dpr', dpr);
// 动态写入样式
docEl.firstElementChild.appendChild(fontEl);
fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';
// 给js调用的,某一dpr下rem和px之间的转换函数
window.rem2px = function(v) {
v = parseFloat(v);
return v * rem;
};
window.px2rem = function(v) {
v = parseFloat(v);
return v / rem;
};
window.dpr = dpr;
window.rem = rem;
该方法可以准确计算出不同屏幕的rem参考值。 缺点是需要加载这么一段js代码,但我个人认为这是目前最好的解决方案。
因为这个方案同时解决了三个问题:
: 1px 问题
图片高清问题
屏幕适配布局问题
说到布局,自然要回答最初的问题:CSS编码中如何还原视觉稿的真实宽度和高度?
先决条件:
我得到的是750×1334的高清视觉稿
使用上述高清方案(js代码)。
如果psd文件中有一个测量的块:一个宽高为750×300px的div,那么如何将其转换为rem单位呢?
公式如下:
rem = px / 基准值;
对于模型来说,它的基线值为 75(之前提到过);
因此,在确定视觉草案(即确定基线值)后,我们通常使用 less 来编写 mixin,如下所示:
// 例如: .px2rem(height, 80);
.px2rem(@name, @px){
@{name}: @px / 75 * 1rem;
}
所以,对于一个宽高为750×300px的div,我们使用less,这样写:
.px2rem(width, 750); .px2rem(height, 300);
转换成html就是这样:
width: 10rem; // -> 750px height: 4rem; // -> 300px
最后,由于dpr为2,页面缩放了0.5,所以手机屏幕上实际显示的宽高应该是375×150px,刚刚好。
如果页面没有比例 0.5,我们的代码将如下所示:
.px2rem(width, 375); .px2rem(height, 150);
我们经常得到这样的宽度和高度:
将750×1334的模型转换成375×667的尺寸后,再测量这个块的尺寸(感觉好傻)。
测量出750×1334的块宽高为750×300px后,口头除以2(感觉很麻烦)。
最后给出一张没有布局适配(上图)和有rem布局适配(下图)的对比图:
(以上手机为:、、)
很明显,适应rem的每个块的宽度和高度会随着手机屏幕宽度的变化而变化。 最明显的可以从图片列表中看到。 最后一张图稿要求只出现一点点,rem布局在任何屏幕上看起来都很棒。
字体大小问题
由于上述方案会导致页面缩放,因此页面块的宽度和高度我们可以依靠高清样机来确定。 因为模型已经是×2了,所以我们可以直接测量它。 那么我们应该如何处理字体呢? ?
关于字体缩放的问题,设计者最初的要求是这样的:任何手机屏幕上的字体大小必须是统一的,所以我们会针对不同的分辨率(不同的dpr)做如下处理:
font-size: 16px;
[data-dpr="2"] input {
font-size: 32px;
}
(注意字体不能使用rem,误差太大,而且任何屏幕上字体大小都不能一样)
为了方便起见,我们还将使用 less 编写一个 mixin:
.px2px(@name, @px){
@{name}: round(@px / 2) * 1px;
[data-dpr="2"] & {
@{name}: @px * 1px;
}
// for mx3
[data-dpr="2.5"] & {
@{name}: round(@px * 2.5 / 2) * 1px;
}
// for 小米note
[data-dpr="2.75"] & {
@{name}: round(@px * 2.75 / 2) * 1px;
}
[data-dpr="3"] & {
@{name}: round(@px / 2 * 3) * 1px
}
// for 三星note4
[data-dpr="4"] & {
@{name}: @px * 2px;
}
}
(注:html的data-dpr属性在前面的js解决方案中提到过,这里有用)
根据经验和测试,这些奇怪的 DPR 仍然会出现。 这里我们统一兼容~
使用时,它看起来像这样:
.px2px(font-size, 32);
当然,对于其他css属性,如果你也要求它们在不同DPR下保持一致,也可以这样做,比如:
.px2px(padding, 20); .px2px(right, 8);
终于
以上是对移动H5高清及多屏适配的一些解决方案的总结,以及知识讲解。 如有错误请指出新浪微博- 。
提醒:请联系我时一定说明是从星空网上看到的!