目录

文章目录

    • 目录
    • 1.css尺寸介绍
    • 2.视口基础
    • 3.像素并非像素
    • 4.rem的几种解决方案
        • 4.1 方案1,针对各个分辨率范围在html上设置font-size
        • 4.2 方案2,通过视口的宽度的比值动态算出html根元素的字体大小
        • 4.3 方案3,阿里团队的方案,推荐方案
        • 4.4 方案4,淘宝触屏版的方案
        • 4.5 方案5,另一种

1.css尺寸介绍

单位 描述 备注
% 百分比 相对
in 英寸 绝对
cm 厘米 绝对
mm 毫米 绝对
ex, ch 分别是 小写x的高度 和 数字0的宽度。 相对
pt 磅 (1 pt 等于 1/72 英寸) 绝对
pc 12 点活字 (1 pc 等于 12 点)。Points (1/72 of an inch), picas (12 points.)。 绝对
px 像素 (计算机屏幕上的一个点) 绝对
em 1em 等于当前的字体尺寸。如,如果某元素以 12pt 显示,那么 2em 是24pt。 相对
rem 和em以同样的方式工作,但它总是等于默认基础字体(html的font-size)大小的尺寸; 相对
vw 视口宽度的1/100。1vw = 1% of viewport width。 相对
vh 视口高度的1/100,1vh = 1% of viewport height。 相对
vmin&vmax 1vmin = 1vw or 1vh, 最小。1vmax = 1vw or 1vh, 最大。 相对

2.视口基础

一个典型的针对移动端优化的站点包含类似下面的内容:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

该meta标签的作用是让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放。也许允不允许用户缩放不同的网站有不同的要求,但让viewport的宽度等于设备的宽度,这个应该是大家都想要的效果,如果你不这样的设定的话,那就会使用那个比屏幕宽的默认viewport,也就是说会出现横向滚动条。

属性 描述
width 设置layout viewport 的宽度,为一个正整数,或字符串"width-device"
initial-scale 设置页面的初始缩放值,为一个数字,可以带小数
minimum-scale 允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale 允许用户的最大缩放值,为一个数字,可以带小数
height 设置layout viewport 的高度,这个属性对我们并不重要,很少使用
user-scalable 是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许

第一、如果不设置meta viewport标签,那么移动设备上浏览器默认的宽度值为800px,980px,1024px等这些,总之是大于屏幕宽度的。这里的宽度所用的单位px都是指css中的px,它跟代表实际屏幕物理像素的px不是一回事。

第二、每个移动设备浏览器中都有一个理想的宽度,这个理想的宽度是指css中的宽度,跟设备的物理宽度没有关系,在css中,这个宽度就相当于100%的所代表的那个宽度。我们可以用meta标签把viewport的宽度设为那个理想的宽度,如果不知道这个设备的理想宽度是多少,那么用device-width这个特殊值就行了,同时initial-scale=1也有把viewport的宽度设为理想宽度的作用。所以,我们可以使用

<meta name="viewport" content="width=device-width, initial-scale=1">

来得到一个理想的viewport

3.像素并非像素

ss中的1px并不等于设备的1px
在css中我们一般使用px作为单位,在桌面浏览器中css的1个像素往往都是对应着电脑屏幕的1个物理像素,这可能会造成我们的一个错觉,那就是css中的像素就是设备的物理像素。但实际情况却并非如此,css中的像素只是一个抽象的单位,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素是不同的。在为桌面浏览器设计的网页中,我们无需对这个津津计较,但在移动设备上,必须弄明白这点。在早先的移动设备中,屏幕像素密度都比较低,如iphone3,它的分辨率为320×480,在iphone3上,一个css像素确实是等于一个屏幕物理像素的。后来随着技术的发展,移动设备的屏幕像素密度越来越高,从iphone4开始,苹果公司便推出了所谓的Retina屏,分辨率提高了一倍,变成640×960,但屏幕尺寸却没变化,这就意味着同样大小的屏幕上,像素却多了一倍,这时,一个css像素是等于两个物理像素的。其他品牌的移动设备也是这个道理。例如安卓设备根据屏幕像素密度可分为ldpi、mdpi、hdpi、xhdpi等不同的等级,分辨率也是五花八门,安卓设备上的一个css像素相当于多少个屏幕物理像素,也因设备的不同而不同,没有一个定论。

还有一个因素也会引起css中px的变化,那就是用户缩放。例如,当用户把页面放大一倍,那么css中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,css中1px所代表的物理像素也会减少一倍。关于这点,在文章后面的部分还会讲到。

在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。css中的px就可以看做是设备的独立像素,所以通过devicePixelRatio,我们可以知道该设备上一个css像素代表多少个物理像素。例如,在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。但是要注意的是,devicePixelRatio在不同的浏览器中还存在些许的兼容性问题,所以我们现在还并不能完全信赖这个东西,具体的情况可以看下这篇文章。

4.rem的几种解决方案

4.1 方案1,针对各个分辨率范围在html上设置font-size

rem相对于根元素的字体大小的单位。通过css的媒体查询或者通过js根据文档视口宽度动态计算得到的html根元素的字体大小的值。另外值得说的是即使采用了rem布局方案,页面上不一定所有的元素都是采用rem作为单位。比如微信的WEUI框架。

html {font-size: 20px;}
@media only screen and (min-width: 400px) {html {font-size: 21.33px !important;}}
@media only screen and (min-width: 414px) {html {font-size: 22.08px !important;}}
@media only screen and (min-width: 480px) {html {font-size: 25.6px !important;}}

该方案的缺点会比较明显,不同尺寸梯度变换的时候,显示的尺度落差比较大,过度不平滑,而且显示比例不可控制,用户体验较差。

4.2 方案2,通过视口的宽度的比值动态算出html根元素的字体大小

设置文档的html {font-size: 4.26667vw !important;}值,为何是4.26667乘以vw?
看如下的例子,我们设定当前视口的宽度为iPhone6的375宽度,并设定body的字体大小为<body style="font-size:16px;">16px;然后在设置示例“字体1”和“字体2”的字体大小,分别为“继承”和“1rem”,然后通过浏览器调试获取元素大小;“字体1和字体2的大小一样”,默认情况下html的1rem = 16px,也就是说“4.26667”可以作为一个基准的比例。

<html lang="zh-Hans"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no,target-densitydpi=device-dpi,viewport-fit=cover">
<style>html {font-size: 4.26667vw !important;}</style>
</head>
<body style="font-size:16px;"><span>你大爷</span><span style="font-size: 1rem;">你大爷</span>
</body></html>

移动H5 浏览器适配解决方案-编程知识网
移动H5 浏览器适配解决方案-编程知识网

4.3 方案3,阿里团队的方案,推荐方案

找不到

4.4 方案4,淘宝触屏版的方案

淘宝触屏版(webapp版本),此方案是默认 1rem = 100px,所以布局的时候是可以按照设计师给的效果图设置显示大小。例如,在效果图上量取的某个按钮元素宽、高是60px、38px,那样式就可以这样设置 .btn{width: 0.6rem;height: 0.38rem;}

!function (e, t) {var n = t.documentElement,d = e.devicePixelRatio || 1;function i() {var e = n.clientWidth / 3.75;n.style.fontSize = e + "px"}if (function e() {t.body ? t.body.style.fontSize = "16px" : t.addEventListener("DOMContentLoaded", e)}(),i(),e.addEventListener("resize", i), e.addEventListener("pageshow",function (e) {e.persisted && i()}),2 <= d) {var o = t.createElement("body"),a = t.createElement("div");a.style.border = ".5px solid transparent",o.appendChild(a),n.appendChild(o),1 === a.offsetHeight && n.classList.add("hairlines"),n.removeChild(o)}}(window, document)

4.5 方案5,另一种

!(function (win, doc) {var root = doc.documentElement;function init() {var w = root.clientWidth || win.innerWidth;w = w < 320 ? 320 : w;root.style.fontSize = w >= 640 ? '100px' : (w / 3.75 + 'px');doc.body.style.fontSize = '16px';}win.addEventListener('orientationchange' in window ? 'orientationchange' : 'resize', init, false);doc.addEventListener('DOMContentLoaded', init, false);
})(window, document);
  • 为何要视口宽度除以3.75
    该方案也采用,默认 1rem = 100px,在iPhone6下视口宽度刚好是375,将其作为一个基准。所以布局的时候是可以按照设计师给的效果图设置显示大小。例如,在效果图上量取的某个按钮元素宽、高是60px、38px,那样式就可以这样设置 .btn{width: 0.6rem;height: 0.38rem;}

  • 示例中为何采用宽度最小320或者最大640呢?
    第一,宽度最大640,一般设计的效果图的宽度默认为640px或者750,这是一个安全宽度,这个是出于显示美观考虑,提升用户体验。
    第二,宽度最小320纯属于避免别人说你代码有bug,有些人比较喜欢转牛角尖。

  • 为何要使用这种方案?
    第一,我们目前的项目目前还停留在通过css文件的样式内容控制布局
    第二,我们没有使用模板引擎像“淘宝触屏版(webapp版本)”那样,通过js动态计算后控制显示样式。
    所以目前只能采用这种简单粗暴的解决方案。