乐趣区

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

前言

本来是打算写写怎么使用 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 的设备, 做一些样式适配

为什么需要了解这些?

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

示例

机型 iPhone6S 某某手机
设备宽高(pp) 375 * 667 375 * 667
屏幕密度(ppi) 326
CSS 像素(px) 375 * 667 375 * 667
设备独立像素(dip) 750dip * 1334dip 375dip 667dip
设备像素比(dpr) 2 1

尽管两者 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 页面的终端适配 https://www.w3cplus.com/mobil…)(还有一些常用的居中布局, 经典布局方法和优缺点可以参考我之前写的文章页面基础布局相关知识 — 居中 & 经典布局)

meta 标签

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

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

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

移动端必备标签!

属性 描述
width device-width: viewport 宽度
initial-scale 初始缩放比例
maximum-scale 最大缩放比例
minimum-scale 最小缩放比例
user-scalable 是否允许用户缩放(yes/no)

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

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

<meta name="format-detection" content="telephone=no" />

忽略识别邮箱

<meta name="format-detection" content="email=no" />

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

<meta content="yes" name="apple-mobile-web-app-capable"/>

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

<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />

默认值为 default(白色),可以定为 black(黑色)和 black-translucent(黑色半透明.)

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

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

<meta name="apple-mobile-web-app-title" content="标题">

苹果是否启用 WebApp 全屏模式

<meta name="apple-mobile-web-app-capable" content="yes" />

理论知识

CSS 优先级算法如何计算?

  • 元素选择符: 1
  • class 选择符: 10
  • id 选择符: 100
  • 内联样式: 1000
  • !important 优先级最高
  1. 如果优先级相同, 则选择最后出现的样式;
  2. 继承得到的样式的优先级最低;
  3. 嵌套选择器优先级是相加, 例如: #A .B = 100 + 10 = 110;

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

合并

  • margin 在垂直方向会合并, 其值为两者最大值, 水平方向不合并;
  • 如果元素内容为空, 自身 margin 垂直方向也会合并, 其值为两者最大值;
  • 父元素如果没有 padding, border 等属性时, 其子元素的 margin 上下方向会和父元素的 margin 进行重叠;

与其他元素相交定位

  • 位于普通文档流中元素, 只会覆盖颜色, 不会覆盖文字;
  • relative 下, 会完全覆盖前一个元素并影响后面元素一起移动;
  • absolute 下, 元素脱离了普通文档流并对其他元素没有影响;
  • 对于 float 元素, 可以通过负值进行覆盖;

(原本想写些例子, 但是太麻烦, 可能还得截图标注, 就干脆不写了.)

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

先说说 float 的特性:

浮动元素会脱离正常文档流, 一直平移到碰到容器边框或者另一个浮动元素;

浮动元素会根据上一个元素的类型判断位置:

  • 如果是浮动元素, 则跟随他浮动, 放置不下就挤到下一行展示;
  • 如果是标准流元素, 则浮动元素的相对垂直高度不变, 顶部和上一个底部对齐;

浮动带来的问题:

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

综合写法:

.clearfix:after {
  content: ""; // 设置内容为空  
  height: 0; // 高度为 0  
  line-height: 0; // 行高为 0  
  display: block; // 将文本转为块级元素 
  visibility: hidden; // 将元素隐藏  
  clear: both; // 清除浮动
}
.clearfix {zoom: 1; // 为了兼容 IE;}

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

根层叠上下文:

页面根元素 html;

定位元素与传统层叠上下文:

对于包含有 position:relative/position:absolute 的定位元素, 以及 FireFox/IE 浏览器 (不包括 Chrome 等 webkit 内核浏览器) 下含有 position:fixed 声明的定位元素, 当其 z-index 值不是 auto 的时候, 会创建层叠上下文;

CSS3 与新时代的层叠上下文:

  • z-index 值不为 auto 的 flex 项(父元素 display:flex|inline-flex).
  • 元素的 opacity 值不是 1.
  • 元素的 transform 值不是 none.
  • 元素 mix-blend-mode 值不是 normal.
  • 元素的 filter 值不是 none.
  • 元素的 isolation 值是 isolate.
  • will-change 指定的属性值为上面任意一个.
  • 元素的 – webkit-overflow-scrolling 设为 touch.

层叠上下文之间的顺序:

如果不依赖 z-index, 则 z-index:auto 可看成 z:index:0 级别;

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

如果依赖 z-index, 则其层叠顺序由 z-index 值决定.

z-index 胜者为王;

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

.title {}
.title h1 {}
.title h1 span {}

要找到. title .h1 span 选择器:

  1. 找到父节点 title;
  2. 在父节点之下找 h1;
  3. 再找到 h1 下面的 span;

看起来顺利解析完毕, 然后来看看再看看稍微复杂点的

.title {}
.title h1 {}
.title h2 {}
.title h1 em {}
.title 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” 点透 ”, 提升移动端点击响应速度](https://github.com/ftlabs/fas…)

点击穿透问题

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

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

解决方案:

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

滚动穿透问题

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

解决方案:

touchmove 事件监听加 e.preventDefault()

  • 如果遮罩本身也有滚动条也会被禁止;

body/html 添加 overflow:hidden,height: 100%;

  • 部分机器 / 浏览器不行;
  • 页面的背景还是能够有滚的动的效果;
  • 滚动位置消失, 需要 js 计算修复;
body.modal-open {position: fixed; width: 100%;}
------------------------------------------------------------
var ModalHelper = (function(bodyCls) {
    var scrollTop; // 在闭包中定义一个用来保存滚动位置的变量
    return {afterOpen: function() {
            // 弹出之后记录保存滚动位置, 并且给 body 添加. modal-open
            scrollTop = document.scrollingElement.scrollTop;
            document.body.classList.add(bodyCls);
            document.body.style.top = -scrollTop + 'px';
        },
        beforeClose: function() {
            // 关闭时将. modal-open 移除并还原之前保存滚动位置
            document.body.classList.remove(bodyCls);
            document.scrollingElement.scrollTop = scrollTop;
        },
    };
})('modal-open');

(从网上看到的方法关于移动端开发中遇到的坑)

通用样式

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

改变输入框 placeholder 的颜色值

::-webkit-input-placeholder {
  /* WebKit browsers */
  color: #999;
}
:-moz-placeholder {
  /* Mozilla Firefox 4 to 18 */
  color: #999;
}
::-moz-placeholder {
  /* Mozilla Firefox 19+ */
  color: #999;
}
:-ms-input-placeholder {
  /* Internet Explorer 10+ */
  color: #999;
}
input:focus::-webkit-input-placeholder {color: #999;}

省略文本

单行文本

p{
    overflow: hidden;/* 超出部分隐藏 */
    text-overflow:ellipsis;/* 超出部分显示省略号 */
    white-space: nowrap;/* 规定段落中的文本不进行换行 */
    width: 250px;/* 需要配合宽度来使用 */
    border: 1px solid red;
    font-size: 30px;
}

多行文本

p{
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
    width: 250px;
    border: 1px solid red;
    font-size: 30px; 
}

旋转样式

// 竖屏时样式
@media all and (orientation:portrait){}
// 横屏时样式
@media all and (orientation:landscape){}

transition 闪屏

// 设置内嵌的元素在 3D 空间如何呈现: 保留 3D
-webkit-transform-style: preserve-3d;
// 设置进行转换的元素的背面在面对用户时是否可见: 隐藏
-webkit-backface-visibility:hidden;
// 定义 3D 元素距视图的距离,以像素计
-webkit-perspective: 1000; 

纯 CSS 创建三角形?

div {
  width: 0;
  height: 0;
  border-top: 40px solid transparent;
  border-left: 40px solid transparent;
  border-right: 40px solid transparent;
  border-bottom: 40px solid #ff0000;
}

input[type=number]的问题

1, maxlength 属性不会提供任何反馈.

用 js 解决

2, form 提交会默认取整数.

step 属性规定 < input > 元素的合法数字间隔, 也是通过自带箭头增减的数字, 默认为 1

<input type="number" name="points" step="0.01" />

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

Element {-webkit-transform: rotate(-4deg) skew(10deg) translateZ(0);
  transform: rotate(-4deg) skew(10deg) translateZ(0);
  outline: 1px solid rgba(255,255,255,0);
}

打电话

<a href="tel:10086"> 打电话给: 10086</a>

发短信, winphone 系统无效

<a href="sms:10086"> 发短信给: 10086</a>

写邮件

第一个功能以 “?” 开头, 后面的以 “&” 开头

  • mailto: 普通邮件
  • cc: 收件地址后添加抄送地址(Android 存在兼容问题)
  • bcc: 抄送地址后添加密件抄送地址(Android 存在兼容问题)
  • subject: 包含主题
  • body: 包含内容,

    • 如包含文本, 使用 给文本换行
    • 如包含 http(s):// 等的文本自动转化为链接
    • 如内容包含图片(PC 不支持)

包含多个收件人, 抄送, 密件抄送人, 用分号 (;) 隔开多个邮件人的地址

<a href="mailto:xxx@qq.com;xxx@qq.com?cc=xxx&bcc=xxx@qq.com&subject=[邮件主题]&body=xxxhttp://www.baidu.com<img src='images/1.jpg'/>"> 点击我发邮件 </a>

系统兼容问题

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

某些 Android 手机圆角失效

Element {background-clip: padding-box;}

android 去掉语音输入按钮

input::-webkit-input-speech-button {display: none}

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

Element {-webkit-tap-highlight-color: rgba(255,255,255,0);
}

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

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

input,
textarea {
  border: 0;
  -webkit-appearance: none;
}

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

Element {-webkit-appearance: none;}

Retina 屏的 1px 边框

Element {border-width: thin;}

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

this.value = this.value.replace(/\u2006/g, '');

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

html5 的 oninput 事件代替

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

Element {-webkit-overflow-scrolling: touch;}

auto: 使用普通滚动, 当手指从触摸屏上移开, 滚动会立即停止.

touch: 使用具有回弹效果的滚动, 当手指从触摸屏上移开, 内容会继续保持一段时间的滚动效果. 继续滚动的速度和持续的时间和滚动手势的强烈程度成正比. 同时也会创建一个新的堆栈上下文.

启动了硬件加速的特性, 所以滑动起来会非常流畅; 不过会影响性能

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

<input type="text" autocapitalize="off" />

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

a,
img {-webkit-touch-callout: none;}

手机拍照和上传图片

IOS 有拍照, 录像, 选取本地图片功能, 部分 Android 只有选择本地图片功能. Winphone 不支持

<input type="file" accept="images/*" />
<input type="file" accept="video/*" />

输入框被键盘挡住问题

if (/Android/.test(navigator.appVersion)) {window.addEventListener('resize', function() {if (document.activeElement.tagName == 'INPUT' || document.activeElement.tagName == 'TEXTAREA') {document.activeElement.scrollIntoView();
        }
    });
}

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

播放视频不全屏

ios7 + 支持自动播放

支持 Airplay 的设备 (如: 音箱, Apple TV) 播放: x-webkit-airplay=”true”

播放视频不全屏: webkit-playsinline=”true”

<video x-webkit-airplay="true" webkit-playsinline="true" preload="auto" autoplay src="http://"></video>

移动端 HTML5 audio autoplay 失效问题

苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放, 必须由用户来触发才可以播放.

  1. audio 元素的 autoplay 属性在 IOS 及 Android 上无法使用, 在 PC 端正常
  2. audio 元素没有设置 controls 时, 在 IOS 及 Android 会占据空间大小, 而在 PC 端 Chrome 是不会占据任何空间

解决方法思路: 先通过用户 touchstart 触碰, 触发播放并暂停(音频开始加载, 后面用 JS 再操作就没问题了).

document.addEventListener('touchstart', function() {document.getElementsByTagName('audio')[0].play();
    document.getElementsByTagName('audio')[0].pause();});

微信下兼容处理

document.addEventListener(
    'WeixinJSBridgeReady',
    function() {music.play();
    },
    false
);

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

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

window.onload = function () {
  // 同时按下两个手指
  document.addEventListener('touchstart', function (event) {if (event.touches.length > 1) {event.preventDefault();
    }
  });
  var lastTouchEnd = 0;
  // 特别注意 300ms 时差的设置
  document.addEventListener('touchend', function (event) {var now = new Date().getTime();
    if (now - lastTouchEnd <= 300) {event.preventDefault();
    }
    lastTouchEnd = now;
  });
};

定位的坑

fixed 定位

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

解决方案: 使用 Iscroll , 如:

<div id="wrapper">
  <ul>
    <li></li>
  </ul>
</div>
<script src="iscroll.js"></script>
<script>
  var myscroll;
  function loaded() {myscroll = new iScroll("wrapper");
  }
  window.addEventListener("DOMContentLoaded", loaded, false);
</script>

position 定位

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

var ua = navigator.userAgent.indexOf('Android');
if (ua > -1) {$('.ipt')
        .on('focus', function() {$('.css').css({visibility: 'hidden'});
        })
        .on('blur', function() {$('.css').css({visibility: 'visible'});
        });
}

各种黑科技

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

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

新版本谷歌好像取消支持了

-webkit-text-size-adjust: none;

缩小尺寸

-webkit-transform: scale(0.5);

解决缩放后 margin-left 的位移问题

-webkit-transform-origin-x: 0;

解决缩放后 margin-left 的位移问题

-webkit-transform-origin-x: 0;

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

长时间按住页面出现闪退

element {-webkit-touch-callout: none;}

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

body,
div,
fieldset,
form,
h1,
h2,
h3,
h4,
h5,
h6,
html,
p {webkit-text-size-adjust: 100%;}

去除 input 默认样式

input[type=number] {-moz-appearance: textfield;}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

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

input[type=checkbox]::-ms-check,
input[type=radio]::-ms-check {display: none;}

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

input[type=number]::-ms-clear,
input[type=tel]::-ms-clear,
input[type=text]::-ms-clear {display: none;}

select 下拉选择设置右对齐

select option {direction: rtl;}

出现滚动条时页面跳动?

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

Element {margin-left: calc(100vw - 100%);
}

禁止复制, 选中文本

Element {
  -webkit-user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  user-select: none;
}
退出移动版