再谈移动端适配和点5像素的由来

Posted zhiqiang21

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了再谈移动端适配和点5像素的由来相关的知识,希望对你有一定的参考价值。

前言

这篇文章的内容如题目一样,主要分为两个部分,

  1. 谈谈业内主流的移动端适配解决方案

  2. 点5像素的由来和实现方法

建议在读这篇文章的时候先读下这篇文章《高清屏概念解析与检测设备像素比的方法_20161005》,因为这些文章涉及的很多概念在这篇文章中都会提到。

1.再谈移动端适配

1.1百分比解决方案的缺点

在我们的项目中大量的使用百分比来解决页面在宽度上的自适应,其实在高度上并没有很好的自适应。所以在我们的前端页面会出现一些比较奇怪的问题。比如下面这样:

还有一个比较明显的问题就是:在任何机型上我们的按钮的高度是不会变化自适应的,所以小屏手机我们的按钮看起来很臃肿。

1.2一些常用单位的概念解析

在谈我为什么在我们的项目中引入rem单位的时候,先来详细的了解几个常用的单位概念。

  1. px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的(也就是说是跟物理设备有关的)。拿高清屏和普通屏来做对比就是普通屏幕的1个像素点就是1个物理像素点,而高清屏的1个像素点4个物理像素点

  2. em相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。em单位的特点:1. em的值并不是固定的;2. em会继承父级元素的字体大小。

  3. rem相对长度单位。rem是CSS3新增的一个相对单位,这个单位引起了广泛关注。这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是html根元素。这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。

任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1rem=16px。那么12px=0.75rem,10px=0.625rem。为了简化font-size的换算,需要在css中的html选择器中声明font-size=62.5%,这就使rem值变为 16px*62.5%=10px, 这样12px=1.2rem, 10px=1rem, 也就是说只需要将原来的px数值除以10,然后换上rem作为单位就行了。

注意:当我们在根节点<html>上设置了font-size基准值以后,在文档中有使用rem单位的属性值都是相对于根节点font-size的一个相对值。比如说一些元素的属性如width height margin等。也正是这个原因,现在很多网站的移动端网站都在使用rem单位作为适配工具。

在使用rem的时候比较麻烦的就是pxrem换算的问题。上面的除10的方案是比较简单的。但是根据设置基准值的不同换算方法也不一样。如果我们使用scss来写我们的样式表的话,解决方法就比较简单了,代码如下:

@function px2rem($px)
    @return ($px/10)/2 + rem;  //  相当于$px/20  +rem


width:px2rem(100px);   //5rem
height:px2rem(200px);  //10rem

1.3为什么引入 rem 单位

由上面的内容已经知道百分比单位在多屏幕适配上的缺点和rem单位的优点。那么rem单位能为我们的开发带来什么呢?来看一个常见的多列布局,淘宝移动端的商品列表页,如下图:

设计稿(不管是iphone6的二倍稿还是iphone5的二倍稿)中给展示商品的坑位的宽高比是固定的。为了能够使这个列表在不同的屏幕上达到最佳的显示效果,需要保持宽度和高度比一致。如果使用百分比肯定是满足不了这个需求的,因为高度上我们没有办法控制。

iphone6和iphone5的屏幕宽度和高度比不一样,当我们使用百分比做多列布局的时候就会出现下面的这种情况:

所以为了满足商品坑位在不同屏幕上的宽高比一致,淘宝使用的是rem的解决方案,也是目前最好的解决方案。

1.3为什么将计算根元素的font-size值的js放在head标签中

设置根节点font-size值的方法,第一种是使用css的Media queries,示例代码如下:

@media (min-device-width : 375px) and (max-device-width : 667px) and (-webkit-min-device-pixel-ratio : 2)
      htmlfont-size: 37.5px;

上面的这种方式在我之前做过的项目中使用了一段时间。上面的设置方法有一个很明显的问题font-size是在一个屏幕宽度的区间上有一个基准值。像安卓手机种类的繁多,屏幕大小就更多的情况下,上面的方法很鸡肋。

第二种解决方案,就是使用javascript根据当前屏幕的宽度动态计算font-size值,这种方法可以保证屏幕宽度连续变化的时候,font-size基准值也是连续变化的

计算方法可以参考这篇文章《根据iPhone6设计稿动态计算rem值》

那么最后一个问题也来了:为什么将计算rem单位的js放在head标签里面?

一句话总结:在浏览器中文档流是从上往下加载渲染的。为了保证发生不必要的重绘或者是重排肯定是越早给根节点设置font-size值越好。

1.4什么情况下使用rem来布局和注意的问题

  1. 整体的布局还是使用百分比

  2. 使用rem的最佳场景是,遇到例如多列带有图片的列表,常常需要图片固定宽高比例

  3. 研究了一些网站,比如淘宝,对字体字体一般情况建议使用px

  4. 出现1px像素线的地方,仍旧使用border-width:1px;而不是border-width:.1rem;

2.点5像素的由来

在前言中推荐阅读的那篇文章中已经知道在 高清屏(Retina) 中控制显示的最小的物理单元包括4个基本的像素点,而普通屏幕1个点像素就是1个物理像素单元。所以在高清屏(Retina)出来之前,就算我们在css中写 0.5px,对于显示屏幕也是不识别的。但是在高清屏(Retina)中我们可以通过间接的方法实现0.5px的效果。

下面的这张图可能能让我们迅速回忆上篇文章的内容

来看一段简单的示例代码加深理解:

<div class="item1"></div>
<div class="item2"></div>

css代码如下:

.item1
    width:100px;
    height:50px;
    border-top:1px solid #000;
    float: left;
    margin-top:10px;


.item2
    width:100px;
    height:50px;
    margin-top:10px;
    border-top:.5px solid #de1dfb;
    float: left;

chrome中的显示效果如下图:

我把这张图截取下来放到 PS 中放大可以很明显的看到一些问题。就是高清屏实际上是用了两排的物理像素点来显示1px的像素线。且不做特殊处理的话1px0.5px的在Chrome浏览器中显示效果是相同的。也就是说Chrome浏览器不识别0.5px

但是相同的代码我在 safari浏览器中的效果却是下面的效果:

下面的效果是我在PS中做了放大后的效果。

所以,我们可以得出一个结论:对于0.5px不同浏览器对它的识别是存在差异的。

以下这张图是一位网友对一些常用设备是否识别0.5px做的统计:

其实从视觉的感受上来说0.5px像素的显示效果确实是比1px的显示效果要好很多。大多数情况下也更符合设计稿上的1px线的效果。那么我们有没有办法可以让1px在不同的浏览器和设备中显示真正的1像素的效果呢?

答案是肯定定的。

2.1传统的实现方法,也就是我们的项目中正在使用的方法:

伪元素 + css3的缩放巧妙地实现;

基本步骤就是:

  1. 设置目标元素定位参照

  2. 给目标元素添加一个伪元素before或者after,并设置绝对定位

  3. 给伪元素添上1px的边框

  4. 设置伪元素的宽高为目标元素的2倍

  5. 缩小0.5倍(变回目标元素的大小)

  6. 使用border-box把border包进来

先来看一个1像素0.5像素的显示效果,下面的截图是在chrome中:

实现的代码如下:

<div class="item4">测试用的边框</div>
<div class="item5">测试用的边框</div>
.item4, .item5 
    width: 200px;
    height: 100px;
    position: relative;


.item4 
    border: 1px solid #000;


.item5::before 
    content: '';
    position: absolute;
    width: 200%;
    height: 200%;
    border: 1px solid #000;
    transform-origin: 0 0;
    transform: scale(0.5, 0.5);
    box-sizing: border-box;

可以很明显的看到缩放前和缩放后的效果。在ps中把上面的截图放大很多倍以后我们可以看到显示细节。缩放以后确实是使用的最小的物理像素单元来显示边框。如下图:

注意:按照css3 transform 的scale的定义,理论上边框可以任意细(1/n px)。但是上图中已经是物理设备能够使用的最小的物理单元了,那么我们继续缩放会有什么现象呢?

使用一下代码

探讨移动端布局适配方案

移动端适配方案

[移动端]移动端设备属性

移动端,多屏幕尺寸高清屏retina屏适配的解决方案

移动端适配必须掌握的基本概念和适配方案

移动端适配