H5开发规范与兼容

379 阅读2分钟

规范

骨架屏

.skeleton {
  background-image: linear-gradient(-45deg, #f5f5f5 40%, #fff 55%, #f5f5f5 63%);
  background-size: 400% 100%;
  background-position: 100% 50%;
  animation: skeleton-animation 2s ease infinite;
}

@keyframes skeleton-animation {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

 export const skeleton = (data, otherClass)=> {
   return data ? ` ${otherClass}` : `skeleton ${otherClass}`
 }
 <div :class="skeleton(true)"></div>

兼容

一. 通用

吸顶

  • 菜单等组件吸顶建议使用 position:sticky; ,

使用条件:

  • 父元素不能overflow:hidden或者overflow:auto属性。
  • 必须指定top、bottom、left、right4个值之一,否则只会处于相对定位
  • 父元素的高度不能低于sticky元素的高度
  • sticky元素仅在其父元素内生效

demo

<template>
 <div class="strcky__wrapper">
   <div class="strcky__content">
     StickyStickyStickyStickySticky
   </div>
   <div>
     还会滚动
   </div>
 </div>
</template>

<script>
export default {
  data() {
    return {

    };
  },
  methods: {

  }
};
</script>
<style lang="stylus" scoped>
.strcky__wrapper {
  border 1px solid red
  height 1000px
}
.strcky__content {
  position sticky
  top 0
  height 50px
  border 1px solid  green
  background-color #fff
}
</style>
  • scroll事件进行监听scrollTop的值,然后改变为 position: fixed; 也可以实现,不过滚动过快会出现断层。

双层滚动

双层滚动建议当弹框弹出时候设置body或者另一层滚动设置 overflow: hidden; ,当弹框消失时设置 overflow: auto;

还可以使用禁止事件冒泡实现,效果不好。

一像素边框

安卓部分机型无法显示1px线,所以要放大再缩小,如果需要站位,建议使用两个相同的div,一个不缩放,设置 visibility:hidden;

.border-1px {
  position: absolute;
  top: 0;
  left: 0;
  width: 200px;
  height: 200px;
  transform: scale(0.5);
  transform-origin: 0 0;
  border: 1px solid red;
}

页面禁止选中

页面禁止选中目前是通过 css 实现, 通过 js 通过监听 contextmenu 事件只能在 PC 端实现,移动端有问题。

* {
  -webkit-touch-callout: none; /* 系统默认菜单被禁用 */
  -webkit-user-select: none; /* webkit浏览器 */
  -khtml-user-select: none; /* 早期浏览器 */
  -moz-user-select: none; /* 火狐浏览器 */
  -ms-user-select: none; /* IE浏览器 */
  user-select: none; /* 用户是否能够选中文本 */
}

二. 安卓

文字 <11px 居中

app.vue

<template>
  <div id="app">
    <CenterText v-for="(item, index) in 10" :key="index" :props="centerTextProps" />
  </div>
</template>

<script>
import CenterText from "./components/CenterText.vue";

export default {
  name: "App",
  components: {
    CenterText,
  },
  data() {
    return {
      centerTextProps: {
        class: 'app-center-text-wrapper',
        text: "abcdefg123456789",
        fontSize: "22",
        height: "44",
        borderRadius: "12",
        color: "#239466",
        fontWeight: "700",
        borderWidth: "1",
      },
    };
  },
};
</script>

<style lang="stylus" scoped>
.app-center-text-wrapper {
  background-color: rgba(33,33,33,.3)
}
</style>

CenterText.vue

<template>
  <div
    :class="['center-text__wrapper',props.class]"
    :style="{ backgroundColor: props.backgroundColor , height }"
  >
    <div class="center-text__wrapper-box">
      <div
        class="center-text__content"
        :style="{ fontSize, color:props.color, fontWeight:props.fontWeight }"
      >{{props.text}}</div>
    </div>
    <div
      class="center-text__wrapper-after"
      :style="{ borderRadius, borderColor: props.borderColor, borderWidth, borderStyle: props.borderStyle }"
    />
  </div>
</template>

<script>
import { px2vw } from "@/util";
console.log(px2vw);
export default {
  props: {
    props: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      px2vw,
    };
  },
  computed: {
    height() {
      return px2vw(this.props.height);
    },
    fontSize() {
      return px2vw(this.props.fontSize, 2);
    },
    borderRadius() {
      return px2vw(this.props.borderRadius, 2);
    },
    borderWidth() {
      return px2vw(this.props.borderWidth, 2);
    },
  },
  mounted() {},
};
</script>

<style lang="stylus" scoped>
.center-text__wrapper {
  position: relative;
  box-sizing: border-box;
  display: inline-block;
  margin-right: 10px;
  padding: 0 10px;
  margin-bottom: 10px;
}

.center-text__wrapper-box {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.center-text__content {
  color: black;
  zoom: 0.5;
}

.center-text__wrapper-after {
  position: absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 200%;
  transform: scale(0.5);
  transform-origin: 0 0;
  border: 1px solid red;
  border-radius: 15px;
}
</style>

util.js


export function px2vw(px, multiple) {
  if (!px) return '0';
  const val = parseFloat(px.toString() || '0');
  if (multiple) {
    return isNaN(val) ? '0' : `${Number((val / 7.5 * multiple).toFixed(3))}vw`;
  } else {
    return isNaN(val) ? '0' : `${Number((val / 7.5).toFixed(3))}vw`;
  }
 }
 

三. iOS

禁横向滚动条

方法一实现时而有效时而无效,方法一,方法二同时使用

方法一:

::-webkit-scrollbar {
  width:0;
  height:0;
  opacity:0;
  display: none;
}

方法二: 让父dom超出隐藏,子带滚动条dom高度放大三倍,使滚动条超出父dom,被隐藏掉。

惯性滚动

-webkit-overflow-scrolling : touch;

禁止 dom 切换黑色阴影

* {
  -webkit-tap-highlight-color: rgba(0,0,0,0) ;
  -webkit-tap-highlight-color: transparent; /* For some Androids */ 
}

适配 iphone 刘海屏

body {
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}