个人博客

A web front-end programmer's personal blog.

一些移动端遇到的问题汇总

Q1: IOS中阻止当页面滚动到顶部或底部时页面整体滚动

IOS中浏览页面当页面滚动到顶部或底部时继续滚动会将整个页面滑动,阻止这种效果可以使用下面的函数,参数为最外层容器的选择器

preventPageScroll('.container');
function preventPageScroll(id){
    var el = document.querySelector(id);
    var sy = 0;
    el.addEventListener('touchstart', function (e) {
      sy = e.pageY;
    });
    el.addEventListener('touchmove', function (e) {
      var down = (e.pageY - sy > 0);
      //top
      if (down && el.scrollTop <= 0) {
        e.preventDefault();
      }
      //bottom
      if (!down && el.scrollTop >= el.scrollHeight - el.clientHeight) {
        e.preventDefault();
      }
    });
}

Q2: 使用zepto常见的点透问题

对于点透问题有以下方案可供解决参考

  1. 引入fastclick.js,源码地址,使用参考github

  2. 使用touchend代替tap,并阻止掉默认行为

     $(dom).on('touchend',function(ev){
         // to doing
         ev.preventDefault();
     });
    
  3. chrome Android 通过设置 viewport 的 user-scalable=no 可以阻止掉页面的300ms的延时

  4. 延迟一定时间(300ms+)处理

     $(dom).on('tap',function(){
        setTimeout(function(){
            // to doing
        },320)
     });
    

Q3:获取窗口宽度

获取窗口宽度有以下一些方法(这里假设已经将样式 reset):

  • window.innerWidth
  • document.body.clientWidth
  • document.body.offsetWidth

zepto中有

  • $(window).width()
  • $(document).width()

曾经遇到过在页面第一次打开时 window 和 document 获取的width 是相同的,但是当再次刷新页面时获取的两个宽度却不再相同,所以为了避免出现样式错乱,尽量使用 document 获取 width

Q4: Android部分机型中给img设置border-radius失效

radius

解决给img外嵌一个元素

//结构
<div>
    <img src="">
</div>
//样式
div{
    display: inline-block;
    border-radius: 50%;
    border: 4px solid #FF7000;
}
img{
    vertical-align: top;
}

Q5: 部分机型中圆角元素,背景颜色会溢出

border-radius

解决给该元素添加下面样式

//
{background-clip:padding-box;}

Q6:圆角使用Animation 做loading动画时,圆角背景溢出

radius-animation

解决使用一个同等大小的圆角图片做蒙版遮罩

//
{
	background-color: #F9CEAC;
    border-radius: 32px 0 0 32px;
    -webkit-mask-image: url(./image/btn_mask.png);
}

蒙版图片btn_mask

Q7: CSS 三角在 Android 上显示为方块

解决:可能是对这个三角使用了圆角,去掉 border-radius 即可

//
{
    border: 10px solid transparent;
    border-left-color: #000;
    /*border-radius: 2px;*/
}

Q8:Android 上使用 svg 作为 background-image 时显示模糊

解决:设置 background-size

//
{
    -webkit-background-size: 100%;
    background-size: 100%;
}

Q9: IOS中 :active 样式不生效

Safari 默认禁用了元素的 active 样式,我们通过声明 touchstart 来覆盖默认事件,就可以让 active 样式重新激活。

解决:

document.addEventListener("touchstart", function() {},false);
//或者 body标签添加 ontouchstart
<body ontouchstart="">

此外,默认点击按钮会有一个灰色的外框,通过这段 CSS 可以清除:

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

Q10: 多行文字超出截断需要出现省略号方法

单行文本截断并末尾出现省略号一般写法是:

//
{
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

多行文版截断并出现省略号的纯CSS方法,其中的 -webkit-line-clamp: 2 即用来控制文本超出两行时截断并出现省略号。 在使用中如果出现第三行文字露一点头出来的问题,设置合理的 line-height 即可解决

//
{
    display: -webkit-box;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

Q11: 1px 线条、边框

在高版本设备中可以直接设置 0.5px 边框,但底版不能友好支持,一个比较合适的方法:原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transformscale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。

  • 单条 border

      .hairlines li{
          position: relative;
          border:none;
      }
      .hairlines li:after{
          content: '';
          position: absolute;
          left: 0;
          background: #000;
          width: 100%;
          height: 1px;
          -webkit-transform: scaleY(0.5);
                  transform: scaleY(0.5);
          -webkit-transform-origin: 0 0;
                  transform-origin: 0 0;
      }
    
  • 四条 border

      .hairlines li{
          position: relative;
          margin-bottom: 20px;
          border:none;
      }
      .hairlines li:after{
          content: '';
          position: absolute;
          top: 0;
          left: 0;
          border: 1px solid #000;
          -webkit-box-sizing: border-box;
          box-sizing: border-box;
          width: 200%;
          height: 200%;
          -webkit-transform: scale(0.5);
          transform: scale(0.5);
          -webkit-transform-origin: left top;
          transform-origin: left top;
      }
    

样式使用的时候,也要结合 JS 代码,判断是否 Retina 屏

if(window.devicePixelRatio && devicePixelRatio >= 2){
    document.querySelector('ul').className = 'hairlines';
}

更多请参考这篇文章

Q12: 当模块使用系统的横向滚动时,不想显示出系统的滚动条样式

解决:

  • Android

      ::-webkit-scrollbar{ opacity: 0; }
    
  • Ios

      //html
      <div class="wrap">
          <div class="box"></div>
      </div>
      //css
      .wrap{ height: 100px; overflow: hidden; }
      .box{ width: 100%; height: -webkit-calc(100% + 5px); overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
    

原理:.box 元素的横向滚动条通过其外层元素 .wrapoverflow:hiden 来隐藏。 (5px 是 iOS 上滚动条元素的高度)

Q13:横向滚动的元素,滑动时有时图片显示不出来/文字显示不出来

解决:给每个横滑的元素块使用硬件加速

li{ -webkit-transform: translateZ(0); }

Q14:使用 animation 动画后,页面上 overflow:auto 的元素滚动条不能滑动

解决:不使用 translate 方式的动画,换为使用 left/top 来实现元素移动的动画

Q15:上下滑动页面时候,页面元素消失

解决:检查是否使用了 fadeIn 的 animation,如有则 fill-mode 使用 backwards 模式

//
{ -webkit-animation: fadeIn 0.5s ease backwards; }

Q16: 页面上数字自动变成了可以点击的链接

解决:在页面 <head> 里添加

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

Q17:input 在 iOS 中圆角、内阴影去不掉

解决:

input{ -webkit-appearance: none; border-radius: 0; }

Q18:焦点在 input 时,placeholder 没有隐藏

解决:

input:focus::-webkit-input-placeholder{ opacity: 0;}

Q19:input 输入框调出数字输入键盘

解决:

<input type="number" />
<input type="number" pattern="[0-9]*" />
<input type="tel" />

分别对应下图的1、2、3 keyboard_number

需要注意的是,单独使用 type=”number” 时候, iOS 上出现并不是九宫格的数字键盘,如果需要九宫格的数字键盘,可选择使用 2、3 的方法。 1、2、3 在 Android 上均可以唤起九宫格的数字键盘

Q20: rem单位动态设置fontSize

(function (doc, win) {
    var _root = doc.documentElement,
        resizeEvent = 'orientationchange' in window ? 'orientationchange' : 'resize',
        resizeCallback = function () {
            var clientWidth = _root.clientWidth,
                fontSize = 50;
            if (!clientWidth) return;
            if(clientWidth < 750) {
                fontSize = 50 * (clientWidth / 375);
            } else {
                fontSize = 50 * (750 / 375);
            }
            _root.style.fontSize = fontSize + 'px';
        };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvent, resizeCallback, false);
    doc.addEventListener('DOMContentLoaded', resizeCallback, false);
})(document, window);