文章目录
声明
本文着重于资源整合,主要探讨基础视口的viewport和rem的使用,目前市面上最为流行的解决方案。
1. 参考文献(网站资源)
- mdn:CSS的值和单位
- wsschool:CSS 单位
- CSS Validation Service:检查层叠样式表(CSS)文档和HTML或者XHTML文档中的CSS内容
- codepen:在线调试html相关代码
- jsfiddle
- mdn:@viewport
- 在移动浏览器中使用viewport元标签控制布局
- A Tale of Two Viewports:两个视口的故事
- A pixel is not a pixel is not a pixel:像素不是像素不是像素
- Mobile Safari 引入了 “viewport元标签” 来让web开发者控制视口的尺寸及比例
- Debugging CSS:调试css
- 国内10大前端团队网站
- 移动适配解决方案:阿里团队的高清方案
- 移动适配解决方案推荐博客:手机端页面自适应解决方案—rem布局进阶版(附源码示例)
- 微信的WEUI框架
- 淘宝触屏版(webapp版本)
2. 前言
移动端浏览器(如Fennec)在一个通常比屏幕更宽的虚拟”窗口“(视口)中渲染页面,从而无需将所有页面都压缩进小屏幕里(那样会把很多没有针对移动端进行优化的站点打乱)。用户可以通过平移和缩放来浏览页面的不同区域。
Mobile Safari 引入了”viewport元标签“来让web开发者控制视口的尺寸及比例。如今许多其他移动端浏览器已经支持这一标签,虽然它不是任何web标准的一部分。苹果的文档 详尽地说明了web开发人员可以怎样使用这一标签,然而我们还是不得不仔细推敲Fennec究竟应该怎样实现它。例如,Safari的文档指出标签的内容应为”由逗号分隔的列表“,但是现有的浏览器和网页都把逗号、分号及空格混用作分隔符。
可以在A Tale of Two Viewports了解更多在不同移动浏览器中视口的情况。
2.1 css尺寸介绍
单位 | 描述 | 备注 |
---|---|---|
% | 百分比 | 相对单位 |
in | 英寸 | 绝对单位 |
cm | 厘米 | 绝对单位 |
mm | 毫米 | 绝对单位 |
em | 1em 等于当前的字体尺寸。 2em 等于当前字体尺寸的两倍。 例如,如果某元素以 12pt 显示,那么 2em 是24pt。 在 CSS 中,em 是非常有用的单位,因为它可以自动适应用户所使用的字体。 | 相对单位 |
rem | REM(root em)和em以同样的方式工作,但它总是等于默认基础字体大小的尺寸; 继承的字体大小将不起作用,所以这听起来像一个比em更好的选择,虽然在旧版本的IE上不被支持(查看关于跨浏览器支持 Debugging CSS.)。 | 相对单位 |
ex, ch | 分别是小写x的高度和数字0的宽度。这些并不像em那样被普遍使用或很好地被支持。 | 相对单位 |
pt | 磅 (1 pt 等于 1/72 英寸) | 绝对单位 |
pc | 12 点活字 (1 pc 等于 12 点)。 点(Points (1/72 of an inch)), 十二点活字( picas (12 points.))。 | 绝对单位 |
px | 像素 (计算机屏幕上的一个点) | 绝对单位(absolute units) |
vw, vh | 分别是视口宽度的1/100和视口高度的1/100,其次,它不像rem那样被广泛支持。 vw = 1% of viewport width。 1vh = 1% of viewport height。 1vmin = 1vw or 1vh, 最小。 1vmax = 1vw or 1vh, 最大。 | 相对单位 |
3. 视口基础
一个典型的针对移动端优化的站点包含类似下面的内容:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
width属性控制视口的宽度。可以像width=600这样设为确切的像素数,或者设为device-width(物理设备的宽度)这一特殊值来指代比例为100%时屏幕宽度的CSS像素数值。相应有height及device-height属性,可能对包含基于视口高度调整大小及位置的元素的页面有用。
initial-scale属性控制页面最初加载时的缩放等级。maximum-scale、minimum-scale及user-scalable属性控制允许用户以怎样的方式放大或缩小页面。
4. 像素并非像素
iPhone和许多Android手机有3*4英寸(7*10厘米)大的分辨率为320*480像素的屏幕(~160 dpi)。Firefox for Maemo同样运行在Nokia N900上,它的屏幕具有同样的物理尺寸有着480*800像素的分辨率(~240 dpi)。因此,过去版本的Fennec会把很多页面显示得比在iPhone或Android上小大约三分之一(物理尺寸)。这导致很多针对触屏优化的网站产生了可用性和可读性的问题。Peter-Paul Koch在A pixel is not a pixel is not a pixel中提到了这一问题。
针对Fennec for maemo 1.1将采取基于WebKit的Android浏览器所使用的方式,以1.5个硬件像素显示每一个CSS”像素“。这意味着一个initial-scale=1的页面在Fennec for Maemo、Mobile Safari for iPhone以及Android浏览器中,无论在HDPI或是MDPI手机上,都能显示为相近的物理尺寸。这与CSS 2.1标准一致:
如果显示设备的像素密度与典型的电脑显示器差异明显,用户代理应当重新调整像素值。建议像素单位指向设备所包含的所有最接近参考像素标准的像素。建议以阅读者在一臂距离处观察到的像素密度为96 dpi的设备上的一个像素作为参考像素。
对web开发者来说,这意味着在所有之前提到的手持设备上,比例=1时竖屏模式的最大宽度都是320像素,并且会相应地调整布局及图片的大小。不过要记得不是所有移动设备的宽度都相同,应该确保页面在横屏模式以及iPad与Android平板等更大的设备上工作良好。
在240 dpi及以上的屏幕上,initial-scale=1的页面实际上会被Fennec及Android WebKit浏览器放大至150%。其中的文字会保持平滑锐利,但位图图像在全屏模式下就难免不尽人意了。为了使图片在这些屏幕上变得清晰,web开发者或许会把图片甚至整个布局设计成最终尺寸的150%(或者200%从而支持像配备retina屏的iPhone那样的像素密度高达320 dpi及以上的设备),然后通过CSS或视口属性缩小。
默认比例依赖于显示密度。在密度低于200 dpi的显示设备上,比例为1.0。在密度介于200及300 dpi之间的显示设备上,比例为1.5。对于具有300 dpi以上密度的显示设备,比例为密度/150 dpi向下取整的结果。注意再有在视口比例为1时才会应用默认比例。否则,CSS像素与设备像素之间的关系依赖于当前的缩放等级。
5. rem的几种解决方案
rem相对于根元素的字体大小的单位。通过css的媒体查询或者通过js根据文档视口宽度动态计算得到的html根元素的字体大小的值。然后在布局使用过程中。将其宽高或者字体大小设置为 div{width:1rem; height:1rem; font-size:1rem;}
实现自适应。另外值得说的是即使采用了rem布局方案,页面上不一定所有的元素都是采用rem作为单位。比如微信的WEUI框架。
5.1 方案1,针对各个分辨率范围在html上设置font-size
早期的解决方案,webapp要适应各种分辨率的移动设备,针对各个分辨率范围在html上设置font-size的代码:
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;}}
该方案的缺点会比较明显,不同尺寸梯度变换的时候,显示的尺度落差比较大,过度不平滑,而且显示比例不可控制,用户体验较差。
5.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>
通过上述例子可得到,两个span元素的显示大小都是 宽41.38、高21,如图所示:
5.3 方案3,阿里团队的方案,推荐方案
该网站(http://www.aliued.com)已经打不开,该文暂时,看不了了,非常抱歉
5.4 方案4,淘宝触屏版的方案
淘宝触屏版(webapp版本),此方案是默认 1rem = 100px,所以布局的时候是可以按照设计师给的效果图设置显示大小。例如,在效果图上量取的某个按钮元素宽、高是60px、38px,那样式就可以这样设置 .btn{width: 0.6rem;height: 0.38rem;}
。
- js代码
!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)
5.5 方案5,我的解决方案
-
为何要视口宽度除以
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动态计算后控制显示样式。
所以目前只能采用这种简单粗暴的解决方案。 -
js代码
!(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);
总结
目前市面上有很多种“rem解决方案”,比较推荐是“阿里高清版本”的。最主要还是要根据选择的技术架构进行选择使用哪种适配解决方案;其实,大同小异,都是改变viewport的参数和html字体大小,只是值不一样而已。