本文介绍了移动端适配的3种方法,以及移动端图片模糊问题和1px细线问题的解决方法。当然了,在这之前先整理了与这些方法相关的知识:物理像素、设备独立像素、设备像素比和viewport。
>>>>物理像素、设备独立像素和设备像素比
在CSS中我们一般使用px作为单位,需要注意的是,CSS样式里面的px和物理像素并不是相等的。CSS中的像素只是一个抽象的单位,在不同的设备或不同的环境中,CSS中的1px所代表的物理像素是不同的。在PC端,CSS的1px一般对应着电脑屏幕的1个物理像素,但在移动端,CSS的1px等于几个物理像素是和屏幕像素密度有关的。
物理像素(physical pixel)
物理像素又被称为设备像素、设备物理像素,它是显示器(电脑、手机屏幕)最小的物理显示单位,每个物理像素由颜色值和亮度值组成。所谓的一倍屏、二倍屏(Retina)、三倍屏,指的是设备以多少物理像素来显示一个CSS像素,也就是说,多倍屏以更多更精细的物理像素点来显示一个CSS像素点,在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素(参照下文田字示意图理解)。
设备独立像素(device-independent pixel)
设备独立像素又被称为CSS像素,是我们写CSS时所用的像素,它是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。
设备像素比(device pixel ratio)
设备像素比简称为dpr,定义了物理像素和设备独立像素的对应关系:设备像素比 = 物理像素 / 设备独立像素。
CSS的1px等于几个物理像素,除了和屏幕像素密度dpr有关,还和用户缩放有关系。例如,当用户把页面放大一倍,那么CSS中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,CSS中1px所代表的物理像素也会减少一倍。关于这点,在文章后面的1px细线问题部分还会讲到。
>>>>viewport
viewport就是设备上用来显示网页的那一块区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览器的可视区域要大,也可能比浏览器的可视区域要小。在默认情况下,一般来讲,移动设备上的viewport都是要大于浏览器可视区域的,这是因为考虑到移动设备的分辨率相对于桌面电脑来说都比较小,所以为了能在移动设备上正常显示那些传统的为桌面浏览器设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),但带来的后果就是浏览器会出现横向滚动条,因为浏览器可视区域的宽度是比这个默认的viewport的宽度要小的。
明确三种不同的viewport视口:
visual viewport 可见视口,指屏幕宽度
layout viewport 布局视口,指DOM宽度
ideal viewport 理想适口,使布局视口就是可见视口即为理想适口
获取屏幕宽度(visual viewport)的尺寸:
window. innerWidth/Height
获取DOM宽度(layout viewport)的尺寸:
document. documentElement. clientWidth/Height
设置理想视口ideal viewport:
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
该meta标签的作用是让layout viewport的宽度等于visual viewport的宽度,同时不允许用户手动缩放,从而达到理想视口。
meta[name="viewport"]里各参数的含义为:
width: 设置layout viewport 的宽度,为一个正整数,或字符串”width-device”。
initial-scale: 设置页面的初始缩放值,为一个数字,可以带小数。
minimum-scale: 允许用户的最小缩放值,为一个数字,可以带小数。
maximum-scale: 允许用户的最大缩放值,为一个数字,可以带小数。
height: 设置layout viewport 的高度,这个属性对我们并不重要,很少使用。
user-scalable: 是否允许用户进行缩放,值为“no”或“yes”。
>>>>rem适配方案
适配是为了使页面在不同手机设备上,相对保持统一的效果。移动端自适应方案很多,有百分比布局,弹性盒模型布局等,但是最好用的要数rem布局了。
rem是相对于根元素的字体大小的单位,我们可以根据设备宽度动态设置根元素的font-size,使得以rem为单位的元素在不同终端上以相对一致的视觉效果呈现。下面介绍3种根据屏幕宽度设置rem基准值的方法。(注:为了换算方便,以下三种方法都用1:100的比例,即1rem=100px。)
用JS设置rem基准值
/* 设计稿是750,采用1:100的比例,用1rem表示100px,font-size为100 * (clientWidth / 750) */
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
用密集的媒体查询设置font-size
/* 设计稿是750,采用1:100的比例,用1rem表示100px,100*(100/750)=13.333 以min-width: 750px时font-size: 100px为基准,
min-width每缩小100px,font-size就缩小13.3333px,如需更密集的媒体查询可以按照这个对照关系设置。*/
@media screen and (min-width: 320px) {
html {
font-size: 42.6667px;
}
}
@media screen and (min-width: 375px) {
html {
font-size: 50px;
}
}
@media screen and (min-width: 425px) {
html {
font-size: 56.6667px;
}
}
@media screen and (min-width: 768px) {
html {
font-size: 102.4px;
}
}
用单位vw设置font-size
1vw等于屏幕可视区宽度(的可视区域的百分之一。
/* 设计稿是750,采用1:100的比例,用1rem表示100px,font-size为100*(100vw/750) */
html {
font-size: 13.3334vw;
}
注:兼容性不是很好。
了解了物理像素、设备独立像素、设备像素比和viewport这几个重要概念后,来看一下移动端开发中,由于屏幕分辨率导致的两个经典问题:图片模糊问题和1px细线问题。(注:为了叙述简洁,以下多倍屏均只叙述2倍Retina屏,其它屏幕同理。)
>>>>图片模糊问题
一个位图像素是栅格图像(如:png, jpg, gif等)最小的数据单元。每一个位图像素都包含着一些自身的显示信息(如:显示位置,颜色值,透明度等)。理论上,1个位图像素对应于1个物理像素,图片才能得到完美清晰的展示。对于dpr=2的Retina屏幕而言,1个位图像素对应于4个物理像素,由于单个位图像素不可以再进一步分割,所以只能就近取色,导致图片看起来比较模糊,如下图。
对于图片模糊问题,比较好的方案就是用多倍图片(@2x)。如:一个200×300(CSS pixel)的img标签,对于dpr=2的屏幕,用400×600的图片,如此一来,位图像素点个数就是原来的4倍,在Retina屏幕下,位图像素点个数就可以跟物理像素点个数形成 1 : 1的比例,图片自然就清晰了。
如果普通屏幕下,也用了两倍图片,会怎样呢?
在普通屏幕下,200×300(CSS pixel)img标签,所对应的物理像素个数就是200×300个,而两倍图片的位图像素个数是200×300×4个,所以就出现一个物理像素点对应4个位图像素点,但它的取色也只能通过一定的算法取某一个位图像素点上的色值,这个过程叫做(downsampling),肉眼看上去虽然图片不会模糊,但是会觉得图片缺少一些锐利度,或者是有点色差,如下图。
所以最好的解决办法是:不同的dpr下,加载不同的尺寸的图片。不管是通过CSS媒体查询,还是通过JS条件判断都是可以的。
>>>>1px细线问题
在上文我们已经知道,CSS像素为1px宽的直线,对应的物理像素是不同的,可能是2px或者3px,而设计师想要的1px宽的直线,其实就是1物理像素宽,如下图。
对于CSS而言,可以认为是border: 0.5px;,这是多倍屏下能显示的最小单位。然而,并不是所有手机浏览器都能识别border: 0.5px,有的系统里,0.5px会被当成为0px处理,那么如何实现这0.5px呢?网上有很多解决方法,比如border-image 图片、background-image 渐变、box-shadow 等,因为这些方案不太好,所以不做赘述了,我推荐两种方法:用媒体查询根据dpr用“伪元素+transform”对边框进行缩放;用JS根据屏幕尺寸和dpr精确地设置不同屏幕所应有的rem基准值和initial-scale缩放值。
伪元素+transform
构建1个伪元素, border为1px, 再以transform缩放到50%。
/* 设计稿是750,采用1:100的比例,font-size为100*(100vw/750) */
.border-1px {
position: relative;
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border-1px:before {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
border-top: 1px solid #D9D9D9;
color: #D9D9D9;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
用JS计算rem基准值和viewport缩放值
/* 设计稿是750,采用1:100的比例,font-size为100 * (docEl.clientWidth * dpr / 750) */
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 = 100 * (docEl.clientWidth * dpr / 750);
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之用,解决图片模糊问题和1px细线问题
docEl.setAttribute('data-dpr', dpr);
// 动态写入样式
docEl.firstElementChild.appendChild(fontEl);
fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';
相较与于上文rem适配方案里“用JS计算rem基准值”的方案,这个“用JS计算rem基准值和viewport缩放值”的方案可以解决1px细线问题。表格以2倍Retina屏做比较,其他多倍屏同理。
用JS根据屏幕尺寸和dpr精确地设置不同屏幕所应有的rem基准值和initial-scale缩放值,这个JS方案已经在完美解决了1px细线问题,我们不需要再做任何事情,至于图片模糊问题,只需要根据data-dpr的值动态加载不同尺寸的图就可以了。
分享一个公众号-----前端麻辣烫 ,一个专注于前端技术学习与交流的公众号~
微信搜索“WebSnacks”,或者扫描下方二维码。
移动端高清适配方案(解决图片模糊问题、1px细线问题)的更多相关文章
-
webapp:移动端高清、多屏适配方案(zz)
来源: http://sentsin.com/web/1212.html 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉 ...
-
移动端高清、多屏适配方案 [来源:http://div.io/topic/1092]
Lovesueee 发布于 8 月前 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视 ...
-
css图片高清适配
同一张图片,在普通屏显示正常,但高清屏出现模糊.原因是原来一个像素的点分成的四个像素的点进行了显示. 解决方案:在高清屏中把图片变成二倍图,前提是二倍的高清图已经存在. .icon{ backgrou ...
-
基于REM的移动端响应式适配方案
视口 在前一段时间,我曾经写过一篇关于viewport的文章.最近由于在接触移动端开发,对viewport有了新的理解.于是,打算重新写一篇文章,介绍移动端视口的相关概念. 关于这篇文章说到的所有知识 ...
-
如何录制高清GIF格式的图片
如何录制高清GIF格式的图片 工具:傲软GIF 下载地址:https://www.apowersoft.cn/gif 特点:质量高,能够一帧一帧的修改 使用简单.就不说了.自行尝试.这里只是提供一个制 ...
-
基于rem的移动端响应式适配方案(详解) 移动端H5页面的设计稿尺寸大小规范
基于rem的移动端响应式适配方案(详解) : https://www.jb51.net/article/118067.htm 移动端H5页面的设计稿尺寸大小规范 http://www.tuyiyi.c ...
-
移动端高清、多屏适配方案——rem
背景: 开发移动端H5页面 一套设计图 不同尺寸的手机 不同分辨率的手机 方案:使用rem作为单位解决一套设计图适应不同分辨率,不同尺寸的手机. 概念: REM(font size of the ro ...
-
jquery图片延迟加载方案解决图片太多加载缓慢问题
当在做一个图片展示站的时候,一个页面加载的图片过多会,如果服务器的带宽跟不上,明显会感觉到页面很卡,严重的浏览器也会崩溃,所以我推荐采用即看即所得的模式,当滚动到下一屏时才进行加载图片. 注意:即便如 ...
-
移动端Web页面适配方案
概念理解 viewport视口 visual viewport 可见视口,设备屏幕的宽度 windw.innerWidth/Height layout viewport 布局视口,DOM宽度 doc ...
随机推荐
-
JDBC专题
JDBC ·持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应用,数据持久化以为着将内存中的数据保存到硬盘上加以“固化”,而持久化的实现过程大多 ...
-
Is it possible to change the iPhone device name programmatically?
今天刚好方案公司谈到一个需求方案,要制作一个dvr连接手机,手机能上网的功能. 为了简化,让dvr开机轮询,连接某个iphone设备名字特征的手机,希望在app中提供一个输入框,可以 按dvr可以识别 ...
-
SKTextureAtlas类
继承自 NSObject 符合 NSCodingNSObject(NSObject) 框架 /System/Library/Frameworks/SpriteKit.framework 可用性 可用 ...
-
javascript变量:全局?还是局部?这个得注意!
做项目就是一个学习的过程! 做为一个学习C3年多,从C程序员转前端的人来说,javascript中的许多规则是没办法或者说一时半会理解不了的. 今天就遇到了一个,大致就是这么个代码. var a ; ...
-
Oracle定时器调用存储过程
1. 创建表 create table job_table(run_time date); 2. 创建存储过程 create or replace procedure job_proc is begi ...
-
QT学习 之 QwtPlot(数学绘图)
QT对于统计图像.函数图像等的绘制是没有相关组件的帮助的,只有利用手工绘制图片. QwtPlot是用来绘制二维图像的widget,继承自QFrame 和 QwtPlotDict.不过严格的说来,它只是 ...
-
IMapControl3 Interface(1) Properties属性
IMapControl3 Interface Provides access to members that control the MapControl. Note: the IMapControl ...
-
Skyline Te Pro二次开发技能总结
前两天项目开发中,忽然一个Imagelabel的参数不会调了,但是前段时间可是很熟悉的.好吧,好记性不如烂笔头! 1. 模型弹出窗调试 这里的模型弹出框指涉及到模型操作的,比如监听模型选定事件.根据窗 ...
-
Linux下CenOS系统 安装MariaDB
1.首先去MariaDB官网下载安装包,首页是:https://mariadb.org/ 2.放在linux下的新建目录下:/root/mariadb 然后解压缩,命令为:tar -xzvf mari ...
-
XenServer 自动化布署 (关键词: PXE ANSWER SCRIPT)
XenServer 6.x PXE自动化布署: 测试环境:win10 + Tiny pxe server 1.0.2,采用gpxelinux.0 时间:2017.1.10 PXE远程安装: 1)def ...