【移动适配】一个像素的border怎么实现
一个像素里复杂纷扰的世界
文 | 啃先生 Mar.3rd.2016 首发于微信公众号(啃先生)
上一篇发了《【移动适配】移动Web怎么做屏幕适配》
壹 | Fisrt
在CSS的世界里Px是原子操作,我们无法定义边框的宽度是0.5px,最小都是1px。所以有以下结论:

然而,对于精益求精的产品而言,这种认识只是片面的!例如:我做了一个页面,上面只有两条边框,在高清屏(如iPhone5s)上,经过特殊处理的边框比1像素的边框还要细。
因此,在高清屏上,border-width:1px;并不是最小边框。浏览器可以显示的最小粒度比CSS中的1px还要小。

貳 | Second
那么CSS中的1px是什么?浏览器是怎么渲染它的?
网页在一个叫viewport的东西里渲染,可以理解为画布,画布被分成 N x M 个小方格,1个CSS像素,就是其中的一个小方格。
viewport又是什么?
网页在viewport上渲染,可以想像在PS上画东西时,上面也有个画布,这个画布分割了 N x M 个方格,N是它的宽度,M是它的高度。宽高都可以任意设置,所以说viewport是虚拟的。假设设置宽度是400,那么浏览器显示区域的横向将被分为400份,CSS的1px占的宽度就是显示区域的 1/400。如果是980,那就是1/980。
viewport值不一样时,对页面元素宽度的影响
看一个的页面,不动任何其他代码,只修改viewport的宽度,页面发生了什么变化
代码如下:

以下是支行結果

viewport=500的情況

viewport=900的情況
我们只分析用户头像的图片,已知头像宽度是50px。
当viewport宽度为500时,屏幕横向被分为500份,每份1px,所以头像宽度是屏幕的1/10。(500/50=10)
当viewport宽度为900时,屏幕横向被分为900份,每份1px,所以头像宽度是屏幕的1/8。 (900/50=18)
所以,在CSS中,1px是指viewport中的一个小方格,而viewport宽度是可以任意设置的。
叁 | Third
那么,怎么合理设置viewport的宽度?
viewport的宽度可以是数字和字符串"device-width"。device-width指设备宽度。
当取值为数字时,指不论是什么手机屏幕,viewport都被分为那么多份
当取值为device-width时,指的是手机屏幕的viewport宽度被设置为跟手机宽度一样。那这个宽度怎么算的呢?
device-width的算法
先理清几个非常关键的术语概念:
物理像素:买手机的时候会有一个 n*m 的分辨率,那是屏幕的n*m个呈像的点,一个点(小方格)为一个物理像素。它是屏幕能显示的最小粒度
CSS像素:就是CSS里的Px,上面已经讲了是viewport中的一个小方格。
像素密度:即dpi或ppi,屏幕每英寸所占的物理像素点。
而CSS像素与物理像素之间是有一个转换关系的。即是:

其中,转换系统计算过程如下:


安卓的密度区域和转化系数的对应表

iPhone的密度区域和转化系数的对应表
(声明:以上三个图片来源于 http://tgideas.qq.com/webplat/info/news_version3/804/7104/7106/m5723/201509/376281.shtml)
例如:某台安卓手机,分辨率是 1920*1080,屏幕对象线是5英寸。那么在这台手机上1个CSS像素,占了多少个物理像素?
第一步:勾股定理算出对角线的分辨率,即 √(1920²+1080²)≈2203px
第二步:算出dpi。对角线的分辨率/对角线英寸 = 2203/5≈440dpi
第三步:得出转换系数。根据上面的图片,安卓手机440dpi,属于XXHDPI,转换系数是3
因此这台手机中,1个CSS像素 = 3*物理像素。即1个CSS像素占了3个物理像素。
这个转换系数,也等同于dpr,设备像素比。
因为很明显device-width的宽度值单位是CSS像素。所以当viewport设置为device-width时,此时它是手机横向分辨率 / 转换系数。即:

例如上述的例子中,该台安卓手机的device-width是1080/3 = 360,即viewport的宽度是 360 CSS像素。
而viewport设置为固定的数字有可能会破坏这种转换关系,都是建议设置viewport宽度为device-width,这样1个CSS像素就尽最大可能刚好占dpr个物理像素点。
肆 | Fourth
为什么会出现比border-width:1px更细的边框?
屏幕能够显示的最小粒度是1个物理像素,而当viewport宽度设置为device-width时,1个CSS像素占用的物理像素是由转换系数决定的。所以,像iPhone6这样的高清屏上,转换系数为3,border-width:1px,这个边框占了3个物理像素。如果能让某个border的宽度为1个物理像素,那么它就比1个CSS像素要细,而本文最开始边框那个更细是因为经过特殊处理后使其只占用1个物理像素。
让1个CSS像素占用一个物理像素的办法。
方法一:viewport的scale
在viewport的属性里,除了设置宽高的width和height外,还有缩放比例scale。
当scale为1时,页面大小正常,但scale为0.5时,页面被缩小了1倍,本来1个CSS像素宽度占2个物理像素宽度,缩小后的border-width:1px就只占1个物理像素。代码如下:

其中,initial-scale为1/dpr。
优点:
不用为border写很多样式代码,跟原来一样border:1px solid #D5D5D6即可
可以轻松设置圆角 border-radius。
缺点:
1. 整个页面缩小了,副作用就是字体,图片,其他元素的尺寸边距等等都同比例缩小了。这种情况,设置viewport为dpr*document.documentElment.clientWidth,再结合我上一篇文章《【移动适配】移动Web怎么做屏幕适配(一)》,即可解决。
方法二:transform scale
方法一是缩放整个页面,在CSS3标准里,可以缩放某个元素。例如某个div.border-top,为它设置如下样式,使该DIV的顶部有一个边框
.border-top{position: relative;border-top: none !important;}
.border-top:after {
content: " ";
position: absolute;
left:;
top:;
width: 100%;
height: 1px;
background-color: #D5D5D6;
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
-ms-transform: scaleY(0.5);
transform: scaleY(0.5);
}
在该DIV后面添加一个高度为1px的内容,并且缩小dpr倍,这里就是缩小成原来的1/2。
优点是整个页面不用缩放,缺点是border代码较多,无法实现border-radius圆角
写完濒临虚脱。。

- 深入理解viewport和px(http://tgideas.qq.com/webplat/info/news_version3/804/7104/7106/m5723/201509/376281.shtml)
- A tale of two viewports(http://www.quirksmode.org/mobile/viewports.html)

适配的问题还没讲完,但又臭又长的纯技术文太硬了,下期可能会喝点汤,讲讲故事。
开始码字才知道码字不易,坚持码字更不易。转载请声明来源

如果觉得文章有用,顺手点击下方的推荐
【移动适配】一个像素的border怎么实现的更多相关文章
- HTML5 Canvas中实现绘制一个像素宽的细线
正统的HTML5 Canvas中如下代码 ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(10, 100); ctx.lineTo(300,100); c ...
- Solid Angle of A Cubemap Texel - 计算Cubemap的一个像素对应的立体角的大小
参考[http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/] 计算diffuse irradiance map或者求解sh ...
- QML 移动端适配一个参考思路
参考: Qt Quick 准确的移动平台屏幕适配 qt qml 高宽自动适配android设备 QML 从无到有 (移动适配) 思路:以一个平台分辨率为基准(如320*480),考虑其与其它平台的比例 ...
- DIV+CSS常见问题:DIV如何设置一个像素高度?
CSS如何控制DIV实现1像素高度呢?问题看起来很简单,但万恶的IE6会让你很麻烦,不过解决办法很多,本文将介绍最简单的一种:DIV{height:1px;line-height:1px;font-s ...
- 临摹一个像素风格高楼shader
原始效果地址:http://glslsandbox.com/e#40050.0 是一个的城市高楼感的shader,比较像素风 可以拿来做游戏背景,或者基于这个思路做一些别的效果 这个是我后来找的版本, ...
- Canvas 绘制一个像素风电子时钟
想法是在 Canvas 上绘制由小方块组成的数字. 第一步是实现绘制小方块的方法,先画出一个边长为 5 的 10x10 个方块,使用两个 for 循环很简单就能完成. for (let i = 0; ...
- opencv 中对一个像素的rgb值或像素值进行操作的几个常用小办法【转】
You can access the Image pixels in many ways:1. One using the Inbuilt macro2. One using the pointer ...
- C# 绘图时使用抗锯齿会多出一个像素
如下图,使用局部绘图覆盖后的效果. 减去像素后效果
- 利用poi包装一个简单的Excel读取器.一(适配一个Reader并提供readLine方法)
通常,读文本我们会使用BufferedReader,它装饰或者说管理了InputStreamReader,同时提供readLine()简化了我们对文本行的读取.就像从流水线上获取产品一样,每当取完一件 ...
随机推荐
- java简单词法分析器(源码下载)
java简单词法分析器 : http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%8D%E6%B3%95%E5%88%8 ...
- c++中关于初始化型参列表的一些问题
/* 1.成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的! 一个好的习惯是,按照成员定义的顺序进行初始化. 2.数组成员在初始化型参列表中不正确 */ #in ...
- 哈夫曼树(三)之 Java详解
前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:htt ...
- WebStorm 9 自动编译 SCSS 产出 CSS 和 source maps
1. 上一节我们学习了Windows下搭建Ruby开发环境,也为这一节的学习做了铺垫.因为本节需要在Ruby环境下安装SASS.详细请见:http://www.cnblogs.com/wind128 ...
- Docker - Docker国内镜像的配置及使用
Docker国内镜像 DaoCloud - Docker加速器 阿里云 - 开发者平台 微镜像 - 希云cSphere 镜像广场 - 时速云 灵雀云 网易蜂巢 阿里云的Docker加速器 阿里云 - ...
- Windows Azure Web Site (9) Web Site公网IP地址
<Windows Azure Platform 系列文章目录> 本文会同时介绍国内由世纪互联运维的Azure China和海外Azure Global. 熟悉Windows Azure平台 ...
- path入门 20141102-1405
那Python有哪些缺点呢? 第一个缺点就是运行速度慢,和C程序相比非常慢, 第二个缺点就是代码不能加密. Python是解释型的 不是编译型的 Python解释器-CPython 命令行: 只需要在 ...
- Elasticsearch 连接查询
在一般的关系型数据库中,都支持连接操作. 在ES这种分布式方案中进行连接操作,代价是十分昂贵的. 不过ES也提供了相类似的操作,支持水平任意扩展,实现连接的效果. 其他内容,参考Elasticsear ...
- 基于HTML5 Canvas实现工控2D叶轮旋转
之前在拓扑上的应用都是些静态的图元,今天我们将在拓扑上设计一个会动的图元——叶轮旋转. http://www.hightopo.com/guide/guide/core/serialization/e ...
- 完美且精准的 IE10- 版本检测。
通过动态的写入条件注释的方式,来判断当前的ie浏览器的版本,优点是,对比userAgent字符匹配,要精准很多,应该说是100%正确,缺点就是要通过JS写入条件注释,拖慢页面的加载速度. 如果对于只判 ...