移动端兼容(三)布局问题

2019 Java 开发者跳槽指南.pdf (吐血整理)….>>>

移动端兼容(三)布局问题

前言

现阶段前端的发展重点是移动端,本该native同学处理的事情,由于混合开发的崛起,前端的小手不得不伸得更长,掌握工作中常用的移动端适配问题 尤为重要。

一、处理 Retina 双倍屏幕

对于小型网站,CSS Sprites并没有带来很大的变化,或许这样使用并不理想。但在是高分辨率的显示屏幕下,比如说Retina屏幕下,CSS Sprites将会起来越重要。

优化高分辨率下的屏幕下效果,你需要通过“media queries”准备一张大的图片。所以在正常分辨率下加载的是“@1x”图像,在高分辨率下加载的是@2像素下的效果。这就意味着,你的图片数要增加两倍,而且CSS样式中也需要增加两倍。我们可以通过javascript可以解决,但是我们没有找到通过代码真正解决的方法。但是通过css sprites技术,我们只需要通过CSS的选择器来覆盖@1x的图片。

span.location {
  backgroundurl(location.png) no-repeat 0 0;
}

span.success {
  backgroundurl(success.png) no-repeat 0 0;


a.delete {
  backgroundurl(delete.png) no-repeat 0 -100px;


.content a.fav-link {
  backgroundurl(favorite.png) no-repeat 0 0;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2), 
only screen and (min-device-pixel-ratio: 2) {
  span.location {
    background-imageurl(location@2x.png);
    background-size16px 14px;
  }

  span.success {
    background-imageurl(success@2x.png);
    background-size13px 14px;
  }

  a.delete {
    backgroundurl(delete@2x.png) no-repeat 0 -100px;
  } 

.content a.fav-link {
  background-imageurl(favorite@2x.png);
  background-size11px 13px;
  }
}

span.location {
  backgroundurl(sprite.png) no-repeat 0 0;
}

span.success {
  backgroundurl(sprite.png) no-repeat -100px 0;


a.delete {
  backgroundurl(sprite.png) no-repeat -100px -100px;


.content a.fav-link {
  backgroundurl(sprite.png) no-repeat 0 -100px;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2), 
only screen and (min-device-pixel-ratio: 2) {
  span.location,
  span.success,
  a.delete,
  .content a.fav-link {
    /* Reference the @2x Sprite */
    background-imageurl(sprite@2x.png);
    /* Translate the @2x sprite's dimensions back to 1x */
    background-size200px 200px
  }
}
记住上面的这个例子仅适用于Retina屏幕下的设备,目前仅在IOS的移动设备iPhone4s、iPhone5、iPad、iPod和Mackbook Pro。对于Android系统下,要取决于你的系统,采用不同的“min-device-pixel-ratio”。
不应该将所有的资源引入一个文件中,应该使用CSS sprite来集成图片。并且创建@2x的sprites图,这个图刚好是普通图的两倍,而且具有双向扩展,在Retina屏幕下,对应的元素上使用相同的Scripts图片。使用background-size属性来确保你的@2x Sprites图正确定位。在Retina屏幕下,使用这种方法,不仅节约了的请求,还让你的代码简洁易于维护,同时在Retina下也更高效。

二、placeholder问题

input类型为date情况下不支持placeholder,这其实是浏览器自己的处理。因为浏览器会针对此类型 input 增加 datepicker 模块。对 input type date 使用 placeholder 的目的是为了让用户更准确的输入日期格式,iOS 上会有 datepicker 不会显示 placeholder 文字,但是为了统一表单外观,往往需要显示。Android 部分机型没有 datepicker 也不会显示 placeholder 文字。

桌面端(Mac)

  • Safari 不支持 datepicker,placeholder 正常显示。

  • Firefox 不支持 datepicker,placeholder 正常显示。

  • Chrome 支持 datepicker,显示年、月、日格式,忽略placeholder。

移动端

  • iPhone5 iOS7 有 datepicker 功能,但是不显示placeholder。

  • Andorid 4.0.4 无 datepicker 功能,不显示 placeholder

解决方法:

<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')"  id="date"
因为text是支持placeholder的。因此当用户focus的时候自动把type类型改变为date,这样既有placeholder也有datepicker了。

三、判断照片的横竖排列

有这样一种需求,需要判断用户照片是横着拍出来的还是竖着拍出来的,这里需要使用照片的exif信息:
$("input").change(function({
    var file = this.files[0];
    fr   = new FileReader;

    fr.onloadend = function({
        var exif = EXIF.readFromBinaryFile(new BinaryFile(this.result));
        alert(exif.Orientation);
    };

    fr.readAsBinaryString(file);
});
针对exif信息,android、ios平台有不同的获取方法。

四、白屏解决与优化方案

当前很多无线页面都使用前端模板进行数据渲染,那么在糟糕的网速情况下,一进去页面,看到的不是白屏就是 loading,这成为白屏问题。此问题发生的原因基本可以归结为网速跟静态资源,下面的解决方法均在不考虑增加服务器硬件资源和带宽的情况下。
css文件加载需要一些时间,在加载的过程中页面是空白的。
  • 可以考虑将css代码前置和内联。

首屏无实际的数据内容,等待异步加载数据再渲染页面导致白屏。
  • 在首屏直接同步渲染html,后续的滚屏等再采用异步请求数据和渲染html。

首屏内联js的执行会阻塞页面的渲染。
  • 尽量不在首屏html代码中放置内联脚本。

解决方案
根本原因是客户端渲染的无力,因此最简单的方法是在服务器端,使用模板引擎渲染所有页面。同时
  • 减少文件加载体积,如html压缩,js压缩。

  • 加快js执行速度 比如常见的无限滚动的页面,可以使用js先渲染一个屏幕范围内的东西。

  • 提供一些友好的交互,比如提供一些假的滚动条。

  • 使用本地存储处理静态文件。

五、active的兼容

要让a链接的CSS active伪类生效,只需要给这个a链接的touch系列的任意事件touchstart/touchend绑定一个空的匿名方法即可hack成功。
<style>
a {
color#000;
}
a:active {
color#fff;
}
</style>
<a herf=”asdasd”>asdasd</a>
<script>
var a=document.getElementsByTagName(‘a’);
for(var i=0;i<a.length;i++){
a[i].addEventListener(‘touchstart’,function(){},false);
}
</script>

六、安卓手机点击锁定页面问题

有些安卓手机,页面点击时会停止页面的javascript,css3动画等的执行,可以用阻止默认事件解决。
function touchHandlerDummy(e)
{
    e.preventDefault();
    return false;
}
document.addEventListener("touchstart", touchHandlerDummy, false);
document.addEventListener("touchmove", touchHandlerDummy, false);
document.addEventListener("touchend", touchHandlerDummy, false);

七、禁用的一些小功能

7.1 使用特殊链接:
如果你关闭自动识别后,又希望某些电话号码能够链接到 iPhone 的拨号功能,那么可以通过这样来声明电话链接。
<a href="tel:12345654321">打电话给我</a>
<a href="sms:12345654321">发短信</a>
或用于单元格:
<td onclick="location.href='tel:122'">
7.2 自动大写与自动修正
要关闭这两项功能,可以通过autocapitalize 与autocorrect 这两个选项:
<input type="text" autocapitalize="off" autocorrect="off" />
7.3 不让 Android 识别邮箱
<meta content="email=no" name="format-detection" />
7.4 禁止 iOS 弹出各种操作窗口
-webkit-touch-callout:none
7.5 禁止用户选中文字
-webkit-user-select:none

八、WebAPP启动图片在ios设备上的适应性

<!-- iPhone ICON -->
<link href="apple-touch-icon-57x57.png" sizes="57x57" rel="apple-touch-icon">
<!-- iPad ICON-->
<link href="apple-touch-icon-72x72.png" sizes="72x72" rel="apple-touch-icon">
<!-- iPhone (Retina) ICON-->
<link href="apple-touch-icon-114x114.png" sizes="114x114" rel="apple-touch-icon">
<!-- iPad (Retina) ICON-->
<link href="apple-touch-icon-144x144.png" sizes="144x144" rel="apple-touch-icon">

<!-- iPhone SPLASHSCREEN-->
<link href="apple-touch-startup-image-320x460.png" media="(device-width: 320px)" rel="apple-touch-startup-image">
<!-- iPhone (Retina) SPLASHSCREEN-->
<link href="apple-touch-startup-image-640x920.png" media="(device-width: 320px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPad (portrait) SPLASHSCREEN-->
<link href="apple-touch-startup-image-768x1004.png" media="(device-width: 768px) and (orientation: portrait)" rel="apple-touch-startup-image">
<!-- iPad (landscape) SPLASHSCREEN-->
<link href="apple-touch-startup-image-748x1024.png" media="(device-width: 768px) and (orientation: landscape)" rel="apple-touch-startup-image">
<!-- iPad (Retina, portrait) SPLASHSCREEN-->
<link href="apple-touch-startup-image-1536x2008.png" media="(device-width: 1536px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPad (Retina, landscape) SPLASHSCREEN-->
<link href="apple-touch-startup-image-2048x1496.png" media="(device-width: 1536px)  and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 6/7/8 -->
<link href="/images/favicon/750x1334.png" media="(device-width: 375px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<!-- iPhone 6 Plus/7 Plus/8 Plus -->
<link href="/images/favicon/1242x2208.png" media="(device-width: 414px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />

九、input元素输入时出现的怪异

Android Web 视图,至少在 HTC EVO 和三星的 Galaxy Nexus 中,文本输入框在输入时表现的就像占位符。情况为一个类似水印的东西在用户输入区域,一旦用户开始输入便会消失。
在 Android 的默认样式下当输入框获得焦点后,若存在一个绝对定位或者 fixed 的元素,布局会被破坏,其他元素与系统输入字段会发生重叠(如搜索图标将消失为搜索字段),可以观察到布局与原始输入字段有偏差。
以下简单布局可以重现这个问题:
<label for="phone">Phone: *</label>
<input type="tel" name="phone" id="phone" minlength="10" maxlength="10" inputmode="latin digits" required="required" />

解决方法:

-webkit-user-modify: read-write-plaintext-only
该属性会导致中文不能输入词组,只能单个字。另外,在position:fixed后的元素里,尽量不要使用输入框。依旧无法解决(摩托罗拉ME863手机),则使用input:text类型而非password类型,并设置其设置 -webkit-text-security: disc; 隐藏输入密码从而解决。

总结

每次各个不同内核的浏览器升级、android与ios的升级,都是一代版本一代坑。
移动端兼容(三)布局问题

原文始发于微信公众号(程序员思语):移动端兼容(三)布局问题