前端自适应方案
-
基于rem的适配方案
-
rem: 指相对于根元素的字体大小的单位,在日常开发过程中我们通常把根元素(html/body)的字体设置为10px,方便于我们计算(此时子元素的1rem就相当于10px)
-
适用场景: 不固定宽高比的Web应用,适用于绝大部分业务场景
-
使用方式
- 安装依赖
npm i postcss-pxtorem autoprefixer amfe-flexible --save-dev
注:postcss-pxtorem 是PostCSS的插件,用于将像素单元生成rem单位 autoprefixer 浏览器前缀处理插件 amfe-flexible 可伸缩布局方案 替代了原先的
lib-flexible
选用了当前众多浏览器兼容的viewport
- 项目根目录创建
postcss.config.js
文件
module.exports = { plugins: { autoprefixer: { overrideBrowserslist: [ "Android 4.1", "iOS 7.1", "Chrome > 31", "ff > 31", "ie >= 8", "last 10 versions", // 所有主流浏览器最近10版本用 ], grid: true, }, "postcss-pxtorem": { rootValue: 192, // 设计稿宽度的1/ 10 例如设计稿按照 1920设计 此处就为192 propList: ["*", "!border"], // 除 border 外所有px 转 rem selectorBlackList: [".el-"], // 过滤掉.el-开头的class,不进行rem转换 }, }, };
main.ts/js
文件中导入依赖
import "amfe-flexible/index.js";
- 项目重启即可
- **建议:**vscode安装 px to rem & rpx & vw (cssrem)插件,同时在vscode左上角的文件 – 首选项 – 设置(左下角管理 – 设置) – 输入框输入“root”,找到 "基准font-size "更改为192,然后在就能够根据视觉稿中的像素值进行自动转化rem值。
-
-
基于scale的适配方案
-
在CSS3中,我们可以使用transform属性的scale()方法来实现元素的缩放效果。缩放,指的是“缩小”和“放大”的意思。
-
transform: scaleX(x); / 沿x轴方向缩放/
-
transform: scaleY(y); / 沿y轴方向缩放/
-
transform: scale(); / 同时沿x轴和y轴缩放/
-
适用场景:固定宽高比的Web应用,如大屏或者固定窗口业务应用
-
使用方式(Vue2)
- 新建
resize.ts/js
文件
// * 设计稿尺寸(px) const baseWidth = 1920; const baseHeight = 1080; const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5)); export default { data() { return { screenRef: '', // * 指向最外层容器 timer: 0, // 定时函数 scale: { width: "1", height: "1", }, // 默认缩放值 baseProportion, } }, methods: { // * 需保持的比例(默认1.77778) calcRate() { // 当前宽高比 const currentRate = parseFloat( (window.innerWidth / window.innerHeight).toFixed(5) ); if (this.screenRef) { if (currentRate > this.baseProportion) { // 表示更宽 this.scale.width = ( (window.innerHeight * this.baseProportion) / baseWidth ).toFixed(5); this.scale.height = (window.innerHeight / baseHeight).toFixed(5); this.screenRef.style.transform = `this.(${scale.width}, ${this.scale.height})`; } else { // 表示更高 this.scale.height = ( window.innerWidth / this.baseProportion / baseHeight ).toFixed(5); this.scale.width = (window.innerWidth / baseWidth).toFixed(5); this.screenRef.style.transform = `scale(${this.scale.width}, ${this.scale.height})`; } } }, resize() { clearTimeout(this.timer); this.timer = window.setTimeout(() => { this.calcRate(); }, 200); }, // 改变窗口大小重新绘制 windowDraw() { window.addEventListener("resize", this.resize); }, // 改变窗口大小重新绘制 unWindowDraw() { window.removeEventListener("resize", this.resize); }, }, }
- 相关界面引入
resize.ts/js
<script> import windowResize from './minxins/resize'; export default { name: 'App', components: {}, mixins: [windowResize], data() { return {} }, mounted() { // 监听浏览器窗口尺寸变化 this.windowDraw() this.calcRate() }, destroyed() { this.unWindowDraw(); }, } </script>
-
注意:如果是通过mixins的方法引入,需要在main.js文件加入下面代码:
import minxins from './minxins/resize'; Vue.use(minxins);
- 新建
-
使用方式(Vue3)
- 新建
resize.ts/js
文件
import { ref } from "vue"; export default function windowResize() { // * 指向最外层容器 const screenRef = ref(); // * 定时函数 const timer = ref(0); // * 默认缩放值 const scale = { width: "1", height: "1", }; // * 设计稿尺寸(px) const baseWidth = 1920; const baseHeight = 1080; // * 需保持的比例(默认1.77778) const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5)); const calcRate = () => { // 当前宽高比 const currentRate = parseFloat( (window.innerWidth / window.innerHeight).toFixed(5) ); if (screenRef.value) { if (currentRate > baseProportion) { // 表示更宽 scale.width = ( (window.innerHeight * baseProportion) / baseWidth ).toFixed(5); scale.height = (window.innerHeight / baseHeight).toFixed(5); screenRef.value.style.transform = `scale(${scale.width}, ${scale.height})`; } else { // 表示更高 scale.height = ( window.innerWidth / baseProportion / baseHeight ).toFixed(5); scale.width = (window.innerWidth / baseWidth).toFixed(5); screenRef.value.style.transform = `scale(${scale.width}, ${scale.height})`; } } }; const resize = () => { clearTimeout(timer.value); timer.value = window.setTimeout(() => { calcRate(); }, 200); }; // 改变窗口大小重新绘制 const windowDraw = () => { window.addEventListener("resize", resize); }; // 改变窗口大小重新绘制 const unWindowDraw = () => { window.removeEventListener("resize", resize); }; return { screenRef, calcRate, windowDraw, unWindowDraw, }; }
- 相关界面引入
resize.ts/js
<template> <div class="screen-container"> <div class="screen-content" ref="screenRef"> <span class="screen-title">基于scale的适配方案</span> <img class="screen-img" src="https://img2.baidu.com/it/u=1297807229,3828610143&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281" alt=""> </div> </div> </template> <script setup lang="ts"> import windowResize from '../../utils/resize'; import {onMounted, onUnmounted} from 'vue'; const { screenRef, calcRate, windowDraw, unWindowDraw } = windowResize() onMounted(() => { // 监听浏览器窗口尺寸变化 windowDraw() calcRate() }) onUnmounted(() => { unWindowDraw(); }) </script> <style lang="scss" scoped> .screen-container { height: 100%; background-color: lightcyan; display: flex; justify-content: center; align-items: center; .screen-content { width: 1920px; height: 1080px; background-color: #fff; display: flex; justify-content: center; align-items: center; flex-direction: column; .screen-title { font-size: 32px; } .screen-img { margin-top: 20px; } } } </style>
- 新建
-