关于移动端基础布局概念方式和常见问题总结(不定时更新)

原创 Lin_Grady 教程 html/css 1101阅读 2018-05-06 21:44:19 举报

前言

本来是打算写写怎么使用lib-flexible进行移动端的布局的,然后前面还加些像素基本知识铺垫,后面又加了些CSS属性概念,最后还来些常见布局问题和系统样式bug,果然排版也是门高深学问,这里有些自己写的,有些看完之后总结出来的,还有些别人那里搬来的,顺带会送上飞机票告诉你们来源在哪里,他们会更加仔细,毕竟我只是简明扼要的写结论.
因为知识点太多,我没有全都碰到过,所以最后的一些样式解决办法是觉得有用写出来的,没试过,以后如果还有遇到其他问题或者看到别人有意思的方案也会补充进来.
最后,这文章我已经转成简体字了,应该不会再有人说看的吃力了吧.

疑问

相比PC端,移动端怎么适配不同尺寸的屏幕?
为什么同一套代码,有些看起来很清晰,有些看起来很模糊?
除了响应式之外有一步到位的布局方法么?
为什么样式没写错,有些手机用起来就是不正常?
怎么解决遇到的一些乱七八糟没有逻辑的bug?

像素基本知识

视窗 viewport:

设备的屏幕上能用来显示我们的网页的那一块区域,而移动端还提供了两个viewport:

  • visual viewport(虚拟视口):
    可以改变大小或形状,当前屏幕上显示的页面的一部分.
    通过window.innerWidth/Height获取,会随著页面缩放而变化.
  • layout viewport(布局视口):
    不会改变大小或形状,可以比可视化的viewport宽得多,并且包含出现在屏幕上的元素.
    通过document.documentElement.clientWidth/Height获取.在Android 2, Oprea mini 和 UC 8中无法正确获取.
  • ideal viewport(理想视口):
    不需要用户缩放和滚动就能正常的查看网站的所有内容,显示的文字大小合适,保证同样的网站在不同分辨率的设备上看起来都是一样或差不多的.
  • 渲染过程:
    1) 渲染: 将整个页面渲染在一个layout viewport中,以保证页面排版正确;
    2) 缩放: 将整个layout viewport缩放到visual viewport大小,以保证页面在手机屏幕上被完整显示出来;
    公式表示就是:visual viewpor = layout viewport * scale;

例如你在手机上访问一个PC页面,手机当前展示区域就是visual viewport,但是整个PC页面是很大的,往往屏幕是显示不完,所以会出现滚动条给你滑动(固定值排版的话),整个PC页面的尺寸就是layout viewport了,上面说visual viewport可以改变大小或形状,意思是你可以通过旋转屏幕或放大缩小改变显示的页面.

物理像素(physical pixel)/设备像素:

显示设备中一个最微小的物理部件.每个像素可以根据操作系统设置自己的颜色和亮度.正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果.

设备独立像素(density-independent pixel)/逻辑像素/密度无关像素:

可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用并控制的虚拟像素(比如CSS像素),然后由相关系统转换为物理像素.
公式表示就是:CSS像素 = 设备独立像素 = 逻辑像素.

与设备无关的像素(device-independent pixel)/CSS像素

用于页面布局的抽象单位,用来精确度量网页上的内容,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素的长度可能是不同的.

屏幕密度(pixels per inch)/像素密度:

即每英寸屏幕所拥有的像素数,像素密度越大,显示画面细节就越丰富,
公式表示就是:像素密度 = 对角线分辨率 / 屏幕尺寸.

设备像素比(device pixel ratio):

物理像素与逻辑像素之间的比例.
公式表示就是:设备像素比(dpr) = 物理像素(pp) / 设备独立像素(dip).
在JavaScript中,可以通过window.devicePixelRatio获取到当前设备的dpr.而在CSS中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview).

为什么需要了解这些?

一切的起源来自于iphone4的诞生,当时它使用一种新的屏幕的显示技术Retina(视网膜),它将640x960的分辨率压缩到一个3.5英寸的显示屏,像素密度达到326像素/英寸(ppi).声称当一个显示屏像素密度超过300ppi时,人眼就无法区分出单独的像素,显示设备清晰度已达到人视网膜可分辨像素的极限.

示例

以iPhone6S作为基准设计尺寸
设备宽高: 375pt 667pt
屏幕密度: 326ppi
visual viewport: 375px
667px
物理像素: 750pp 1334pp
CSS像素: 750px
1334px
设备独立像素: 750dip * 1334dip
设备像素比: 2dpr

某某手机
设备宽高: 375pt 667pt
visual viewport: 375px
667px
物理像素: 375pp 667pp
设备独立像素: 375dip
667dip
设备像素比: 1dpr

尽管两者CSS像素所呈现的物理尺寸是一致的,但在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素.靠提升单位面积屏幕的像素数量,即像素密度来提升分辨率.
iphone常见如下:

(更详细内容请看The Ultimate Guide To iPhone Resolutions)

lib-flexible

重点来了,在旧的布局方式困难重重,新的属性方法短时间不被主流浏览器大范围兼容的情况下,手淘团队出了lib-flexible.

基本原理: 先在<html>元素上增加一个data-dpr属性,以及一个font-size样式.JS会根据不同的设备添加不同的data-dpr值和对应的font-size的值.开发时候通过把设计稿做些计算转换成rem单位来设置.他们会根据html元素的font-size值做相应的计算,从而实现屏幕的适配效果.

使用建议:
1, 在页面所有资源加载前执行,避免在渲染过程或之后再次重新计算样式;
2, 像字体,某些固定尺寸的样式可以直接使用px;

(更详细内容请看使用Flexible实现手淘H5页面的终端适配)
(还有一些常用的居中布局,经典布局方法和优缺点可以参考我之前写的文章页面基础布局相关知识 --- 居中&经典布局)

meta标签

这里只会列出一些常用的标签,单独某些浏览器或低版本系统不会列出来.

限制移动端页面视口宽度缩放等.

移动端必备标签!
width viewport宽度(数值/device-width)
height viewport高度(数值/device-height)
initial-scale 初始缩放比例
maximum-scale 最大缩放比例
minimum-scale 最小缩放比例
user-scalable 是否允许用户缩放(yes/no)

禁止数字识自动别为电话号码

很多时候真的只是文本文字,也会被当作电话号码处理

忽略识别邮箱

删除默认的苹果工具栏和菜单栏

设置苹果状态栏的背景颜色

default 默认值.
black 状态栏背景是黑色.
black-translucent 状态栏背景是黑色半透明. 如果设置为 default 或 black ,网页内容从状态栏底部开始. 如果设置为 black-translucent ,网页内容充满整个屏幕,顶部会被状态栏遮挡.

苹果添加到主屏后的标题(iOS 6 新增)

苹果是否启用WebApp全屏模式

理论知识

CSS优先级算法如何计算?

  • 元素选择符: 1
  • class选择符: 10
  • id选择符:100
  • 内联样式:1000
  • !important优先级最高

1) 如果优先级相同,则选择最后出现的样式;
2) 继承得到的样式的优先级最低;
3) 嵌套选择器优先级是相加,例如: #A .B = 100 + 10 = 110;

margin有什么需要注意的特性?

  • 合并
    1) margin在垂直方向会合并,其值为两者最大值,水平方向不合并;
    2) 如果元素内容为空,自身margin垂直方向也会合并,其值为两者最大值;
    3) 父元素如果没有padding、border等属性时,其子元素的margin上下方向会和父元素的margin进行重叠;
  • 与其他元素相交定位
    1) 位于普通文档流中元素,只会覆盖颜色,不会覆盖文字;
    2) relative下,会完全覆盖前一个元素并影响后面元素一起移动;
    3) absolute下,元素脱离了普通文档流并对其他元素没有影响;
    4) 对于float元素,可以通过负值进行覆盖;
    (原本想写些例子,但是太麻烦,可能还得截图标注,就干脆不写了.)

为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式?

先说说float的特性:

  • 浮动元素会脱离正常文档流,一直平移到碰到容器边框或者另一个浮动元素;
  • 浮动元素会根据上一个元素的类型判断位置:
    1) 如果是浮动元素,则跟随他浮动,放置不下就挤到下一行展示;
    2) 如果是标准流元素,则浮动元素的相对垂直高度不变,顶部和上一个底部对齐;

浮动带来的问题:

  • 父元素的高度无法被撑开,影响与父元素同级的元素
  • 与浮动元素同级的非浮动元素(内联元素)会跟随其后
  • 若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构.

综合写法:

position跟display、overflow、float这些特性相互叠加后会怎么样?

display属性规定元素应该生成的框的类型;
overflow属性规定当内容溢出元素框时发生的事情.
position属性规定元素的定位类型;
float属性是一种布局方式,定义元素在哪个方向浮动.

  • 首先overflow怎么处理溢出显示,跟其他三者无冲突影响的;
  • 如果display: none此元素不会被显示.否则就是规定元素应该生成的框的类型;
  • 如果脱离文档流的话position:absolute/fixed优先级高于浮动float,并且display只能影响子元素继承属性;
  • float或者absolute定位的元素,display只能是块元素或表格;

元素竖向的百分比设定是相对于容器的高度吗?

当按百分比设定一个元素的宽度时,它是相对于父容器的宽度计算的,但是,对于一些表示竖向距离的属性,例如 padding-top , padding-bottom , margin-top , margin-bottom 等,当按百分比设定它们时,依据的也是父容器的宽度,而不是高度.

伪类和伪元素有哪些,又有什么区别和作用?

伪类 (Pseudo-classes) :active, :focus, :hover, :link, :visited, :first-child, :lang等,用于向某些选择器添加特殊的效果.
伪元素 (Pseudo-elements) :first-letter, :first-line, :before, :after等,用于向某些选择器设置特殊效果.

伪类能获取不能被常规CSS选择器获取的信息,可以算是选择器的一种补充吧,每个选择器可以同时使用多种伪类.
伪元素能在DOM树中创建一些存在于文档语言里的抽象元素.

对BFC规范的理解?

定义: BFC(Block formatting context)直译为"块级格式化上下文".它是一个独立的渲染区域,只有Block-level box参与,它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干.

w3c规范中的BFC定义:

浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的BFC(块级格式上下文).
在BFC中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin值所决定的.在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠.
在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘).

BFC布局规则:
1, 内部的Box会在垂直方向,一个接一个地放置;
2, Box垂直方向的距离由margin决定.属于同一个BFC的两个相邻Box的margin会发生重叠;
3, 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反).即使存在浮动也是如此;
4, BFC的区域不会与float box重叠;
5, BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素.反之也如此;
6, 计算BFC的高度时,浮动元素也参与计算;

触发条件:
1, 根元素,即html;
2, float的值不为none(默认);
3, overflow的值不为visible(默认);
4, display的值为inline-block、table-cell、table-caption;
5, position的值为absolute或fixed;

(更详细内容请看前端精选文摘:BFC 神奇背后的原理)

层叠

(实在复杂,更详细内容请看CSS大神张鑫旭的深入理解CSS中的层叠上下文和层叠顺序,下面都是我根据他的文章简要记录下来的)

层叠上下文(stacking context): 是HTML中的一个三维的概念.如果一个元素含有层叠上下文,我们可以理解为这个元素在z轴上就“高人一等”.
层叠水平(stacking level): 决定了同一个层叠上下文中元素在z轴上的显示顺序.
层叠顺序(stacking order): 表示元素发生层叠时候有著特定的垂直显示顺序.
注意:上面的层叠上下文和层叠水平是概念,而这里的层叠顺序是规则.

(原谅我盗图)

特别说明:
普通元素的层叠水平优先由层叠上下文决定,某些情况下z-index可以影响层叠水平,但是,只限于定位元素以及flex盒子的子元素;

层叠准则:
1, 当在同一个层叠上下文领域具有明显的层叠水平标示的时候,如z-indx,层叠水平值大的那一个覆盖小的那一个;
2, 当元素的层叠水平一致、层叠顺序相同的时候,在DOM流中处于后面的元素会覆盖前面的元素;

层叠上下文的特性:
1, 层叠上下文的层叠水平要比普通元素高;
2, 层叠上下文可以阻断元素的混合模式(普通元素的层叠水平优先由层叠上下文决定);
3, 层叠上下文可以嵌套,内部层叠上下文及其所有子元素均受制于外部的层叠上下文(父元素的层级决定了子元素之间的层级比较);
4, 每个层叠上下文和兄弟元素独立,也就是当进行层叠变化或渲染的时候,只需要考虑后代元素;
5, 每个层叠上下文是自成体系的,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中;

层叠上下文的创建:

  • 根层叠上下文:
    1) 页面根元素html;
  • 定位元素与传统层叠上下文:
    1) 对于包含有position:relative/position:absolute的定位元素,以及FireFox/IE浏览器(不包括Chrome等webkit内核浏览器)下含有position:fixed声明的定位元素,当其z-index值不是auto的时候,会创建层叠上下文;
  • CSS3与新时代的层叠上下文:
    1) z-index值不为auto的flex项(父元素display:flex|inline-flex).
    2) 元素的opacity值不是1.
    3) 元素的transform值不是none.
    4) 元素mix-blend-mode值不是normal.
    5) 元素的filter值不是none.
    6) 元素的isolation值是isolate.
    7) will-change指定的属性值为上面任意一个.
    8) 元素的-webkit-overflow-scrolling设为touch.

层叠上下文之间的顺序:

  • 如果不依赖z-index,则z-index:auto可看成z:index:0级别;
    1) 元素一旦成为定位元素,其z-index就会自动生效就是默认的auto,也就是0级别,根据上面的层叠顺序表,就会覆盖inline或block或float元素;
    2) 不支持z-index的层叠上下文元素天然z-index:auto级别,也就意味著,层叠上下文元素和定位元素是一个层叠顺序的,遵循的是“后来居上”准则
  • 如果依赖z-index,则其层叠顺序由z-index值决定.
    1) z-index胜者为王;

(以前写的文章也提到一道关于层叠的题目,在一些搞死人的基础题 --- (不定时更新)里面的: 三,關於z-index 層級樹)

浏览器是怎样解析CSS选择器的?

要找到.title .h1 span选择器:
1, 找到父节点title;
2, 在父节点之下找h1;
3, 再找到h1下面的span;
看起来顺利解析完毕,然后来看看再看看稍微复杂点的

要找到.title .h1 span选择器:
1, 找到父节点title;
2, 在父节点之下找h1(第三行不符合);
3, 再找到h1下面的span(第四行不符合);
在这里也能大概看得出,如果是从左往右解析CSS选择器的话,每次发现不符合规则的都要进行回溯,不仅浪费时间而且浪费性能,所以上面的说法是我误导不懂的人的,实际上浏览器CSS选择器的解析规则是从右往左的.然后我们再看看上面的解析规则.
1, 找到子节点span;
2, 在span的父节点上找h1;
3, 在h1的父节点上找title;
整个解析下来,每一步都能过滤掉些不符合规则的分支情况,直到找到根元素或满足条件的匹配规则的选择器就结束这个分支的遍历.
最后建议:,不管浏览器怎么解析,我刚开始学前端的时候就经常看到那么一句话: 尽量避免深层嵌套CSS,因为寻找选择器和计算最终样式都会受影响的.

如果需要手动写动画,你认为最小时间间隔是多久,为什么?

多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms.

移动端点击300ms延迟

原因: 因为手机会通过300ms的延迟判断用户是单击还是双击屏幕决定执行哪种手势行为.

解决方案:
1, 网页头部meta标签禁用缩放,为了解决短暂的延迟问题却要完全禁止用户手势缩放行为,这就过分了;
2, 网页头部meta标签设置视口宽度为设备宽度,优点是只禁用双击手势缩放功能;
3, 指针事件,是一个新的 web 事件系列,相应的规范旨在使用一个单独的事件模型,对所有输入类型,包括鼠标 (mouse)、触摸 (touch)、触控 (stylus) 等,进行统一的处理.其中touch-action
属性决定 “是否触摸操作会触发用户代理的默认行为.这包括但不限于双指缩放等行为”.但浏览器兼容是个问题;

解决库:
1, 指针事件库, 就是上面第三个方案的js兼容库;
2, FastClick.js,实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即触发模拟一个click事件,并把浏览器在300ms之后的click事件阻止掉.需要注意的是至2015年之后的浏览器大多数都已经取消了300ms的延迟,再引入的话不仅没用还可能引起应用bug;
3, tap事件代替click, 如果你引用的库或框架有提供的话;
(我发现有个文章深入源码分析的挺好的,虽然我没细看,有兴趣可以看一下【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度)

点击穿透问题

原因: 移动端一次点击会顺序触发touchstart -> touchmove -> touchend -> tap(如果有) -> click,并且click有300ms的滞后性.

举例: 有一对父子元素,分别绑定让自身消失的事件在父元素的click和子元素的touchstart上,当点击子元素会让子元素自身消失,过了300ms之后才会触发到click事件,但是子元素已经消失了,click事件会被顺递派发到下层的父元素让其也消失.

解决方案:
(1)尽量都使用touch事件来替换click事件.例如用touchend事件(推荐);
(2)fastclick;
(3)preventDefault阻止;
(4)延迟一定的时间(300ms+)来处理事件 (不推荐);
(5)以上一般都能解决,实在不行就换成click事件;

滚动穿透问题

举例: 当页面弹出遮罩的时候依然可以让页面滚动.

解决方案:

  • touchmove事件监听加e.preventDefault()
    1) 如果遮罩本身也有滚动条也会被禁止;
  • body/html添加overflow:hidden,height: 100%;
    1) 部分机器/浏览器不行;
    2) 页面的背景还是能够有滚的动的效果;
    3) 滚动位置消失,需要js计算修复;
  • position: fixed(从网上看到的方法关于移动端开发中遇到的坑)

通用样式

这里只会总结部分特殊问题,太常见的就不提,IE的不提,低版本浏览器问题不提(主要我也不懂).

改变输入框placeholder的颜色值

旋转样式

transition闪屏

纯CSS创建三角形?

input[type=number]的问题

1, maxlength属性不会提供任何反馈.
用js解决
2, form提交会默认取整数.
step属性规定<input>元素的合法数字间隔,也是通过自带箭头增减的数字,默认为1

通过transform进行skew变形,rotate旋转会造成出现锯齿现象

打电话

发短信,winphone系统无效

写邮件

第一个功能以"?"开头,后面的以"&"开头
mailto:普通邮件
cc: 收件地址后添加抄送地址(Android存在兼容问题)
bcc: 抄送地址后添加密件抄送地址(Android存在兼容问题)
subject: 包含主题
body: 包含内容,
1) 如包含文本,使用%0A给文本换行
2) 如包含http(s)://等的文本自动转化为链接
3) 如内容包含图片(PC不支持)
包含多个收件人、抄送、密件抄送人,用分号(;)隔开多个邮件人的地址

系统兼容问题

安卓苹果常见的问题,还有些基于系统版本,浏览器版本的不说.

某些Android手机圆角失效

android上去掉语音输入按钮

ios和android下触摸元素时出现半透明灰色遮罩

有些机型去除不了,不使用a或者input标签,直接用div标签

ios 设置input按钮样式会被默认样式覆盖

iphone及ipad下输入框默认内阴影

Retina屏的1px边框

关于 iOS 系统中,中文输入法输入英文时,字母之间可能会出现一个六分之一空格

IOS中input键盘事件keyup、keydown、keypress支持不是很好

html5的oninput事件代替

iOS某些时候会觉得滚动很卡

auto: 使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止.
touch: 使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果.继续滚动的速度和持续的时间和滚动手势的强烈程度成正比.同时也会创建一个新的堆栈上下文.
启动了硬件加速的特性,所以滑动起来会非常流畅;不过会影响性能

解决IOS键盘字母输入默认首字母大写

禁止长按链接与图片弹出菜单

手机拍照和上传图片

输入框被键盘挡住问题

可以解决绝大数安卓机上面的问题

播放视频不全屏

移动端 HTML5 audio autoplay 失效问题

苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放.
1.audio元素的autoplay属性在IOS及Android上无法使用,在PC端正常
2.audio元素没有设置controls时,在IOS及Android会占据空间大小,而在PC端Chrome是不会占据任何空间
解决方法思路:先通过用户touchstart触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了).

微信下兼容处理

ios10+以上,尽管开发者设置了user-scalable=no,Safari还是允许用户通过手势来缩放

检测touch相关事件来阻止事件的触发

定位的坑

fixed定位
1.ios下fixed元素容易定位出错,软键盘弹出时,影响fixed元素定位
2.android下fixed表现要比iOS更好,软键盘弹出时,不会影响fixed元素定位
3.ios4下不支持position:fixed
解决方案:使用Iscroll,如:

position定位
Android下弹出软键盘弹出时,影响absolute元素定位

各种黑科技

使用的都是些特殊属性,兼容性是个比较大的问题.

Chrome设置小于12px的字体大小?

注意: 放在body上会导致页面缩放失效

长时间按住页面出现闪退

旋转屏幕时,字体大小调整的问题

去除input默认样式

禁用radio和checkbox默认样式,::-ms-check修改表单复选框或单选框默认图标,设置隐藏并使用背景图片来修饰

禁用pc端表单输入框默认清除按钮,::-ms-clear修改清除按钮,设置隐藏并使用背景图片来修饰

select下拉选择设置右对齐

出现滚动条时页面跳动?

原因是滚动条占据一定的宽度挤压了页面布局导致的.

禁止复制、选中文本

评论 ( 1 )
最新评论
长大吧 2018-05-22 12:49:27 1F

很认真,想收藏!排版很好! 问题加上答案的方式,布局-理论-样式(通用样式)-小tips总结。值得借鉴学习!