活动/业务/h5兼容性问题以及css、js常用设置

197 阅读9分钟

h5兼容性问题

1、移动端input总结

ios13.1 input错位问题

cloud.tencent.com/developer/a…

结论:最简单的方法,input聚焦的时候

    window.scrollTop(0)

input 样式字体上下居中问题

设计师给的input样式通常都是外框高,输入的内容区域低,要求输入的内容区域在input上下居中。 比如如下图片: image.png

第一种方法,给input添加个父元素(推荐)

如图,蓝色框为div,红色框为input image.png

第二种方法,针对不同系统改样式

红色框一整个都为input image.png 对于placeholder样式,在ios端它的字体不会上下居中,而android会。所以要针对ios做特殊的处理,可以设置line-height来进行微调,以达到居中效果。也可以设置padding- top进行微调,但是有可能字体会被遮挡。

经过真机测试,line-heightpadding-top::placeholder 的设置只有ios生效。

input::placeholder {
      line-height:36px;  
      /*或者*/
      padding-top: 10px;
 }

对于input输入文字后,文字的样式同样在ios端它的字体不会上下居中,而android会。可以针对ios设置padding-top进行微调。注意设置line-height是无效的

input {
      padding-top: 10px; 
 }

input唤起与隐藏细节总结

1、自动聚焦

点击非input元素,让input元素聚焦的关键是 有点击事件,而且input元素在点击发生前就需要存在于dom树下。故此input可以用visible或者z-index来设置隐藏。

2、弹出系统输入框不遮盖输入框上面的元素

输入框元素与上面不想被遮盖的元素是兄弟节点,且两个元素的position != fixed || absolute

 <div class="wrapper">
    <div class="zone1"></div>
    <input  type="text">
    <div class="showInput"></div>
 </div>
 当点击showInput的时候,showInput隐藏,input从z-index=-1 变成z-index=1。

3、通过监听onBlur事件来让输入框隐藏

注意:

1、如果发送按钮是跟输入框一同消失与出现,则onBlur里面设置让input隐藏的代码要延迟300毫秒,再执行。保证发送按钮的事件能够触发。

2、在IOS上,输入中文拼音后(未选择文字)直接触发input的blur事件,此时输入键盘关闭,当再次唤起输入键盘时,会先触发input的blur事件,再触发focus事件。这里会导致的问题就是1所设置的延迟300毫秒会触发,表现为输入键盘弹起了,但是你的输入框被你隐藏了。解决的方法当想要唤起输入键盘时,清除1所设置的延迟函数。

4、自定义input框会概率性隐藏

通过函数触发自定义input组件(position:absolute; bottom: 0)的focus方法来唤起键盘,在ios上如果来回重复关闭与隐藏输入键盘,会概率性出现自定义input组件没有被输入键盘顶上去,而是被藏在输入键盘的后面。

限制输入只能为数字且限制长度

<input
className={cs.inputCode_input}
type="text"
pattern="[0-9]*"
autoComplete="one-time-code"
inputMode="numeric"
maxLength={6}
/>

解决方法是:

自定义input组件的input元素的value必须含有值。

  1. 当自定义input框隐藏时,给input的value设置为空格。
  2. 当自定义input框显示时, 如果input的value原本是空格,则清空。
  3. 当自定义input框触发发送按钮时,将input的value设置为空格。

2、canvas的坑

在移动端ios上,canvas的渲染区域的前面如果有元素,当页面是可以滚动且canvas是在顶部的时候,因为ios的渲染机制会导致canvas在视觉效果上覆盖掉元素。

    解决方法:
    transform: translateZ(0);//给元素添加,通过硬件加速让元素优先级高于canvas

3、点击div元素有阴影

解决方案

transform: translate3d(0,0,0);

4、ios滚动吸底元素抖动

原因: 如果滚动区域也就是元素设置了overflow-y: scroll;吸底元素是滚动区域的子节点,则会出现抖动。

解决方法: 滚动区域与吸底元素同为兄弟节点,或者吸底元素不是滚动区域的的子节点

5、vh存在的问题

image.png vh 存在问题?试试动态视口单位之 dvh、svh、lvh

6、ios下拉刷新

在一些设备上,ios下拉刷新整个页面,出现顶部间距展示异常情况。 image.png 解决方法

组件渲染完成后执行一次如下方法
  useEffect(() => {
    setTimeout(() => {
      window.scrollTo({
        top: 1,
        left: 0,
        behavior: 'smooth',
      })
    }, 100);
  }, [])

7、ios图片没有渲染问题

在一些ios设备上,图片通过transfrom使用硬件加速也没有渲染出来,可以改通过动画的方式强制启用。

.wrapper {
  position: relative;
  width: 100%;
  animation: forceRender  0.05s ease 0s;
}
@keyframes forceRender {
  0% {
    transform: translateX(1px);
  }
  100% {
    transform: translateX(0);
  }
}

8、弹框后阻止后面的元素滚动

背景

h5项目在移动端上如果弹窗后,滑动弹窗后,弹窗后面的元素也会滚动。

解决方法1(touchmove)

当弹窗出现的时候,给body设置事件,禁止默认事件的触发,弹窗消失则消除事件。react代码如下:

  useEffect(() => {
    const handleMove = e => {
      e.preventDefault()
    }
    document.body.addEventListener('touchmove', handleMove, {
      passive: false,  // 一定要设置passive: false
    })
    return () => {
      document.body.setAttribute('style', style)
      document.body.removeEventListener('touchmove', handleMove)
    }
  }, [])

缺陷:如果弹窗内容有滚动元素,会导致无法滚动。

解决方法2(overhidden)

当弹窗出现的时候,给body设置style,height = '100vh'、overflow = 'hidden',弹窗消失则恢复原样。react代码如下:

  useEffect(() => {
    const style = document.body.getAttribute('style') || ''
    document.body.style.height = '100vh'
    document.body.style.overflow = 'hidden'
    return () => {
      document.body.setAttribute('style', style)
    }
  }, [])

缺陷:ios设备无效。

解决方法3(同级结构fixed)

弹窗元素与弹窗后面的元素在html的结构上是同一层级。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    .one {
      position: relative;
      width: 100vw;
      height: 200vh;
      background: linear-gradient(blue, pink);
      color: white;
    }
    .two {
      position: fixed;
      top: 0;
      width: 100vw;
      height: 100vh;
      background-color: black;
      overflow-x: scroll;
      opacity: 0.5;
    }
    .three {
      position: relative;
      height: 200vh;
      background: linear-gradient(yellow, green);
    }
  </style>
</head>
<body>
  <div class="one">
    可以明显看到,one并没有滚动
  </div>
  <div class="two">
    <div class="three">

    </div>
  </div>
</body>
<script>
</script>
</html>

css常用设置

1、backgroun-image与img的区别

  1. backgroun-image不能同时设置宽高与object-fit,img可以。这意味着h5的大背景图(底板)不能用backgroun-image来适配,否则会变形

2、文字描边效果

有两种css属性:

第一种:支持数字与英文
-webkit-text-stroke: 2px #E1FF37;
text-stroke: 2px #E1FF37;

第二种:支持数字、英文与中文
text-shadow: 0 2px #e1ff37, 2px 0 #e1ff37, -2px 0 #e1ff37, 0 -2px #e1ff37;

3、css设置省略号

单行省略号

white-space: nowrap;
max-width: 250px;
overflow: hidden;
text-overflow: ellipsis;

多行省略号

display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
word-break: break-all;   // 设置文字切断的方式为强制切断
text-overflow: ellipsis;
width: 100px;

4、滚动-禁止页面滚动

  1. 使用js方法:

  2. 使用css的pointer-events方法解决

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div class="scroll">
        <div class="scrollContent"></div>
    </div>
    <div class="dialog"></div>
</body>

</html>
<style>
    .scroll {
        position: absolute;
        width: 100vw;
        height: 100vh;
        background-color: aqua;
        overflow-y: scroll; 
        overflow-x: hidden;
        pointer-events: none;
    }
    .scrollContent {
        position: absolute;
        width: 100vw;
        height: 200vh;
        background:linear-gradient(red,blue);
    }
</style>
<script>
export let scrollHandle = {
    dom: {
        el: null,
        style: '',
    },
    // 给dom元素的style基础上添加pointer-events,停止滚动
    stopMove() {
        let { el, style } = this.dom;
        el.setAttribute('style', style + '; pointer-events: none;');
    },
    // 初始化返回原来的dom的样式
    reset() {
        let { el, style } = this.dom;
        el.setAttribute('style', style);
    },
    init(dom){
        this.dom.el = dom;
        this.dom.style = dom.getAttribute('style') ? dom.getAttribute('style') : '';
    }
}
</script>

核心关键是:

  1. overflow-ypointer-events要同时在一个元素上。
  2. 当dialog弹出来的时候,给srcoll设置pointer-events: none;
  3. dialog与pointer-events元素为兄弟元素,因为pointer-events会把里面所有的dom事件全部无效后。

5、滚动-移动端隐藏滚动条

*::-webkit-scrollbar {
  display: none; /* 不显示滚动条 */
}

/*滚动元素,需要设置scroll才能隐藏*/
.scorllEle{
  position: absolute;
  width: 100vw;
  height: 100vh;
  overflow-x: hidden;
  overflow-y: scroll;
}

6、滚动-定义滚动条样式

/*css主要部分的样式*/
/*定义滚动条宽高及背景,宽高分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
    width10px/*对垂直流动条有效*/
    height10px/*对水平流动条有效*/
    display: none; /* 不显示滚动条 */
}
/*定义滚动条的轨道颜色、内阴影及圆角*/
::-webkit-scrollbar-track{
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
    background-color: rosybrown;
    border-radius3px;
}
/*定义滑块颜色、内阴影及圆角*/
::-webkit-scrollbar-thumb{
    border-radius7px;
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
    background-color#E8E8E8;
}
/*定义两端按钮的样式*/
::-webkit-scrollbar-button {
    background-color:cyan;
}
/*定义右下角汇合处的样式*/
::-webkit-scrollbar-corner {
    background:khaki;
}

7、设置父dom根据多个子dom自动变宽

.father {
     display: inline-block;
     white-space: nowrap;   //这个很关键,没有设置这个的话,如果超过屏幕宽度则自动换行,导致dom没有自动变宽。
}
.son {
     display: inline-block;
     white-space: nowrap;
}

8、取消ios橡皮筋效果

方法1:设置元素position:fixed;

方法2:

html,
body {
	width: 100%;
	height: 100%;
	overflow: hidden;
}

9、设置图片无法被长按选中与保存

img {
 user-select: none;
 pointer-events: none;
}

10、设置图片与文字一起上下居中

即使文字换行也是哦

.imWrapper {
  position: relative;
  width: 520px;
  border-radius: 29px;
  background-color: rgba(0, 0, 0, 0.3);
  padding:8px 20px;
  box-sizing: border-box;
  margin-bottom: 10px;

  img {
    width: auto;
    height: auto;
    vertical-align: middle;
    margin-right: 8px;
  }
  span {
    vertical-align: middle;
  }
}

<div class='imWrappe'>
<img src='a.png' alt="" />
 <span>哈哈哈哈哈哈哈哈哈哈哈哈哈</span>     
</div>

11、css跑马灯

挑战全网 「跑马灯」最简单实现,欢迎来Battle!

12、css设置c元素自适应父元素剩余高度

a、b元素固定高度、c元素自适应剩余高度。c元素的子内容能够滚动。

.father {
  position: absolute;
  width: 100%;
  height: 100%;
  
  display: flex;
  flex-direction: column;
  align-items: center;
    .a,.b {
        position: relative;
        width: 100%;
        min-height: 118px;
    }
    .c {
        position: relative;
        width: 100%;
        border:20px solid black;
        flex: 1;
        overflow-y: scroll;
        .cLongContent {
          position: relative;
          height: 200vh;
          background: linear-gradient(to bottom, #ff0000, #0000ff);
        }
  }
}

    <div class='father'>
        <div class='a'></div>
        <div class='b'> </div>
        <div class='c'><div class='cLongContent'></div></div>
    </div>

13、BetterScroll 2.0遇到的坑

ios13.4移动端无法滚动,其他都可以滚动。原因是BetterScroll的css代码

.BetterScroll {
    position: relative;
    width: 710px;
    height: 100%;
    // display: flex;
    // flex-direction: column;
    // align-items: center;
    overflow: hidden;
    .conetent {
        position: relative;
        width: 710px;
        height: 2000px;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
    }
}
注释掉:BetterScroll的如下代码即可!
// display: flex;
// flex-direction: column;
// align-items: center;

js常用设置

1、lottie的动画监听

例如使用了lott.playSegments([248, 348], true);循环播放,但是如果用enterFarme来监听执行的最后一帧会有误差,有空还没执行到最后一帧,它就重新播放了。

解决方法:使用loopComplete

lott.addEventListener("loopComplete", () => {
          if(this.animationRuning){
            this.lott.playSegments([10, 100], true);
            this.animationRuning = false;
            this.lott.removeEventListener("loopComplete");
            resolve();
          }
 });

2、滚动-ios在全屏滚动下偶尔会出现无法滚动情况

当给全屏元素设置scroll的时候,里面的内容在滚动的时候ios偶尔会出现无法滚动,不操作几秒才会恢复的情况。

.scroll {
  position: absolute;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  overflow-y: scroll;
  .scrollContent {
      position: relative;
      width: 100vw;
      height: 200vh;
  }
}

解决方法:使用BetterScroll 2.0;

3、滚动到指定元素位置

指定元素.scrollIntoView(true)

参考资料