web移动端常见问题(一)

1.1物理像素

  • 产生原因:css样式的最小值是1px,不过这个1px只是代表css像素,在高清屏上展示的物理像素要>1(iphone6 1css像素=2物理像素。而iph6p则是1css像素=3物理像素)
  • 解决思路:想要展示1物理像素,只能使用scale缩放
  • android设备中dpr值有多种,可知的有0.75,1,1.5,1.75,2,2.5,2.75,3,4等

方法一:局部缩放
哪个元素要用到1物理像素,就设置哪个元素进行垂直方向的缩放。至于是缩放1/2还是1/3就看屏幕的DPR(物理像素与设备独立像素的比例值)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>时钟</title>
    <style>
        .box{
            padding: 20px;
        }
        .line{
            height: 1px;
            background-color: #000;
        }
        @media screen and (-webkit-device-pixel-ratio:2){
            .line{
                transform: scaleY(0.5)
            }
        }
        @media screen and (-webkit-device-pixel-ratio:3){
            .line{
                transform: scaleY(0.3333333)
            }
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="line"></div>
    </div>
    <div class="box">
        <div style="height: 1px;background-color: #000;margin-top: 50px;"></div>
    </div>
</body>
</html>

方法二:全局缩放
使用meta标签方法对全局所有元素进行缩放,但是会影响到所有的元素。需要缩放的元素使用px设置大小,而不需要缩放的元素使用rem设置大小,所以rem的值必须是缩放前2-3倍,这样才保证最终缩放值是1

<script>
    // 获取设备的dpr
    var dpr = window.devicePixelRatio
    // 计算缩放系数
    var scale = 1 / dpr
    // 获取meta viewport标签并设置相应的属性值
    var meta = document.createElement("meta")
    meta.name = "viewport"
    meta.content = "width=device-width,initial-scale=" + scale
    document.querySelector('head').appendChild(meta)

    // 设置html标签font-size的值
    var styleNode = document.createElement("style")
    // 计算根标签font-size的值 因为要缩放,所以1rem比常规要大
    var w = document.documentElement.clientWidth * dpr / 16
    styleNode.innerHTML = "html{font-size:"+ w +"px}"
    // 将style插入到head中
    document.querySelector('head').appendChild(styleNode)
</script>

效果对比:

2.自动识别手机号码

移动浏览器会自动将符合格式的文本识别为手机号码,并展示成一个a链接,点击后可以调用拨打电话的功能,例如
(有些浏览器默认就已经屏蔽了自动识别手机号码这个功能)

<p>18011757617</p>

如果想禁用这功能,需要添加meta标签,告诉浏览器不要识别此类文本

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

如果你想在页面中调用拨号或其他功能,可以这样设置

<body>
    <div><a href="tel:12306">买票热线</a></div>
    <div><a href="mailto:819251937@qq.com">发邮件给xxx</a></div>
    <div><a href="sms:10086">发短信给10086</a></div>
</body>

3.禁止复制、选中文本

移动端长按会选中文字,这是个默认事件

如果有需要的话,可以禁止这个功能。方法就是给元素设定css,让元素的文本无法被选中

.forbid_select{
    -webkit-user-select:none;
    -moz-user-select:none;
    -ms-user-select:none;
    user-select:none;   
}

如果全局都想禁止复制、选中文本,可以使用通配符所有标签都禁止选中文本,但是这样会让iOS的input框无法聚焦(用户可以点击input弹出输入窗口,但是输入框内没有焦点,无法输入文字),可以重新给input标签设置user-select属性为auto

注意:某些浏览器使用通配符会失效,例如alook浏览器,但是单独给某个div设置就可以

<head>
    <style>
        *{
            -webkit-user-select:none;
            -moz-user-select:none;
            -ms-user-select:none;
            user-select:none;   
        }
        input{-webkit-user-select:auto;}
    </style>
</head>

4.touch-callout

当在iOS上一直按住一个目标元素时,Safari会展示一个关于这个链接的callout信息。
例如长按图片时:

长按a链接时:

webkit-touch-callout属性允许禁用掉这一行为。

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

5.双击放大

在一些手机浏览器中,对一个元素进行双击会自动放大这个元素,这个设计本身可以方便用户查看他们点中的元素,但是有时候你想关闭这个效果时(例如游戏模拟器,你快速点击了按钮,会放大页面,导致无法正常游戏),下面给出解决办法:

注意:以下测试只在ios13的浏览器上通过,其他浏览器未能测试

1.行内元素双击不会放大,这个可以略过。

2.块级元素(div,p,h)的宽度达到屏幕宽度的90%以上时,双击不再放大

3.行内块元素和img/canvas这个元素的的宽度达到屏幕宽度的98%以上时,双击不再放大

除了上面的例子,还可以通过事件监听,屏蔽双击放大效果,例如:

//以下任选其一
dom.ontouchstart = function(){
   //无需阻止默认行为,只需要监听即可
}
dom.onclick = function(){
    e.preventDefault()
}
dom.ondblclick = function(e){
    e.preventDefault()
}

6.双指缩放

浏览器默认有一些手势缩放,例如双指缩放。可以通过事件屏蔽,阻止这种默认行为

为对应的dom元素添加touchmove事件监听,阻止默认事件之后,这这个元素的范围内不再有双指缩放行为。但是对顶层元素无效

document.documentElement.addEventListener('touchmove',function(e){
    //对顶层元素无效
    //在根元素上能触发事件打印,但是不能禁止双指缩放
    e.preventDefault()
})
document.querySelector('.box').addEventListener('touchmove',function(e){
    //能禁止元素的范围内的双指缩放
    e.preventDefault() 
    console.log('move')
})

如果想要让整个页面都禁止双指缩放,可以就需要为页面设置一个最外层的容器,然后把所有的元素放在这个容器里面(高度由内容撑开),在这个元素上监听并禁止默认事件即可。但是会产生一个问题:那就是无法拖动滚动条。如果一个页面有滚动条又想双指缩放,就需要进一步判断触点数量,当触点数量大于1时,禁止默认事件

document.querySelector('.box').addEventListener('touchmove',function(e){
    //屏幕内触点数量大于1时禁止元素的范围内的双指缩放
    if(e.touches.length > 1){
        e.preventDefault()
    } 
    console.log('move')
})

但是仍有一个小问题,当页面滚动时,一些浏览器仍然可以双指缩放(有些浏览器页面到顶或者到底了仍然可以继续滑动,会有一个回弹效果,甚至有下拉自动加载的设定,当然这只是某些浏览器本身设定的问题,不代表所有的浏览器都这样)

通过判断触点数量已经足够屏蔽双指缩放了,如果连这点小毛病都不能忍受,只能往下看了
我们分析下原因:当我们单个手指进行上下滑动时,因为没有对单手指操作的touchmove事件进行'阻止默认事件',导致页面滚动条发生了滚动。在页面滚动的过程中,用户可以进行双指缩放。我们无法禁止这种默认行为,只能通过一些方法避免页面滚动条的滚动。

这里给出一个解决思路:
(1)既然页面滚动条会出现这样的事件,那就不使用页面的滚动跳,转而使用box元素自己的滚动条

.box{
    height: 100%;
    overflow: auto;
}

(2)在为box容器设定固定的宽高后,在这个容器上面滑动时,默认滑动的是box元素的滚动条,此时页面滚动条不会有反应。但是box元素的滚动条到顶或者到底后,接着强行滑动,某些浏览器就会操作页面的滚动条(IOS13火狐),为了阻止这种行为,需要对滚动条的距离与滑动方向进行判断,符合条件则禁止默认行为

<script>
    function preventScale(node){
        var x0 = null
        var direction = null
        //监听start事件 记录x0的位置
        node.addEventListener('touchstart',function(e){
            x0 = e.changedTouches[0].screenY
        })
        //监听move事件
        node.addEventListener('touchmove',function(e){
            //更新方向信息
            (e.changedTouches[0].screenY - x0 > 0) ? direction='down' : direction='up'
            //console.log(direction)
            //console.log(node.scrollTop)
            if(e.touches.length > 1){
                //双指则禁止默认事件
                e.preventDefault()
            }else{
                //到顶且下滑时 禁止默认事件
                if(node.scrollTop <= 0 && direction === 'down'){
                    console.log('已经到顶,不要再下滑')
                    e.preventDefault()
                }
                console.log(node.scrollHeight)
                var max = node.scrollHeight - node.offsetHeight
                //到底且上滑时 禁止默认事件
                if(node.scrollTop >= max && direction === 'up'){
                    console.log('已经到底,不要再上滑')
                    e.preventDefault()
                }
            }
            console.log('box move')
        })
    }
    preventScale(document.querySelector('.box'))

</script>

7.按钮圆角过圆

每个浏览器默认的元素样式是有差异的,比如苹果手机中为了美化按钮,默认给按钮添加了圆角,例如

<body>
    <button>我是button元素</button>
    <input type="button" value="我是input[type=button]元素">
</body>

解决办法:设置appearance属性为none,另外苹果的浏览器默认input元素都有圆角,需要手动去除

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

实际项目中不会用到原生的按钮,因为太丑,一般会搭配UI框架,所以这里了解即可。

8.字体增强 font boosting

这个特性被称做「Text Autosizer」,又称「Font Boosting」、「Font Inflation」,是 Webkit 给移动端浏览器提供的一个特性。
当我们在手机上浏览网页时,很可能因为原始页面宽度较大,为了在手机屏幕中完整的显示整个页面,就会把页面缩小。(参见布局视口,一般默认980px)
但是页面是显示完整了,但是里面的内容却因为缩小了而看不清。
而 Font Boosting 特性在这时会自动将其中的文字字体变大,让人们方便的阅读页面中的文本。

解决办法一:设置完美视口,不让页面缩放,自然就不会有 font boosting

<meta name="viewport" content="width=device-width,initial-scale=1.0">

解决办法二:设置max-height

<style>
    p{
        max-height: 9999px;
    }
</style>

9.点击高亮

在移动端,点击可点击元素时(a,button),android下会出现淡蓝色背景,IOS下会出现灰色背景
可以通过-webkt-tap-hightlight-color属性的设置,取消点击时出现的背景效果

*{
    -webkit-tap-highlight-color: transparent;
}

10.滚动回弹

-webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果,页面的滚动条默认就是回弹的效果,如果不想要滚动回弹的效果,需要进行设置

div{
    height: 300px;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
}

这个css属性有2个值:
auto:使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止(默认)
touch:使用具有回弹效果的滚动

不同的浏览器对不同元素的默认效果不一样,chrome的手机模式默认div是没有滚动回弹的,但是真机上面有。

posted @ 2019-10-03 00:19  ---空白---  阅读(513)  评论(0编辑  收藏  举报