移动端适配
1px边框的问题
伪类 + transform:基于media查询判断不同的设备像素比对线条进行缩放
.border_1px:before{
content: '';
position: absolute;
top: 0;
height: 1px;
width: 100%;
background-color: #000;
transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
.border_1px:before{
transform: scaleY(0.5);
}
}
@media only screen and (-webkit-min-device-pixel-ratio:3){
.border_1px:before{
transform: scaleY(0.33);
}
}
关于横屏
js识别
window.addEventListener("resize", ()=>{
if (window.orientation === 180 || window.orientation === 0) {
// 正常方向或屏幕旋转180度
console.log('竖屏');
};
if (window.orientation === 90 || window.orientation === -90 ){
// 屏幕顺时钟旋转90度或屏幕逆时针旋转90度
console.log('横屏');
}
});
css识别
@media screen and (orientation: portrait) {
/*竖屏...*/
}
@media screen and (orientation: landscape) {
/*横屏...*/
}
图片模糊问题
media查询:只适用于背景图,使用media查询判断不同的设备像素比来显示不同精度的图片
.avatar{
background-image: url(conardLi_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
.avatar{
background-image: url(conardLi_2x.png);
}
}
@media only screen and (-webkit-min-device-pixel-ratio:3){
.avatar{
background-image: url(conardLi_3x.png);
}
}
使用image-set:只适用于背景图
.avatar {
background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}
srcset:使用img标签的srcset属性,浏览器会自动根据像素密度匹配最佳显示图片:
<img src="conardLi_1x.png" srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">
JavaScript拼接图片url:使用window.devicePixelRatio获取设备像素比,遍历所有图片,替换图片地址:
const dpr = window.devicePixelRatio;
const images = document.querySelectorAll('img');
images.forEach((img)=>{
img.src.replace(".", `@${dpr}x.`);
})
使用svg:SVG的全称是可缩放矢量图,不同于位图的基于像素,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。除了我们手动在代码中绘制svg,我们还可以像使用位图一样使用svg图片:
<img src="conardLi.svg">
<img src="data:image/svg+xml;base64,[data]">
.avatar {
background: url(conardLi.svg);
}
ios滑动不流畅
1.在滚动容器上增加滚动 touch 方法:将-webkit-overflow-scrolling 值设置为 touch
.wrapper {
-webkit-overflow-scrolling: touch;
}
设置滚动条隐藏: .container ::-webkit-scrollbar {display: none;}
可能会导致使用position:fixed; 固定定位的元素,随着页面一起滚动
2.设置 overflow:设置外部 overflow 为 hidden,设置内容元素 overflow 为 auto。内部元素超出 body 即产生滚动,超出的部分 body 隐藏。
body {
overflow-y: hidden;
}
.wrapper {
overflow-y: auto;
}
两者结合使用更佳
iOS 上拉边界下拉出现白色空白
1. 监听事件禁止滑动:移动端触摸事件有三个,分别定义为
1. touchstart :手指放在一个DOM元素上。
2. touchmove :手指拖曳一个DOM元素。
3. touchend :手指从一个DOM元素上移开。
显然我们需要控制的是 touchmove 事件
touchmove 事件的速度是可以实现定义的,取决于硬件性能和其他实现细节
preventDefault 方法,阻止同一触点上所有默认行为,比如滚动。
由此我们找到解决方案,通过监听 touchmove,让需要滑动的地方滑动,不需要滑动的地方禁止滑动。
实现如下:
document.body.addEventListener('touchmove', function(e) {
if(e._isScroller) return;
// 阻止默认事件
e.preventDefault();
}, {
passive: false
});
页面放大或缩小不确定性行为
HTML meta 元标签标准中有个 中 viewport 属性,用来控制页面的缩放,一般用于移动端。
因此我们可以设置 maximum-scale、minimum-scale 与 user-scalable=no 用来避免这个问题
<meta name=viewport content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no">
阻止页面放大(meta不起作用时)
window.addEventListener(
"touchmove",
function (event) {
if (event.scale !== 1) {
event.preventDefault();
}
},
{ passive: false }
);
click 点击事件延时与穿透
使用 touchstart 替换 click
在原生中使用
el.addEventListener("touchstart", () => { console.log("ok"); }, false);
在 vue 中使用
<button @touchstart="handleTouchstart()">点击</button>
软键盘将页面顶起来、收起未回落问题
方案1:监听input失焦事件,失焦即回落
/iphone|ipod|ipad/i.test(navigator.appVersion) && document.addEventListener(
"blur", (event) => {
// 当页面没出现滚动条时才执行,因为有滚动条时,不会出现这问题
// input textarea 标签才执行,因为 a 等标签也会触发 blur 事件
if (
document.documentElement.offsetHeight <= document.documentElement.clientHeight &&
["input", "textarea"].includes(event.target.localName)
) {
document.body.scrollIntoView(); // 回顶部
}
},
true
);
方案2:软键盘将页面顶起来的解决方案,主要是通过监听页面高度变化,强制恢复成弹出前的高度。
//这里应该改成style,height属性 // 记录原有的视口高度
const originalHeight = document.body.clientHeight || document.documentElement.clientHeight;
window.onresize = function(){
var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if(resizeHeight < originalHeight ){
// 恢复内容区域高度
// const container = document.getElementById("container")
// 例如 container.style.height = originalHeight;
}
}
键盘不能回落问题出现在 iOS 12+ 和 wechat 6.7.4+ 中,而在微信 H5 开发中是比较常见的 Bug。
兼容原理,1.判断版本类型 2.更改滚动的可视区域
const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);
if (!isWechat) return;
const wechatVersion = wechatInfo[1];
const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
// 如果设备类型为iOS 12+ 和wechat 6.7.4+,恢复成原来的视口
if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) {
window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));
}
window.scrollTo(x-coord, y-coord),其中window.scrollTo(0, clientHeight)恢复成原来的视口
页面高度设定为100vh 高度出现的问题
3.在vue项目里使用
<style lang="scss" scoped>
.container {
height: 100vh; /* 在之前设置为100vh,可以兼容某些不支持自定义属性的浏览器。*/
height: calc(var(--vh, 1vh) * 100 - 46px);
</style>
mounted() {
let vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh}px`)
window.addEventListener('resize', () => {
let vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh}px`)
})
},
完美解决办法:
<template>
<div class="module">
<div class="module__item">20%</div>
<div class="module__item">40%</div>
<div class="module__item">60%</div>
<div class="module__item">80%</div>
<div class="module__item">100%</div>
</div>
</template>
<script>
export default {
mounted() {
const vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh}px`)
window.addEventListener('resize', () => {
const vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh}px`)
})
}
}
</script>
<style>
body {
background-color: #333;
}
.module {
height: 100vh; /* Use vh as a fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
margin: 0 auto;
max-width: 30%;
}
.module__item {
align-items: center;
display: flex;
height: 20%;
justify-content: center;
}
.module__item:nth-child(odd) {
background-color: #fff;
color: #f73859;
}
.module__item:nth-child(even) {
background-color: #f73859;
color: #f1d08a;
}
</style>
!!

浙公网安备 33010602011771号