1. 程式人生 > >移動端爬坑記 --- (1)佈局與樣式上的奇葩偶遇

移動端爬坑記 --- (1)佈局與樣式上的奇葩偶遇

前言

彙總下自己搞移動端遇到掉進去的坑,以及脫坑的方案;

Flex相容

Flex想要相容眾多花樣式手機,要注意以下這麼些

  • 字首要考慮2009~2012年的語法[webkit-box,flex,flex-box]
  • 少用複合屬性,比如flex:1,考慮相容理應拆成[flex-grow,flex-shrink,flex-basis];flex-flow拆開成[flex-direction,flex-wrap]
   demo{
          display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
          display
: -moz-box
; /* OLD - Firefox 19- (buggy but mostly works) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ }

這些字首很少手動去寫,一般都用構建工具處理,我用的是gulp+autoprefixer來處理,這裡我的處理範圍

var AUTOPREFIXER_BROWSERS = [
  'ie >= 9',
  'ie_mob >= 9',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 2.3',
  'bb >= 10'
];

值的一提的是,新增字首並不是萬能的,有些國內的手機就不吃這一套了,今天小夥伴就遇到了;華為的一款手機不支援常規的flex寫法。。。最終是原因是不能用行內元素,要改成block元素才能支援flex

2016-8-11 update: 使用flex:1的子元素,切記要增加width:0% .. 有些android不帶這個很奇葩【錯亂】,且不要使用margin:0 auto【作用於子元素】

IOS的H5頁面scroll不流暢解決方案

在滾動包裹層新增這麼一條私有字首樣式即可享受類似APP的滑動效果,不僅絲滑,還帶彈性!

   .contain{
    -webkit-overflow-scrolling : touch;    
    }

IOS 遮罩層較好方案

拒絕採用fixed!!!!!

遮罩層採用position:absolute來置頂,內部元素採用flex來佈局;
這種寫法可以避免一大堆天坑!!!

若是實在不信邪,滾動的時候,微信端這些你就會感受到花兒為什麼這樣紅了。。。

IOS滾動窗滑動到底部還能彈窗拖拉的奇葩修復

這個方案是通過計算離底部多遠加狀態來阻止touch事件

// 防止內容區域滾到底後引起頁面整體的滾動
var content = document.querySelector('main');
var startY;

content.addEventListener('touchstart', function (e) {
    startY = e.touches[0].clientY;
});

content.addEventListener('touchmove', function (e) {
    // 高位表示向上滾動
    // 底位表示向下滾動
    // 1容許 0禁止
    var status = '11';
    var ele = this;

    var currentY = e.touches[0].clientY;

    if (ele.scrollTop === 0) {
        // 如果內容小於容器則同時禁止上下滾動
        status = ele.offsetHeight >= ele.scrollHeight ? '00' : '01';
    } else if (ele.scrollTop + ele.offsetHeight >= ele.scrollHeight) {
        // 已經滾到底部了只能向上滾動
        status = '10';
    }

    if (status != '11') {
        // 判斷當前的滾動方向
        var direction = currentY - startY > 0 ? '10' : '01';
        // 操作方向和當前允許狀態求與運算,運算結果為0,就說明不允許該方向滾動,則禁止預設事件,阻止滾動
        if (!(parseInt(status, 2) & parseInt(direction, 2))) {
            e.preventDefault();
            stopEvent(e);
        }
    }
});

ios和android下觸控元素時出現半透明灰色遮罩

   /*E:這個是代指字元,實際自己替換,ID,CLASS,TAG*/
   -webkit-tap-highlight-color:rgba(255,255,255,0)

IOS 預設輸入框內陰影重置

   /*E:這個是代指字元,實際自己替換,ID,CLASS,TAG*/
   E{
     border: 0;  
     -webkit-appearance: none; 
  }

旋轉螢幕時,字型大小調整的問題

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

預設啟用GPU渲染頁面

這個具體要看你的實際作用範圍,無非就通過一些特殊屬性來強制開啟
- transform:translateZ(0): Z軸會啟用GPU,請自行帶字首
- 呼叫preserve-3d或者animation也會

transition閃屏

/設定內嵌的元素在 3D 空間如何呈現:保留3D /
-webkit-transform-style: preserve-3d;
/ 設定進行轉換的元素的背面在面對使用者時是否可見:隱藏 /
-webkit-backface-visibility:hidden;

placeholder的顏色值改變

input::-webkit-input-placeholder{color:#F40;}
input:focus::-webkit-input-placeholder{color:#F40;}

移動端禁止選中內容

E {
  -webkit-user-select: none;  /* Chrome all / Safari all */
  -moz-user-select: none;     /* Firefox all (移動端不需要) */
  -ms-user-select: none;      /* IE 10+ */      
}

IOS禁止儲存或拷貝影象

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

常用的移動端meta

<!-- 禁止頁面縮放 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />

<!-- 設定Web應用是否以全屏模式執行。-->
<meta name="apple-mobile-web-app-capable" content="yes">

<!-- 啟動或禁用自動識別頁面中的電話號碼。-->
<meta name="format-detection" content="telephone=no">

<!-- 設定快取,看實際需求設定 -->
<meta http-equiv="Cache-Control" content="no-cache" />

<!-- 優先使用最新版本 IE 和 Chrome-->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> 

<!-- QQ瀏覽器私有 -->
<!-- 全屏模式 -->
<meta name="x5-fullscreen" content="true">
<!-- 強制豎屏 -->
<meta name="x5-orientation" content="portrait">
<!-- 強制橫屏 -->
<meta name="x5-orientation" content="landscape">
<!-- 應用模式 -->
<meta name="x5-page-mode" content="app">

<!-- UC瀏覽器私有 -->
<!-- 全屏模式 -->
<meta name="full-screen" content="yes">
<!-- 強制豎屏 -->
<meta name="screen-orientation" content="portrait">
<!-- 強制橫屏 -->
<meta name="screen-orientation" content="landscape">
<!-- 應用模式 -->
<meta name="browsermode" content="application">

IOS中input鍵盤事件呼叫緩慢

直接改為監聽input事件

    document.getElementById('test').addEventListener('input',fn,false);

頁面高度渲染錯誤

document.documentElement.style.height = window.innerHeight + 'px';

怪異懸浮的表單

在部分android 機型中的輸入框可能會出現如圖怪異的多餘的浮出表單,經過觀察與測試發現只有input:password型別的輸入框存在,那麼我們只要使用input:text型別的輸入框並通過樣式-webkit-text-security: disc; 隱藏輸入密碼從而解決。

   input[type=text]{
    -webkit-text-security: disc;
   }

其他一些建議

  • 能用transform實現的過渡的,可以不考慮animation實現;animation在部分機子過渡非常掉幀,體驗非常糟糕,,遇到過好幾次
  • 頁面有滾動區域的建議引入iscroll5,可以避免很多天坑
  • 頁面應該儘可能的減少複雜的DOM【一個功能點,DOM結構越直白,越好維護】,複雜DOM會增加維護難度
  • 考慮移動端響應佈局,建議引入阿里巴巴出品的lib-flexible , IOS動態調整DPR,其他裝置預設DPR1
  • 點透事件可以引入fastclick或者不用click,改為touch來寫,亦或者引入zepto的tap事件

若是以後還有遇到哪些奇葩坑,爬出來了會繼續更新此帖子