REM(推荐)
注意
rem的适配方式建议用在手机端网页、电脑端前台WEB。
对于管理端不太建议,原因是我们后端管理大都用的第三方框架大都是px为单位的,框架内想改为rem比较麻烦。
首先我们知道rem是根据页面根节点的字体大小来计算dom的宽高的,那么我们就可以根据窗口的大小动态改变根节点的字体大小,而页面中的元素的宽高都使用rem作为单位来适配不同的窗口。
页面中添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <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,maximum-scale=1.0"/> </head> <style> html {font-size: 10px}
body { font-size: 1.4rem; } </style> <script>
function debounce(fn, wait) { let timeout = null return function() { if(timeout !== null) clearTimeout(timeout) timeout = setTimeout(fn, wait); } }
function resize(){ const mHtml = document.documentElement; const width = mHtml.clientWidth; mHtml.style.fontSize = 10 * (width / 400) + "px"; } resize(); window.addEventListener('resize', debounce(resize, 100)) </script>
|
这里我根节点的默认宽度使用的是10px,这样是方便换算为rem,
而效果图的计算宽度默认为400px,是因为400px是在所有主流手机宽度的中间值
这样我们就可以在蓝湖上把效果图的宽度设置为400px,所有的宽高直接除以10换算为rem即可。
PC端可以设置一下最小的适配宽度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <style> html { font-size: 10px }
body { font-size: 1.6rem; } </style> <script> function debounce(fn, wait) { let timeout = null return function () { if (timeout !== null) clearTimeout(timeout) timeout = setTimeout(fn, wait); } }
function resize() { const mHtml = document.documentElement; let width = mHtml.clientWidth; if (width < 1280) { width = 1280; } mHtml.style.fontSize = 10 * (width / 1366) + "px"; }
resize(); window.addEventListener('resize', debounce(resize, 100)) </script>
|
PX2REM+REM(推荐)
安装依赖
1
| npm i postcss-px2rem --save -dev
|
Postcss的配置文件.postcssrc.js
找到项目根目录下的.postcssrc.js文件
1 2 3 4 5 6 7 8 9 10
| module.exports = { "plugins": { "postcss-import": {}, "postcss-url": {}, "autoprefixer": { "browsers": ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 8'] }, 'postcss-px2rem':{'remUnit':10} } }
|
remUnit: 10 代表 1rem = 10px; 所以当你一个12px值时,它会自动转成 (12/10)rem
然后使用上面的适配就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <style> html {font-size: 10px}
body { font-size: 1.6rem; } </style> <script> // 防抖 function debounce(fn, wait) { let timeout = null return function() { if(timeout !== null) clearTimeout(timeout) timeout = setTimeout(fn, wait); } } // 计算 function resize(){ const mHtml = document.documentElement; const width = mHtml.clientWidth; // 假如设计图的宽度是1920 mHtml.style.fontSize = 10 * (width / 1920) + "px"; } resize(); window.addEventListener('resize', debounce(resize, 100)) </script>
|
但是内联样式并没有被处理
我们可以手动更改为计算后的rem。
如果在动态绑定样式并且手动计算比较难算的时候使用下面的方式。
转换方法
1 2 3 4 5 6 7 8
| function px2rem(px){ if(/%/ig.test(px)){ return px }else{ return (parseFloat(px) / 10) + 'rem' } } Vue.prototype.$px2rem = px2rem
|
使用
1
| <div :style="{fontSize:$px2rem('16px')}"></div>
|
媒体查询适配(推荐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| body { background-color: green; } @media screen and (min-width: 1200px ) { body { background-color: hotpink; } }
@media screen and (min-width: 761px) and (max-width: 1199px) { body { background-color: yellow; } }
@media screen and (max-width: 760px) { body { background-color: pink; } }
|
页面缩放(不推荐)
整个页面缩放
注意
如果框架的弹窗位置是通过JS计算的,那么会发生偏移,就不推荐这种方式。
有这么一个情况,项目已经开发很久了,都是按1920*1080做的,这样在小屏幕上就会显示不好看,但是换成rem就要所有页面都进行更改就太麻烦了,我们就可以使用zoom方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <div id="app_outer"> </div> <script> function resize() { const width = document.body.clientWidth; const widthZoom = width / 1920; console.info("width:" + width); console.info("widthZoom:" + widthZoom); let app_outer = document.getElementById("app_outer"); app_outer.style.zoom = widthZoom; app_outer.style.height = 100 / widthZoom + "vh"; }
window.onload = function () { resize(); }; window.onresize = function () { resize(); } </script>
|
注意
缩放后100vh就不再是窗口的高度了,要除以缩放比例。
页面中类似于
1
| height: calc(100vh - 100px);
|
也要改为
1
| height: calc(100% - 100px);
|
上面的例子是根据宽度进行适配的,当然也可以根据高度适配,直接获取高度获取到的是0,所以可以使用下面的方式。
获取窗口的高度
1 2 3 4 5 6 7 8 9
| function getClientHeight() { let clientHeight = 0; if (document.body.clientHeight && document.documentElement.clientHeight) { clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight); } else { clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight); } return clientHeight; }
|
内部缩放
如果内部的宽高是确定的,但是会大于外层的DIV,我们想自适应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ZOOM</title> </head> <body> <div id="outer_div"> <div id="inner_div"></div> </div> <script> function resize() { const width = document.getElementById("outer_div").offsetWidth; const zoom = width / 1920; console.info("width:" + width); console.info("zoom:" + zoom); let inner_div = document.getElementById("inner_div"); inner_div.style.zoom = zoom; }
window.onload = function () { resize(); };
window.onresize = function () { resize(); } </script>
<style> body { margin: 0; padding: 0; }
#outer_div { background: red; width: 100vw; height: 100vh; overflow: hidden; }
#inner_div { background: #0a9caf; width: 1920px; height: 1080px; } </style> </body> </html>
|
图片适配
如果尺寸的比例不一样 那么图片就会变形
我们可以设置这个属性
1 2 3 4 5
| img { width: 100%; height: 100%; object-fit: cover; }
|
相关概念
px、em、rem
- px是固定像素,一旦设置了就无法因为适应页面而改变。
- em是rem相对于px更具有灵活性,他们是相对于长度单位的变化而变化,更适应于响应式布局。
- em相对于父元素字体大小的倍数
- rem相对于根元素字体大小的倍数
Viewport 基础
视觉窗口:Viewport是移动端特有。这是一个虚拟的区域,承载网页的。
一个常用的针对移动网页优化过的页面的 viewport meta 标签大致如下:
1
| <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0"/>
|
其中
width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)
height:和 width 相对应,指定高度
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例
maximum-scale:允许用户缩放到的最大比例
minimum-scale:允许用户缩放到的最小比例
user-scalable:用户是否可以手动缩放