【记】移动布局

移动端设计稿尺寸:750*1334 (iphone6) 为标准
设备像素比:
设备物理像素和设备独立像素的比例; 也就是 DPR = 物理像素 / 设备独立像素 iphone6以下 dpr=2
可以通过 window.devicePixelRatio 来获取


移动布局开发准备工作

一、搭建本地静态html页面服务器

# 1. 全局安装 http-server
npm i -g http-server

# 2. 在项目文件夹下: 执行 npm init -y 得到 package.json 文件, 然后配置 script
"script": {
	"dev": "http-server ./ -o --port 8089"
}
# 启动服务
npm run dev

二、VSCode编辑设置 LESS 自动编译成 CSS

/* #步骤:
 * 1. 在扩展中安装 Easy LESS 插件 (切记插件名没有中横杆)
 * 2. 在设置中找到 setting.json 文件进行一下配置
 */
"less.compile": {
	"compress": false, // 是否压缩
	"sourceMap": false, // 是否生产map文件,可在控制台看到less行数
	"out": "${workspaceRoot}\css\",
	"outExt": ".css" // 输出文件后缀, 小程序可以写 .wxss
}

三、VSCode编辑器安装插件输入 px 提示 rem 转换值
一般UI给我们的稿子大小是750的。就以这个为例子:在flexible.js中,把750px分为10份,1rem 为 75px。所以font-size的基准值为75px;
css换算成rem公式为: px值 / 75 = rem, 例如:100px=100/75=1.33rem

/* #步骤:
 * 1. 在扩展中安装 cssrem 插件 
 * 2. 选项 -> 设置 -> 扩展下的cssrem 设置基准 foot-size 为 75 
 */

四、使用iconfont字体图标
登录iconfont.cn, 选择你需要的图标保存至项目。并生成在线连接, 将代码保存至本地即可使用。

// style/iconfont.css
@font-face {
  font-family: "iconfont"; /* Project id 2524131 */
  src: url('//at.alicdn.com/t/font_2524131_8g1ggguc7ig.woff2?t=1619912299648') format('woff2'),
       url('//at.alicdn.com/t/font_2524131_8g1ggguc7ig.woff?t=1619912299648') format('woff'),
       url('//at.alicdn.com/t/font_2524131_8g1ggguc7ig.ttf?t=1619912299648') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-shuben:before {
  content: "e6ca";
}

iconfont 的使用
全局引入:在main.js文件中进行全局引入, import './style/iconfont.css'
具体使用: <span class="iconfont icon-shuben'><!--书本--></span>


移动端开发适配

一、 设置meta标签

<!-- 强制让文档与设备的宽度保持1:1 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<!-- 禁止识别电话和邮箱 -->
<meta name="format-detection" content="telephone=no,email=no" />

二、动态设置html根节点的字体大小,实现 rem 适配

// 动态设置html的字体: font-size设为100px, 1rem = 100px
(function(win, doc) {
    if (!win.addEventListener) return;
    function setHtmlFontSize() {
        var html = document.documentElement;
        var k = 750;
        html.style.fontSize = html.clientWidth / k * 100 + "px";
    }  
    doc.addEventListener('DOMContentLoaded', setHtmlFontSize, false);
    win.addEventListener('resize', setHtmlFontSize, false);
    win.addEventListener('load', setHtmlFontSize, false); 
})(window, document)

H5界面淘宝提供的适配方案flexible.js

github地址:https://github.com/amfe/lib-flexible
官方文档地址:https://github.com/amfe/article/issues/17

Flexible.js的使用:
使用了flexible.js,页面模板不需要设置 <meta name="viewport">的标签,会自动设置根元素html的font-size、动态创建viewport、针对retina屏做dpr

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta content="yes" name="apple-mobile-web-app-capable">
        <meta content="yes" name="apple-touch-fullscreen">
        <meta content="telephone=no,email=no" name="format-detection">
        <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
        <link rel="apple-touch-icon" href="favicon.png">
        <link rel="Shortcut Icon" href="favicon.png" type="image/x-icon">
        <title>案例实战</title>
    </head>
    <body>
        <!-- 页面结构写在这里 -->
    </body>
</html>

移动端常见问题【解决方案】

一、禁止电话与邮箱
添加meta标签全局禁用
<meta name="format-detection" content="telephone=no,email=no" />
局部使用:

<a href="tel:15919829191">电话: 15919829191</a>
<a href="mailto:645629118@qq.com">邮箱: 645629118@qq.com</a>

二、解决链接按钮高亮问题
使用 a 标签作为按钮时,移动端页面中的链接长按会触发一个色块高亮效果;

a {
	-webkit-tap-highight-color: transparent;
}
/* 或者设置你需要的颜色 */
a {
	-webkit-top-highlight-color: rgba(0,0,0,0);
}

三、解决按钮圆角过圆的问题

<style>
input{
	border-radius: 10px;
	-webkit-appearance: none;
}
</style>

<input type="button" value="按钮" />

四、font-boosting 问题
Foot Boosting 是 webkit给移动端提供的一个特性。当在手机浏览器上缩小页面后字体很小看不清,这时浏览器会自动增大字体大小 ,解决方案: 设置最大高度

p {
	font-size: 14pxl
	max-height: 99999px;
}

五、1物理像素问题

<style>
#test:before {
	position: absolute;
	bottom: -1px;
	content: "";
	display: block;
	 100%;
	height: 1px;
	background: #f00;
}
@media only screen and(-webkit-device-pixel-ration: 2) {
	#test:before {
		transform: scaleY(0.5)
	}
}
@media only screen and(-webkit-device-pixel-ration: 3) {
	#test:before {
		transform: scaleY(0.33)
	}
}
</style>
<div id="test">1物理像素</div>

六、移动端触摸事件【点透】问题解决方案

/*
 * 底层节点阻止默认行为 
 * 1. 解决IOS10下设置meta无法禁止用户缩放的兼容性问题
 * 2. 解决IOS10下溢出隐藏的问题 body,html{ 100%; overflow: hidden;}
 * 3. 阻止橡皮筋效果(页面华东到最顶和最低部的缓冲反弹的效果)
 * 4. 禁止长按选中文字、选中图片、弹出菜单等
 * 5. 阻止默认行为后,元素无法获取焦点,元素阻止冒泡后可正常使用
 */
document.addEventListener("touchstart", function(ev) {
	ev.preventDefault();
})
// 缺点: a 链接等可获取焦点的元素的默认行为无法使用,需要手动添加事件绑定
var aNodes = document.querySelectorAll("a")
for(var i = 0; i < aNodes.length; i++) {
	aNodes[i].addEventListener("touchstart", function() {
		this.isMoved = false;
	})
	aNodes[i].addEventListener("touchmove", function() {
		this.isMoved = true
	})
	aNodes[i].addEventListener("touchend", function() {
		if(!this.isMoved) {
			window.location.href = this.href;
		}
	})
}

导航拖拽效果 - 橡皮筋效果

<!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,user-scalable=no" />
    <title></title>
    <style>
    	* { margin: 0; padding: 0; }
        li, ol { list-style: none; }
        html, body {  100%; overflow: hidden; height: 100%; }
        body { font-size: 14px; }
        .slide-nav {
          height: 1rem;
          background: #f4f6fd;
          font-size: 16px;
        }
        .slide-nav > ul {
          float: left;
          white-space: nowrap;
          display: flex;
          align-items: center;
          height: 100%;
        }
        .slide-nav > ul > li {
          display: inline-block;
          padding: 0 0.3rem;
        }
    </style>
    <script>
      // 动态设置html的字体
      (function (win, doc) {
        if (!win.addEventListener) return;
        function setHtmlFontSize() {
          var html = document.documentElement;
          var k = 750;
          html.style.fontSize = (html.clientWidth / k) * 100 + "px";
        }
        doc.addEventListener("DOMContentLoaded", setHtmlFontSize, false);
        win.addEventListener("resize", setHtmlFontSize, false);
        win.addEventListener("load", setHtmlFontSize, false);
      })(window, document);

      /** 
       * 封装设置样式和获取样式的方法
       */
      function css(node, type, val) {
        var filedStr = "transform"
        if (typeof node === "object" && typeof node[filedStr] === "undefined") { 
          node[filedStr] = {} 
        } 

        if(arguments.length >= 3) {
          // 设置
          var text = ''
          node[filedStr][type] = val;
          
          for(item in node[filedStr]) { 
            if(node[filedStr].hasOwnProperty(item)) {
              switch (item) {
                case "translateX":
                case "translateY":
                  text += item + "("+node[filedStr][item]+"px)"
                  break;
                case "scale":
                  text += item + "("+node[filedStr][item]+")"
                  break;
                case "rotate":
                  text += item + "("+node[filedStr][item]+"deg)"
                  break;
              }
            }
          }  
          node.style[filedStr] = node.style.webkitTransform = text; 
        } else if(arguments.length == 2) {
          // 读取
          var val = node[filedStr][type];  
          if (typeof val === "undefined") {
            switch (type) {
              case "translateX":
              case "translateY":
              case "rotate": 
                val = 0;
                break;
              case "scale":
                val = 1
                break;
            }
          } 
          return val;
        }
      }

      window.onload = function () {
        // 滑动导航
        drag();
        function drag() {
          var slideEle = document.querySelector(".slide-nav"),
            slideItem = document.querySelector(".items"),
            // 记录元素开始位置, 手指开始位置
            startX = 0,
            elementX = 0,
            // (可视区宽 - 滑动内容宽) 
            minX = slideEle.clientWidth - slideItem.offsetWidth;
          // 快速滑屏:
          var lastTime = 0,
              lastPoint = 0,
              timeDis = 0,
              pointDis = 0;
          
          slideEle.addEventListener("touchstart", function (ev) {
            ev = ev || event;
            var touchC = ev.changedTouches[0] 

            startX = touchC.clientX;
            elementX = css(slideItem, 'translateX')
            slideItem.style.transition = "none";

            lastTime = new Date().getTime();
            lastPoint = touchC.clientX

            // 清楚速度
            pointDis = 0;
          }); 

          slideEle.addEventListener("touchmove", function(ev) {
            ev = ev || event;
            var touchC = ev.changedTouches[0]
            var nowX = touchC.clientX;
            var disX = nowX - startX;
            var translateX = elementX + disX
            var winW = document.documentElement.clientWidth

            var nowTime = new Date().getTime();
            var nowPoint = touchC.clientX;
            timeDis = nowTime - lastTime;
            pointDis = nowPoint - lastPoint;
            lastTime = nowTime;
            lastPoint = nowPoint;
             
            slideItem.handMove = false; 
            // 范围限制
            if (translateX > 0) { 
              slideItem.handMove = true; // 用于判断是快速滑动还是普通滑动
              var scale = winW/((winW + translateX) * 2); // (0, .5) 
              translateX = css(slideItem, "translateX") + pointDis * scale; 
            } else if (translateX < minX){
              slideItem.handMove = true; 
              var overW = minX - translateX;
              var scale = winW/((winW + overW) * 2); // (0, .5) 
              translateX = css(slideItem, "translateX") + pointDis * scale; 
            }
            css(slideItem, "translateX", translateX)
          })

          slideEle.addEventListener("touchend", function() {
            var translateX = css(slideItem, "translateX"); 
            if (!slideItem.handMove) {
              // 快速滑动 + 橡皮筋效果
              var speed = pointDis/timeDis; // 速度越大,位移越远
              speed = Math.abs(speed) < 0.5 ? 0 : speed; // 
              var targetX = translateX + speed * 200;
              var time = Math.abs(speed) * 0.2;
              time = time < 0.8 ? 0.8 : time;
              time = time > 2 ? 2 : time;

              var bsr = '';
              if (targetX > 0) {
                targetX = 0
                bsr = 'cubic-bezier(.33,1.27,.58,1.42)'
              } else if (targetX < minX){
                targetX = minX
                bsr = 'cubic-bezier(.33,1.27,.58,1.42)'
              }
              slideItem.style.transition = time + "s " + bsr + " transform"; 
              css(slideItem, "translateX", targetX)
            } else {  
              // 普通滑动
              if (translateX > 0) {
                translateX = 0
              } else if (translateX < minX){
                translateX = minX
              }
              slideItem.style.transition = "1s transform";
              css(slideItem, "translateX", translateX)
            }
          }) 
        }
      };
    </script>
  </head>
  <body>
    <div class="slide-nav">
   		<ul class="items">
            <li>新闻</li>
            <li>电视剧</li>
            <li>在线热点</li>
            <li>预览</li>
            <li>我</li>
            <li>职场信息</li>
            <li>最新资讯</li>
            <li>新风向</li>
            <li>娱乐圈</li>
            <li>信用</li>
    		<li>周边房价</li>
    	</ul>
    </div>
  </body>
</html>

CSS 实现 贝塞尔曲线(cubic-bezier) 运动

贝塞尔曲线运动

animation: 1s cubic-bezier(.31,1.13,.41,1.39) transform;

媒体查询

什么是媒体查询:查询屏幕类型和屏幕大小;
为何要媒体查询:为了兼容,根据屏幕大小写样式
媒体类型:

  • all:默认类型,表示全部的
  • screen:浏览器页面
  • print:打印页面
  • speech:正对残障人士设计的
// min-width规则为: 当媒体类型 大于或等于 指定的宽度时, 大括号内的样式生效
@media screen and (min- 900px) {
	...
}
// max-width规则为: 当媒体类型 小于或等于 指定的宽度时,大括号内的样式生效
@media screen and (max- 900px) {
	...
}

媒体查询中的逻辑:

  • 与 (and)
  • 或 (,)
  • 非 (not)
// 同时设置多个媒体特性
// 最大宽度为1000px, 最小宽度为700px。大于等于700px且小于等于1000px的范围内设置生效
@media screen and (max- 1000px) and (min- 700px) {
	...
}
// 

根据设备尺寸加载不同的样式表:

// 根据屏幕设备的尺寸来设置相应的样式 
<link rel="stylesheet" media="screen and (max-device-weidth:480px)" href="iphone.css" />
原文地址:https://www.cnblogs.com/yuxi2018/p/14855213.html