chapter 1 移动页面开发
- 页面布局
- 页面调试
- 常用库和框架
1.1 页面布局
1.1.1 Vieport(视口,视图窗口)
- 设备像素
- 物理像素:屏幕分辨率;
- 设备独立像素:CSS像素(eg:IPhone5 CSS像素是320*568px)。
- 像素密度(PPI)
- PPI = ( 屏幕分辨率宽的平方+屏幕分辨率高的平方 )开根号 / 4 (eg:IPhone5的PPI大于等于326)
- 根据Apple提出的定义,电脑显示屏PPI高于200,手持平板显示屏PPI高于260及移动电话显示屏高于300的屏幕都称为Retina屏幕。(但是可以通过另一数值来判断是否是Retina显示屏—-设备像素比DPR)
- 设备像素比(DPR)
- DPR= 物理像素 / CSS像素
- 对于常规显示屏来说,物理像素和CSS像素比是1:1,但是在Retina屏幕设备中,一个CSS像素可能等于多个物理像素。
- 可以通过window的devicePixelRatio属性来获取当前设备的DPR:
<script>
var dpr = window.devicePixelRatio;
console.log('dpr-----' + dpr);
</script>
-
- eg:IPhone6 设备物理像素:750px * 1334px,CSS像素:375px * 667px,DPR=2。(IPhone从4代开始基本就是2,IPhone Plus例外(DPR:3),而安卓设备,碎片化很严重,没有一个定值。)
3个Viewport
- 1 . Layout Viewport
- 默认的viewport,通过js的document.documentElement.clientWidth(Height)获取。
- 2 . Visual Viewport
- 在浏览器或者App的Webview中的可视区域,通过js的window.innerWidth(Height)获取。
- 3 . Ideal Viewport
- IPhone4/4s/5/5s 320px(竖屏下宽度,下同)
- IPhone6s 375px
- IPhone6 Plus/6s Plus 414px
- Android(大部分) 320px
visual viewport 就是当前显示给用户内容的窗口,你可以拖动或者放大缩小网页,来看清楚网页的内容。
layout viewport 有网页的所有内容,他可以全部或者部分展示给用户。- 1 . Layout Viewport
设置Viewport
- 在head标签中输入一下代码 (快捷键:meta:vp+tab键):
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
-
- Viewport可以用js进行动态的修改,以运用于一些特殊的项目中。
- 淘宝就是通过js的document.write方式设置viewport的
- Viewport可以用js进行动态的修改,以运用于一些特殊的项目中。
// 使用 document.write <script> document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">') </script> // 使用 setAttribute <meta id="viewport" name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"> <script> var vp = document.getElementById('viewport'); vp.setAttribute('content', 'width=300') </script>
- 图片模糊问题
- 原因:在Retina显示屏等屏幕下,一个位图像素就对应了多个物理像素,这就导致位图像素的色彩值不够分,多出来的物理像素就近取色,导致图片模糊。( 当1个位图像素等于1个物理像素是,图片就是清晰的。当在高清屏幕中会用两个或多个物理像素来显示实际1px图片的内容。相当于把1px的图片放大显示了。)
- 解决(应该让图片大一点,然后在代码里缩小图片!):
- 将原本的尺寸放大一定的倍数,这个倍数便是参考DPR值。(大多数设备的DPR都是2,因此,我们将视觉稿放大两倍去设计即可。
- 压缩图标尺寸
(1)直接设置宽高压缩。(eg:图片实际大小是240px * 480px,那就在< img >标签中设置 width=120px; height=240px; 这样在移动端就清晰了。)
(2)通过设置background-size的方式来压缩(一般缩小一倍)。
1.1.2 布局形式
- 传统页面布局(考虑Retina屏幕的内容清晰度,页面两边背景图留白问题)
- 滑屏页面布局(每一页都是全屏,百分比布局,设置html,body{height:100%;}使div的高度100%)
具体实现思路:
- 三层div。
- 第一层高度100%,设置overflow:hideen;。第二层设置高度1000%,等于10个屏幕的高度。第三层存放10个div,每一个div是一屏,高度为10%。
- 使用 js 监听 touchstart,touchmove,touchend事件。
- 三层div。
1.1.3 媒体查询
- 使用媒体查询
- 方式1:用link在 < head>外链样式表。
< link rel=”stylesheet” media=”screen and (max-width:320px)” href=”ip5.css”> - 方式2:直接写入< head>的style里面。
@media screen and (max-width:320px) { background:#fff; }
- 方式1:用link在 < head>外链样式表。
- 媒体查询中的断点设置
*根据内容宽度设置( 根据设备宽度设置与内容宽度设置类似,不同之处在于 max-width设置断点为320px,360px,375px,414px,768px)
//css媒体查询:(根字体大小100px,如果10px大小,写成0.1rem) html { font-size : 100px; } @media only screen and (min-width: 320px) and (max-width: 479px){ html { font-size: 42.67px !important; } } @media only screen and (min-width: 480px) and (max-width: 639px){ html { font-size: 64px !important; } } @media only screen and (min-width: 640px) and (max-width: 749px){ html { font-size: 85.34px !important; } } @media only screen and (min-width: 750px) and (max-width: 959px){ html { font-size: 100px !important; } } @media only screen and (min-width: 960px) and (max-width: 1241px){ html { font-size: 128px !important; } } @media only screen and (min-width: 1242px){ html { font-size: 165.6px !important; } } //js控制(zepto / jQuery)(根字体大小100px,如果10px大小,写成0.1rem) function setFont() { let window_width = window.innerWidth; let font_size = parseFloat(window_width / 3.75); $(‘html’).css(‘font-size’, font_size); } $(window).on(‘resize’, function () { setFont(); });
-
- 根据设备方向设置
@media screen and (orientation:portrait){ /*设置竖屏时的样式*/} @media screen and (orientation:landscape){ /*设置横屏时的样式*/}
-
- 根据设备像素比设置
@media screen and (device-pixel-ratio:2){ /*设置设备像素比为2时的样式*/}
1.1.4 屏幕适应
百分比布局
- 百分比布局非常适合移动端,能够很好地解决设备尺寸碎片化的情况,兼容性也非常好,而且元素的占比计算不会太复杂。
- eg:设计宽度为640px,图片宽高为191px * 67px;(bg设置,而不是img标签)
- 图片在页面的百分比宽度width:191px / 640px =` 29.84%
图片在页面的百分比高度height:0.2914 * 67 /191 =` 10.47%
计算公式: W(元素当前百分比宽度)/ padding-bottom = 图片真实宽度 / 图片真实高度。
为什么使用padding-bottom?因为height和width的参考对象不同(height的备份比值是以父元素的高度参考计算的,但是在实际中,只有在父元素的高度是一个指定值时,子元素设置的百分比高度才会起作用,否则高度会被充值未auto,设置height没有太多的运用价值),height值无法实现等比例变化,而高度在完全使用padding-bottom或者padding-top撑起来。
CSS规范中,margin和padding的百分比值是以其自身父元素的宽度为基础进行计算的。CSS的默认排版的横向的,横向宽度会是一定的,纵向高度是可以无限延展的。
- eg:一个div元素,宽300px,高度200px,其中包含子元素p,当p的CSS样式为margin:10%,p的margin-top/right/bottom/left分别为多少呢?按常规应该是20px,30px,20px,30px.
- 但真实值是30px,30px,30px,30px
- 当改变排版,给p的父盒子div设置-webkit-writing-mode-:vertical-lr; 即横向排版变成纵向。margin参考对象发生改变,从而以父元素的高度为基础进行计算,真实值为:20px,20px,20px,20px;
- 示例图
【左图为页面渲染结果;中、右图为盒子模型图 。】
- 左1:是横向排版margin10%,
- 左2:是竖向排版margin10%
- 左3:是横向排版margin-left:10px;
中:横向排版margin10%(左1)的盒子模型
右:竖向排版margin10%(左2)的盒子模型
验证margin参考对象遇到的坑———margin塌陷问题(以下是对margin的塌陷问题和外边距合并现象扩展):
- 场景:给div中的p设置margin:10%样式,按常规渲染应该出现如下图的样子。但实际情况却是上面的 左1图。 【div跟着p一起向下平移了!!】
- 大盒子包含一个小盒子,小盒子设置margin-top,大盒子会一起向下平移。这就是传说中的margin塌陷问题!
- 要强调的是外边距的塌陷问题只会在垂直之间产生塌陷;水平之间不受影响的;还有就是两个盒子的垂直外边距完全接触才会触发。
- margin塌陷问题的原因:
- 在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。【对于有块级子元素的元素计算高度的方式,如果元素没有垂直边框和填充,那其高度就是其子元素顶部和底部边框边缘之间的距离。一个DIV和它的子DIV特别重视垂直边框或填充,也就好像是,一口锅,里面放个盆,能不能扣住里面的盆,主要看锅盖了,垂直边框或填充就是这个“锅盖”。】
- margin-top是一个距离顶部多少像素的css样式,是用于两个盒子隔离边距用的,margin用于兄弟关系的盒子间距,而padding用于父子级的盒子间距。在编程上,这个其实是没有布好局导致的,需要注意布局方式层级关系。
- 外边距合并现象:
两个div上下拍咧,上div设置了margin-bottom,下div设置了margin-top,margin会合并,合并之后取较大的值作为两个div之间的间距。
margin外边距合并现象不需要解决,设置好值或者取其一即可。margin的塌陷问题是需要解决的,解决方法如下:
- 给大盒子(父元素)加一个边框border(border:1px solid transparent;或者border-top:1px solid transparent;)但是这样会改变盒模型和设计视图。不是很推荐,除非不影响页面整体效果。
- 给大盒子(父元素)设置一个overflow:hidden属性
- 浮动:float:left;
- 等等,触发BFC(块级格式上下文)。
- 在BFC中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin 值所决定的。在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。
- BFC中的元素的布局是不受外界的影响。并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。
- 浮动元素和绝对定位元素,非块级盒子的块级容器(eg: inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的BFC。
- 缩放法
- 缩放的方式有 Zoom 和 transfrom:scale()两种
1 . 支持的值类型不一样。Zoom:(百分比值)zoom:50%,表示缩小到原来的一半;(数值)zoom:0.5,表示缩小到原来的一半。zoom:normal 等同于zoom:1。
而 scale 并不支持百分比值和 normal 关键字,只能是数值。但是能负数,可以只控制1个维度。2 . 相对缩放位置不一样。Zoom 的缩放是相对于左上角的;而scale默认是居中缩放;
3 . Zoom 的缩放改变了元素占据的空间大小(缩放后容器所占据的空间是跟着一起缩放的);
而 scale 的缩放占据的原始尺寸不变,页面布局不会发生变化(缩放后,容器所占据的空间仍不变,会出现空白区域。);4 . Zoom 和 scale 对元素的渲染计算方法可能有差异:zoom:0.5(锐利); transfrom:scale(0.5)(模糊);
5 . 对文字的缩放规则不一致。Zoom 缩放依然受限于最小12像素中文大小限制;而 scale 就是纯粹的对图形进行比例控制,文字50%原来尺寸。
6 . 渲染的性能差异明显。由于 Zoom 的缩放会改变元素的真实空间大小,在 dom 中 Zoom 加在任意一个元素上都会引起一整个页面的重新渲染,而 scale 只是在当前的元素上重绘。因为 scale 变化时候,其原本的尺寸是不变的,就没有 layout 的重计算;但是 Zoom 牵一发动全身。
//zoom (function(fixWidth, id) { var ele = document.getElementById(id); function setZoom() { var cliWidth = document.documentElement.clientWidth || document.body.clientWidth; var blWidth = cliWidth / fixWidth; ele.style.zoom = blWidth; } window.addEventListener('resize', setZoom, false); setZoom(); })(640, 'wrap'); //wrap是页面最外层容器的id
-
- 监听resize事件,窗口大小改变的时候,运行setZoom,第一次运行的时候也设置一次。
- setZoom函数先获取屏幕分辨率,然后通过设计稿来计算缩放比例。参数为(设计稿宽度640,页面最外层容器id);
- 优点:可以按照设计稿尺寸进行页面开发,页面自动个根据浏览器的分辨率进行缩放;
- 缺点:高度是随着宽度进行缩放比的,所以滑屏布局用缩放来做自适应并不是很有利。
- Rem自适应:
- 通过js来控制根目录字号
(function() { if(window.addEventListener)return; var html = document.documentElement; function setFont() { var cliWidth = html.clientWidth; html.style.zoom = blWidth; } document.addEventListener('DOMContentLoaded',setFont,false) } })();
rem vs Zoom ? 各有千秋 择需采用
Zoom兼容PC和移动端,但是某些情况下回因为缩放导致定位出现错乱,并且滑屏的浏览形式不适用。
rem是CSS3的单位,所以在移动端浏览器使用最优,滑屏的尺寸也是可以精确控制的。- 模块和内容的自适应——适配方法
- 对于模块:
- 通过变化元素位置达到减少列数的目的,从而让内容以合适的尺寸显示,适应小屏幕设备。
- 通过隐藏或展开的方式对模块展示进行改变。
- 对模块尺寸进行放大或者缩小。
- 考虑增加或者删减模块的数量。
- 对于模块中的内容:
- 考虑挤压或拉伸内容容器的形状。
- 在内容排版上选择换行或者平铺。
- 和模块类似,对内容进行增加或者删减。
- 对于模块:
1.1.5 内容排布技巧
- 视频与iFrame的自适应
- 计算公式: W(元素当前百分比宽度)/ padding-bottom = 4/3 或16/9 或 16/10
- 水平垂直居中
- 水平通过绝对定位和margin,对于行内使用text-align:center
- 垂直居中使用display:box;需要注意的是要带私有前缀:-webkit- -moz-
-