作为一个前端工程师,适配不同显示器的分辨率算是基本功了,大到各种显示器:2k屏,1920,1280,小到各种手机尺寸,不适配的话界面必定混乱,在前端来说算是bug了,目前主流的适配方式为rem和vw,vh,微信小程序的话直接rpx更方便
为何选用rem而不选用vw,vh
vw,vh的利弊
vw,vh是指把屏幕分成100等份,横屏不论多大,都为100vw,竖屏不论多长都为100vh,操作时可以换算,例如一个375px的设计稿,1vw即为375/100=3.75px,假如一个width为100px的盒子,则长度为100/375 × 100 =26.66 vw
这样就该盒子不论在哪个屏幕,长度都为100份中的26.66份,相当于375中的100,这样尺寸就对上了
rem的利弊
rem是指根字体的大小,即html的font-size,假如html的根字体大小为16px,则rem=16px,所以实现rem的关键就是根据屏幕尺寸设置根字体大小,再根据"根字体"大小转化实际尺寸
实现原理其实跟vw差不多,先把屏幕分为n份rem(n可以随意,主流为10,15,20),这里以10份为例,设置根字体rem的大小为 屏幕尺寸/10
- 假如分辨率为375,则10rem=375px,即1rem为375/10=37.5px,一份375的设计稿100px,就应该为100/(375/10)= 2.66rem
- 假如分辨率为414,则10rem=414px,即1rem为414/10=41.4px,2.66rem为41.4*2.66=110.1px
- 假如分辨率为750,则10rem=750px,即1rem为750/10=75px,2.66rem为75*2.66=199.5≈200px
即不论在什么界面,长度都为2.66rem,所以关键就是设置rem的值,即根字体大小
选择rem的原因
vw非常简单并且好用,这是优点,但只限于移动端
vw在PC端有个很大的缺点,必须每个设置最小值,否则当窗口拉取到很小的时候,就得变形,甚至有时移动端也需要大量的设置最小值,同时也会有最大值的需求,如果有大佬有能一次性设置最值的方式,欢迎交流沟通
rem前期设置更麻烦,但配置好了,不会有最大最小界面的问题
只需要设置一个最大的rem和最小的rem,即可保证界面的最大状态是最小状态
rem适配的3种方式
一、媒体查询,根据屏幕尺寸,设置rem的值
假设目前需要适配移动端320,360,375,1920的分辨率,才用scss,设置一个变量$no为10,用于分10份,
- @media---开启媒体查询
- screen---查询的类型(屏幕宽度)
- max-width最大值
- min-width最小值
global.scss,在main.js中引入
$no: 10;
//表示宽度最大值为320的情况下,设置rem为 320/10 px,即32px
//所以只要小于320px,统一rem为32px,这样就设置了最小值
@media screen and (max-width: 320px) {
html {
font-size: 320px / $no
}
}
//表示宽度最小值为320的情况下,设置rem为 320/10 px,即32px
//所以只要大于320,rem值就为32px
@media screen and (min-width: 320px) {
html {
font-size: 320px / $no
}
}
//表示宽度最小值为360的情况下,设置rem为 360/10 px,即36px
//所以只要大于等于360,rem的值就为36px
@media screen and (min-width: 320px) {
html {
font-size: 320px / $no
}
}
//下面也是同理,同时利用css下方样式的覆盖性,只要按顺序写就能保证能检测到
//表示宽度最小值为375的情况下,设置rem为 375/10 px,即37.5px
//所以只要大于等于375,rem的值就为37.5px
@media screen and (min-width: 375px) {
html {
font-size: 375px / $no
}
}
//PC端适配--使用pc端的分辨率就行
@media screen and (min-width: 1920px) {
html {
font-size: 1920px / $no
}
}
//最后设置个最大值,max-width: 1920px--->最大值为1920px
//只要小于1920px,统一rem为192px,这样就设置了最大值
@media screen and (max-width: 1920px) {
html {
font-size: 1920px / $no
}
}
最后在网页中使用rem做单位,假如100px在375px中长度就用2.66rem做单位(有插件可以转换,下文介绍)
.box {
width: 2.66rem;
height: 2.66rem;
}
二、媒体查询+flexible.js
flexible.js就是手淘团队推出转化rem的方法,复制引用就好,原理就是给每个html标签添加个行内样式
style="font-size: xxx px "
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
//这里也是设置的份数,也是用10
// set 1rem = viewWidth / 10
// 把屏幕平均分成10等份。比如1920/10= 192 px,这个时候1rem就是192px,配合vscod插件快速适配,在style中使用媒体查询。
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
在main.js引入
import '@/utils/flexible'
设置最大值和最小值,加个important,提升权重
@media screen and (max-width: 320px) {
html {
font-size: 320px / $no!important
}
}
@media screen and (max-width: 1920px) {
html {
font-size: 1920px / $no !important
}
}
插件转化的问题
vscode安装cssrem插件
找到设置根字体大小的地方,假设设计稿为1920,设置为10等份,那根字体大小就为1920/10=192,之后写css的时候,只要写 xx px,即会有转化rem选项
三、postcss-pxtorem插件自动转化
安装
可能会有版本问题,遇到可以安装postcss-pxtorem@5.1.1
npm install postcss postcss-pxtorem --save-dev
配置
在你的项目根目录中创建一个 postcss.config.js
文件,并添加以下配置:
//配置自行选择使用,rootValue和propList应该为必选项
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5, // 表示根元素字体大小或根据input参数返回根元素字体大小
propList: ['*'], // 可以从px更改为rem的属性, 通配符*表示启用所有属性
selectorBlackList: ['.norem'], // 过滤掉.norem开头的class,不进行rem转换
replace: true, // 是否直接替换原来的 px 单位
mediaQuery: false, // 是否转换媒体查询中的 px
minPixelValue: 1// 设置要替换的最小像素值
}
}
}
创建utils/rem.js,在main.js中引入,之后直接使用单位px,会自动转化
// 配置基本大小
let baseSize = 37.5;
// 设置 rem 函数
function setRem () {
//当前页面宽度相对于375px屏幕宽的缩放比例,可根据自己需要修改。
let scale = document.documentElement.clientWidth / 375;
//设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,即最大根字体大小为37.5*2=75,可根据实际业务需求调整)
let fz = baseSize * Math.min(scale, 2)
//获得根字体大小后,给全部页面设置根字体大小
//业务需要限制显示页面的最小值,我这里是根据倍数限制的,因为1倍的字体大小为37.5,具体情况可以自己设定
document.documentElement.style.fontSize = scale >= 1 ? fz + 'px' : 37.5 + 'px'
}
setRem(); //初始化
// 适配 - 重置函数
function resetRem (num) {
if (num) baseSize = Number(num);
setRem();
}
window.resetRem = resetRem; // 全局可调用(其他方式也可)
// 改变窗口大小时重置 rem
window.onresize = function () {
setRem()
};
三种方式都可以实现适配,个人感受如下:
- 第一种比较原生,每多适配一个就得多写一个媒体查询
- 第二种属于第一种的进阶版
- 第三种为插件转化,更方便,但可能会有版本兼容的问题
(封面来源于网络,如有侵权,请联系删除)