h5基础

发布时间 2023-10-09 11:11:06作者: songxia777

1. 介绍

1.1 IPhone6的参数

设备像素 750 * 1334

设备独立像素 375 * 667

屏幕分辨率 750 * 1334

ppi 326

一般设置的移动端最大和最小宽度

min-width:320px;
max-width:640px;

1.2 980 布局视口

980 像素就是浏览器厂商设置的布局视口的初始宽度

1.3 数据共享的方法

  1. 提高变量的作用域.
  2. 将数据保存在一个对象中

1.4 addEventListener 第三个参数

document.documentElement.addEventListener('touchstart', function(e){
    //阻止默认行为
    e.preventDefault();
},{
    passive:false // 被动  被动模式   true  false  控制 e.preventDefault 是否失效
}); 

2. 屏幕相关

2.1 屏幕大小

屏幕大小指屏幕的对角线的长度,单位一般是英寸。常见的手机屏幕大小 3.5、4、4.7、5.0、5.5、6.0等。常见手机屏幕查看网址 http://screensiz.es/
image

注意:

  • 英寸的英文为 inch , 英尺的英文是 foot 4.7inch

  • 1foot = 12inch 1inch=2.54cm

2.2 屏幕分辨率

屏幕分辨率是指屏幕横纵向上的像素点数。一般表示形式 x * y 或者 y * x 表示。例如 IPhone 6 的屏幕分辨率为 750 * 1334,华为 P30 的分辨率为 2340 * 1080。

注意:

  • 屏幕分辨率是一个固定值,生产出来就固定了,无论手机屏幕还是电脑屏幕。
  • 屏幕分辨率与显示分辨率不同。计算机可以修改显示分辨率,信号传递给屏幕,屏幕会进行计算,在屏幕上显示。
  • 1080P 的分辨率是1920x1080 720P 1280 * 720
  • 2K 屏幕是单一方向分辨率具有约 2000 像素的显示设备。最标准的 2K 分辨率为 2048×1024

几款手机的分辨率

型号 分辨率
IPhone 3GS 320 * 480
IPhone 4 / 4s 640 * 960
IPhone 5 / 5s 640 * 1136
IPhone 6 / 7 / 8 750 * 1334
华为 P30 1080 * 2340
IPhone X 1125 * 2436

4. 视口viewport

4.1 PC 端

在 PC 端,视口指的是浏览器的可视区域。其宽度和浏览器窗口的宽度保持一致。在 CSS 标准文档中,视口也被称为初始包含块,它是所有 CSS 百分比宽度推算的根源。

// 获取可视区域的宽度  不包含滚动条
document.documentElement.clientWidth

// 获取浏览器窗口的宽度  包含滚动条
window.innerWidth

// 获取浏览器总宽  包含外侧的阴影
window.outerWidth

// 获取屏幕的宽度 screen  屏幕的总宽
screen.width

4.2 移动端

移动端的视口与 PC 端不同,有三个视口

  • 布局视口
  • 视觉视口
  • 理想视口

4.2.1 布局视口:放置网页内容的区域

布局视口是用来放置网页内容的区域

一般移动设备的浏览器都默认定义一个虚拟的布局视口(layout viewport),用于解决早期的页面在手机上显示的问题。 视口大小由浏览器厂商决定,如果不设置viewport,大多数设备的布局视口大小为 980px

获取方式:

document.documentElement.clientWidth // 布局视口的宽度
document.documentElement.clientHeight

4.2.2 视觉视口: 用户可见的区域

视觉视口就是 用户可见的区域:window.innerWidth

获取方式

window.innerWidth // 视觉视口的宽度
window.innerHeight

注:不缩放的情况下,视觉视口宽度 == 布局视口宽度。

4.2.3 理想视口

宽度与屏幕同宽的布局视口称为理想视口。 理想视口的好处

  • 用户不需要缩放和滚动条就能看到网站的全部内容。
  • 针对移动端的设计稿更容易开发。

注意:理想视口不是真实存在的视口

设置理想视口的方法

<meta name="viewport" content="width=device-width" />
<--或者-->
<meta name="viewport" content="initial-scale=1.0" />

<--合体(推荐)-->
<meta name="viewport" content="width=device-width,initial-scale=1.0" />

4.2.4 常用参数

// 获取   布局视口   的宽度
console.log(document.documentElement.clientWidth);

// 获取   视觉视口   的宽度
console.log(window.innerWidth);

5. 缩放

5.1 PC 端

放大时

  • 布局视口变小
  • 视觉视口变小
  • 元素的像素大小不变

缩小时

  • 布局视口变大
  • 视觉视口变大
  • 元素的像素大小不变

5.2 移动端

放大时

  • 布局视口不变
  • 视觉视口变小

缩小时

  • 布局视口不变
  • 视觉视口变大

注意:移动端缩放不会影响页面布局

6. 真机测试流程

真机测试是项目测试必需的一个流程,一定要掌握!!!

  1. 关闭防火墙

  2. webstorm -> ctrl + alt + s -> 搜索 debugger -> 修改端口并选中两个多选框 端口要大于 1024 建议用 8000 8888

  3. 使 PC 与手机处于同一个网络。手机连接电脑 wifi,或者电脑连接手机热点,两者在同一个 wifi 下最方便

  4. cmd 查看电脑无线网卡的 IP(ipconfig)

  5. webstorm 在浏览器中预览文件,将 localhost 更改为 IP

  6. 打开草料网址 https://cli.im/ 将 URL 转化为二维码,手机扫描即可 ?

7. viewport 控制

viewport 标签是苹果公司在 2007 年引进的,用于移动端布局视口的控制。

使用示例

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scaleable=no,maximum-scale=1.0, minimum-scale=1.0">

viewport 相关选项

  • width 布局视口宽度
  • initial-scale 初始化缩放比例
  • minimum-scale 最小缩放比例
  • maximum-scale 最大缩放比例
  • user-scalable 设置是否允许用户缩放
  • viewport-fit auto/contain/cover

width

width 值可以是数字,也可以是设备宽度表示 device-width,这样可以得到完美视口

initial-scale

initial-scale 为页面初始化时的显示比例。

scale = 屏幕宽度独立像素 / 布局视口宽度。 // iphone6 0.5

注意:

  • chrome 测试该参数会有偏差,真机测试
  • initial-scale = 1.0 也可以得到完美视口
  • initial-scale 会影响布局视口和视觉视口的大小
  • width 与 initial-scale 同时设置时,会选择尺寸较大的那个

minimum-scale

设置允许用户最小缩放比例。

minimum-scale = 屏幕独立像素宽度 / 视觉视口 //iphone 6 0.5

maximum-scale

设置允许用户最大缩放比例,苹果浏览器 safari 不认识该属性

maximum-scale = 屏幕独立像素宽度 / 视觉视口 // 2

user-scalable

是否允许用户通过手指缩放页面。苹果浏览器 safari 不认识该属性。

viewport-fit

设置为 cover 可以解决『刘海屏』的留白问题

image

8. 移动端事件

8.1 事件类型

移动端事件列表

  • touchstart 元素上触摸开始时触发
  • touchmove 元素上触摸移动时触发
  • touchend 手指从元素上离开时触发
  • touchcancel 触摸被打断时触发

这几个事件最早出现于IOS safari中,为了向开发人员转达一些特殊的信息

其他常见事件:

键盘:

onkeydown onkeypress onkeyup

滚轮:

onmousewheel

文档:

onload onbeforeunload

<script type="text/javascript">
    // 判断 用户是否离开您的网页
    window.onbeforeunload=function () {
    return '您确定要离开吗?';
}
</script>

表单:

onfocus onblur onsubmit onreset

鼠标:

onclick onmouseenter onmouseleave onmouseover onmouseout onmousedown onmousemove onmouseup

8.7 IOS 多指事件

事件类型

  • gesturestart : 手指触碰当前元素,屏幕上有两个或者两个以上的手指
  • gesturechange : 手指触碰当前元素,屏幕上有两个或者两个以上的手指位置在发生移动
  • gestureend : 在gesturestart后, 屏幕上只剩下两根以下(不包括两根)的手指

多指事件属性

  • rotation : 表示手指变化引起的旋转角度,负值表示逆时针旋转,正值表示顺时针旋转。
  • scale : 表示两个手指间距离的变化情况(例如向内收缩会缩短距离);这个值从 1 开始,并随距离拉大而 增长,随距离缩短而减小。根据我们的生理极限,不允许出现负值

8.2 应用场景

touchstart 事件可用于元素触摸的交互,比如页面跳转,标签页切换

touchmove 事件可用于页面的滑动特效,网页游戏,画板

touchend 事件主要跟 touchmove 事件结合使用

touchcancel 使用率不高

注意:

  • touchmove 事件触发后,即使手指离开了元素,touchmove 事件也会持续触发
  • 触发 touchmove 与 touchend 事件,一定要先触发 touchstart
  • 事件的作用在于实现移动端的界面交互

8.3 事件绑定

方式一:

box.ontouchstart = function(){
    console.log('touch start')
}

方式二(推荐):

box.addEventListener('touchstart', function(){
	console.log('touch start')
})

8.4 点击穿透

touch 事件结束后会默认触发元素的 click 事件,如没有设置完美视口,则事件触发的时间间隔为 350ms 左右,如设置完美视口则时间间隔为 5ms 左右。

如果 touch 事件隐藏了元素,则 click 动作将作用到新的元素上,触发新元素的 click 事件或页面跳转,此现象称为点击穿透

 var t1 = 0;
  var box = document.getElementById('box');
  box.addEventListener('touchstart', function () {
    console.log('触发了  touchstart  事件');
    t1 = Date.now(); // 获取当前时间的时间戳
  });
  box.addEventListener('click', function () {
    console.log('触发了  click  事件');
    var t2 =Date.now();
    console.log('时间间隔:', t2 - t1); 
  })

解决方法

方法1:阻止当前元素事件的默认行为。

cls.addEventListener('touchstart', function(e){	e.preventDefault();})

// 鼠标右键 不弹出自定义的菜单
window.oncontextmenu=function (e) {
   e.preventDefault();
 }

方法2:阻止顶级元素事件的默认行为,可以增加一个包裹元素绑定,也可以给 document 和 window 绑定,不过需要关闭被动模式

 document.addEventListener('touchstart', function (e) {
    e.preventDefault();
  }, {passive: false});

方法3:使用非链接的元素代替 a 标签,设置链接地址属性,并绑定 touchstart 事件

<div class="item">
  <div data-href="http://m.atguigu.com">
    <img src="holder.js/60x60?bg=#a76">
  </div>
     <div data-href="http://m.atguigu.com">
    <img src="holder.js/60x60?bg=#a76">
  </div>
     <div data-href="http://m.atguigu.com">
    <img src="holder.js/60x60?bg=#a76">
  </div>
</div>
通过touchstart 事件,获取data-href属性,并调整链接 location.href=XXX;

方法4:延时隐藏 遮罩层元素

  setTimeout(function () {
    el.style.display = 'none';
  }, 400);

8.5 页面跳转的选择

移动端页面跳转可以使用 a 链接,也可以使用 touchstart 事件来触发 JS 代码完成跳转

  • 效率上,touchstart 速度更快
  • SEO 优化上, a 链接效果更好

8.6 浏览器默认行为(一般是不需要阻止的)

这里指的浏览器默认行为主要有3个

  • 向下滑动会露出空白
  • 长按会弹出复制、拷贝等菜单行为
  • 页面缩放

8.6.1 为什么要阻止这些默认行为

这样可以让网页在不同的浏览器都有一样的表现。

8.6.2 如何阻止默认行为

可以给 document 绑定 touchstart 事件,并阻止默认行为,不过需要关闭被动模式。这里推荐创建一个包裹元素,绑定 touchstart 事件并阻止默认行为。

CSS 代码

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

HTML 代码

<body>
	<div id="app">
        XXXXXX
    </div>
</body>

JS 代码

var app=document.documentGetElementById('app')// 阻止事件的默认行文app.addEventListener('touchstart', function (e) {    e.preventDefault();})

8.6.3 后遗症

最外层元素阻止了 touchstart 默认行为之后,会产生一些意外现象?

  • 链接失效
  • 内容无法选择
  • form 元素无法获得焦点

8.6.4 最终解决方案:阻止冒泡e.stopPropagation()

产生『后遗症』的原因在于 touchstart 阻止了默认行为,后续所有的操作都已经失效。

解决问题:只需要给目标元素绑定 touchstart 事件并阻止事件冒泡,这样当前操作的默认行为仍然可用。

var link = document.getElementsByTagName('a')[0]; // 目标元素
link.addEventListener('touchstart', function (e) {
    e.stopPropagation(); // 阻止事件冒泡
})

注: 不是非要阻止浏览器的默认行为,这是一种极端要求的应对方法,正常只需要设置完美视口即可。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
 
        ul {
            list-style: none;
        }
 
        #box {
            width: 100%;
            height: 2000px;
            background: linear-gradient(to bottom, #98a, #aef);
        }
    </style>
</head>
<body>
<div id="app">
    <div id="box">
        <h2><a href="http://www.baidu.com/s?wd=方便面">兰亭集序</a></h2>
        <div>作者: <input type="text"></div>
        <p>
            永和九年,岁在癸丑,暮春之初,会于会稽山阴之兰亭,修禊事也。群贤毕至,少长咸集。此地有崇山峻岭,茂林修竹,又有清流激湍,映带左右,引以为流觞曲水,列坐其次。虽无丝竹管弦之盛,一觞一咏,亦足以畅叙幽情。
            是日也,天朗气清,惠风和畅。仰观宇宙之大,俯察品类之盛,所以游目骋怀,足以极视听之娱,信可乐也。
            夫人之相与,俯仰一世。或取诸怀抱,悟言一室之内;或因寄所托,放浪形骸之外。虽趣舍万殊,静躁不同,当其欣于所遇,暂得于己,快然自足,不知老之将至;及其所之既倦,情随事迁,感慨系之矣。向之所欣,俯仰之间,已为陈迹,犹不能不以之兴怀,况修短随化,终期于尽!古人云:“死生亦大矣。”岂不痛哉!
            每览昔人兴感之由,若合一契,未尝不临文嗟悼,不能喻之于怀。固知一死生为虚诞,齐彭殇为妄作。后之视今,亦犹今之视昔,悲夫!故列叙时人,录其所述,虽世殊事异,所以兴怀,其致一也。后之览者,亦将有感于斯文。
        </p>
    </div>
</div>
<script>
    var app = document.querySelector('#app');
    var p = document.querySelector('p');
    var input = document.querySelector('input');
 
    //阻止浏览器的默认行为
    app.addEventListener('touchstart', function (e) {
        e.preventDefault();
    });
 
    //获取a链接
    var a = document.querySelector('a');
 
    a.addEventListener('touchstart', function (e) {
        //阻止冒泡
        e.stopPropagation();
    });
 
    // 阻止m冒泡,长按文字就可以复制了
    p.addEventListener('touchstart', function(e){
        e.stopPropagation();
    });
   // input获取焦点
    input.addEventListener('touchstart', function(e){
        this.focus();
        e.stopPropagation();
    });
  // input 丧失焦点
    app.addEventListener('touchstart', function(){
       input.blur();
    });
 
</script>
</body>
</html>

9. 事件对象属性

touch 事件对象中有 3 个非常重要的属性

  • changedTouches
  • targetTouches
  • touches
  • 获取手指离开元素时的位置:只可以使用changedTouches

9.1 touchstart 事件

在 touchstart 事件中,

changedTouches 为当前在元素上同时按下的触点对象数组。

targetTouches 为按下后,当前元素上的触点对象数组

touches 为按下后,当前屏幕上所有的触点对象数组

9.2 touchmove 事件

在 touchmove 事件中

changedTouches 为当前在元素上同时滑动的触点对象数组。

targetTouches 为滑动时,当前元素上的触点对象数组

touches 为滑动时,当前屏幕上所有的触点对象数组

9.3 touchend 事件

在 touchend 事件中

changedTouches 为当前在元素上同时抬起的触点对象数组。

targetTouches 为结束时时,当前元素上的触点对象数组

touches 为结束时时,当前屏幕上所有的触点对象数组

9.4 触点对象

每一个触点对象都包含一些位置信息,其中包括

  • clientX 相对可视区域左侧的偏移
  • clientY 相对可视区域顶侧的偏移
  • pageX 相对文档左侧的偏移
  • pageY 相对文档顶部的偏移

案例一:获取当前鼠标点击时的坐标

var box = document.querySelector('#box');
// 获取当前鼠标点击的坐标
box.onclick = function(e){
    var x = e.clientX;
    var y = e.clientY;

    var a = e.pageX;
    var b = e.pageY;
    console.log(x,y, a, b);
}

案例二: 获取当前按键的信息

// 获取当前按键的信息  ctrl + c
window.onkeydown = function(e){
    console.log(e.keyCode); // 67 c
    console.log(e);
    if(e.keyCode == 67 && e.ctrlKey){
        // alert('你按下了 ctrl + c')
        // 防止用户复制页面内容
        e.preventDefault();
    }
}

案例三: 阻止 右键 的弹出菜单

window.oncontextmenu = function(e){
    e.preventDefault();
}

案例四:点击单独的位置,获取触的位置信息;移动鼠标,也可以获取触点的位置信息

	// 点击单独的位置,获取触的位置信息;移动鼠标,也可以获取触点的位置信息
			var box = document.querySelector('#box');
			box.addEventListener('touchstart', function(e) {
				// 获取触点的信息
				var x = e.changedTouches[0].clientX;
				var y = e.changedTouches[0].clientY;
				box.innerHTML = 'X:' + x + ' <br> Y:' + y;
			});

			box.addEventListener('touchmove', function(e) {
				// 获取触点的信息
				var x = e.changedTouches[0].clientX;
				var y = e.changedTouches[0].clientY;
				box.innerHTML = 'X:' + x + ' <br> Y:' + y;
			});
			// 阻止默认行为
			document.documentElement.addEventListener('touchstart', function(e) {
				e.preventDefault();
			}, {
				passive: false
			})

案例五:拖拽:4的位置=3-(1-2)

image

<!doctype html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport"
			content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>Document</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}

			ul {
				list-style: none;
			}

			#box {
				width: 100px;
				height: 100px;
				background: darkred;
				color: white;
				position: absolute;
				left: 0;
				top: 0;
				/*background:rgb(200,241,200);*/
			}
		</style>
	</head>
	<body>
		<div id="box">

		</div>
		<script>
			// 拖拽box的位置
			var box = document.querySelector('#box');

			box.addEventListener('touchstart', function(e) {
				// 获取按下时触点的位置  
				this.size_client_x1 = e.touches[0].clientX;
				this.size_client_y1 = e.touches[0].clientY;

				// 获取按下时 元素距离左侧的偏移量  
				this.size_offset_left1 = box.offsetLeft;
				this.size_offset_top1 = box.offsetTop;
			});

			box.addEventListener('touchmove', function(e) {
				// 获取按下时触点的位置
				this.size_client_x2 = e.touches[0].clientX;
				this.size_client_y2 = e.touches[0].clientY;

				// 获取按下时 元素距离左侧的偏移量
				this.size_offset_left2 = box.offsetLeft;
				this.size_offset_top2 = box.offsetTop;
				
				var left_val = this.size_client_x2 - (this.size_client_x1 - this.size_offset_left1);
				var top_val = this.size_client_y2 - (this.size_client_y1 - this.size_offset_top1);

				// 获取最大的left 的值
				var maxLeft = document.documentElement.clientWidth - box.offsetWidth;
				// 检测水平方向的位置
				if (left_val <= 0) {
					left_val = 0;
				}
				if (left_val >= maxLeft) {
					left_val = maxLeft;
				}
				if (top_val <= 0) {
					top_val = 0;
				}
				// 设置box的 left top 的值
				box.style.left = left_val + 'px';
				box.style.top = top_val + 'px';
			});

			document.body.addEventListener('touchstart', function(e) {
				e.preventDefault();
			}, {
				passive: false
			});
		</script>
	</body>
</html>

10. 适配

移动端设备的屏幕尺寸繁多,要想让页面的呈现统一,需要对不同尺寸的设备进行适配。适配的方式主要有两种

  • viewport 适配
  • rem 适配

10.1 viewport 适配

拿到设计稿之后,设置布局视口宽度为设计稿宽度,然后量尺寸进行布局即可。

  1. 设置 viewport width 等于设计稿的宽度即可
  2. 量取元素的尺寸, 量出来是多少, 就写多少。比如元素宽度 100 像素, 则css 样式为 width : 100px

10.2 rem适配

https://www.bilibili.com/video/BV1nV411q7ch?p=22 参考视频

em 和 rem 都是 CSS 中的长度单位。而且两个都是相对长度单位,不过两个有点区别

  • em 相对的是父级元素的字体大小

    <div id="outer">
        <div id="inner">
        	内容区域
        </div>
    </div>
    
    <style>
        #outer{
        	font-size:40px;
        }
        #inner{
            // 1em=40px 因为是相对于 父级元素的字体大小
        	font-size: 1em;  
        }
    </style>
    
  • rem 相对的是根元素(html)的字体大小

    <div id="outer">
        <div id="inner">
        	内容区域
        </div>
    </div>
    
    <style>
        html{
        	font-size:80px;
        }
        #outer{
        	font-size:40px;
        }
        #inner{
            // 1rem=80px 因为是相对于 根元素的字体大小
        	font-size: 1rem;  
        }
    </style>
    
  • 核心是等比缩放

rem 适配的策略有以下几种

方法一 :

先按照 IPhone 6 进行页面布局,再进行适配

  1. 完美视口设置
<meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  1. 设计稿总宽 375 布局

    设计稿一般都是750*1334的比例,所以真实的css元素尺寸=量取的宽度/2

  2. 设置 IPhone 6 根元素font-size = 100px

  3. 增加 JS 代码进行自动的html的font-size设置

// 以IPhone 6 根元素 font-size=100px 大小为参考,计算任何设备下的根元素的font-size值
document.documentElement.style.fontSize = document.documentElement.clientWidth*100/375+'px';
 
    window.onresize = function () {
        document.documentElement.style.fontSize = document.documentElement.clientWidth*100/375+'px';
    }
  1. 计算rem

    如果html的font-size为100px,那么1rem=100px,1px=0.01rem,所以,如果设计稿给出的宽度是300px,那么最后转换为rem为:300/2*0.01=1.5rem

完整代码案例:

<!doctype html>
<html lang="en" style="font-size: 100px;">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport"
			content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>适配</title>
		<style>
			#box {
				width: 2rem;
				height:1rem;
				background: #886;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>

		<script>
			// //  获取布局视口的宽度 
			// var width = document.documentElement.clientWidth;
			//
			// //计算新的font-size 以iphone6 font-size=100px为依据
			// var x = width * 100 / 375;
			//
			// //设置新的font-size
			// document.documentElement.style.fontSize = x + 'px';
			
			document.documentElement.style.fontSize = document.documentElement.clientWidth * 100 / 375 + 'px';
			window.onresize = function() {
				document.documentElement.style.fontSize = document.documentElement.clientWidth * 100 / 375 + 'px';
			}
		</script>
	</body>
</html>

方法二(推荐):根据设计稿宽度的比例尺寸作为根元素的字体大小

选择一个设计稿宽度的比例尺寸作为根元素的字体大小,如果设计稿宽度是750px,那么html的font-size=75px(方便计算);如果设计稿宽度是375px,那么html的font-size=37.5px(方便计算);

  1. 完美视口设置

    <meta name="viewport"
                  content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    
  2. 通过 JS 设置页面的根元素字体大小(这里为了方便计算,设置布局视口的宽度/10)

    document.documentElement.style.fontSize = document.documentElement.clientWidth / 10+ 'px';
    window.onresize = function() {
    				document.documentElement.style.fontSize = document.documentElement.clientWidth / 10+ 'px';
    			}
    
  3. 根据设计稿使用 rem 设置元素大小

    如果html的font-size为75px,那么1rem=75px,1px=1/75rem,所以,如果设计稿给出的宽度是300px,那么最后转换为rem为:300/75=4rem

    完整代码案例:

    <!doctype html>
    <html lang="en" style="font-size: 37.5px;">
    	<head>
    		<meta charset="UTF-8">
    		<meta name="viewport"
    			content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    		<meta http-equiv="X-UA-Compatible" content="ie=edge">
    		<title>rem适配</title>
    		<style>
    			#box {
    				width: 400/37.5rem;
    				height: 200/37.5rem;
    				background: #886;
    			}
    		</style>
    	</head>
    	<body>
    		<div id="box"></div>
    
    		<script>
    			document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
    			window.onresize = function() {
    				document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
    			}
    		</script>
    	</body>
    </html>
    
    

    结合scss后会更加方便

    // 因为是参考设计稿750px;如果设计稿是375px,那么此处的base-font-size应该是387.5px
    @function px2rem($px, $base-font-size:75px) {
      @if (unitless($px)) {
        @warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
        @return px2rem($px + 0px);
      } @else if (unit($px)==rem) {
        @return $px;
      }
      @return ($px / $base-font-size) * 1rem;
    }
    
    
    #box {
    				width: px2rem(400); // 400是在750px设计稿下量取的尺寸
    				height:  px2rem(200);
    				background: #886;
    			}
    

11. 1px 边框问题

高清屏幕下 1px 对应更多的物理像素,所以 1 像素边框看起来比较粗,解决方法如下

方法一

  1. 边框使用伪类选择器,或者单独的元素实现。例如底部边框
.box2::after {  content: '';  height: 1px;  width: 100%;  position: absolute;  left: 0;  bottom: 0;  background: #000;}
  1. 在高清屏幕下设置
@media screen and (-webkit-min-device-pixel-ratio: 3) {  .box2 {    transform: scaleY(0.33333);  }}

方法二

  1. rem 页面布局
var fontSize = 50;document.documentElement.style.fontSize = '50'+px;
  1. 元素的边框设置为 1px

  2. 通过 viewport 中的 initial-scale 将页面整体缩小

var dpr = window.devicePixelRatio;viewport.setAttribute('content',                       'user-scalable=no, initial-scale='+1/dpr + ',user-scalable=no');
  1. 重新设置根元素字体
document.documentElement.style.fontSize = fontSize * dpr + 'px';