当前位置: 首页 > news >正文

PostCSS通过px2rem插件和lib-flexible将px单位转换为rem(root em)单位实现大屏适配

目录

    • 文档
    • postcss中使用postcss-plugin-px2rem
      • 安装postcss-plugin-px2rem
      • 示例
      • 默认配置
    • webpack中使用postcss-plugin-px2rem
      • 项目结构
      • 安装依赖
      • 文件内容
    • 大屏适配
    • 参考文章

文档

类似的插件

  • postcss-plugin-px2rem

    • https://www.npmjs.com/package/postcss-plugin-px2rem
    • https://github.com/pigcan/postcss-plugin-px2rem
  • postcss-pxtorem

    • https://www.npmjs.com/package/postcss-pxtorem
    • https://github.com/cuth/postcss-pxtorem
  • postcss-px2rem

    • https://www.npmjs.com/package/postcss-px2rem

amfe-flexible
lib-flexible

postcss中使用postcss-plugin-px2rem

安装postcss-plugin-px2rem

pnpm install postcss postcss-plugin-px2rem --save-dev

依赖 package.json

{"type": "module","dependencies": {"postcss": "^8.4.31","postcss-plugin-px2rem": "^0.8.1"}
}

示例

main.js

import { writeFileSync, readFileSync } from "fs";
import postcss from "postcss";
import pxtorem from "postcss-plugin-px2rem";const css = readFileSync("./style.css", "utf8");// 修改默认配置
const options = {};const processedCss = postcss(pxtorem(options)).process(css).css;writeFileSync("./style.rem.css", processedCss);

输入 style.css

h1 {margin: 0 0 20px;font-size: 32px;line-height: 1.2;letter-spacing: 1PX; /* ignored */
}

输出 style.rem.css

h1 {margin: 0 0 0.2rem;font-size: 0.32rem;line-height: 1.2;letter-spacing: 1PX;
}

默认配置

{rootValue: 100,unitPrecision: 5,propWhiteList: [],propBlackList: [],exclude:false,selectorBlackList: [],ignoreIdentifier: false,replace: true,mediaQuery: false,minPixelValue: 0
}

webpack中使用postcss-plugin-px2rem

项目结构

$ tree -I node_modules
.
├── package.json
├── src
│   ├── index.js
│   └── style.css
└── webpack.config.cjs

安装依赖

pnpm install webpack webpack-cli style-loader css-loader postcss-loader mini-css-extract-plugin --save-dev

完整依赖 package.json

{"type": "module","scripts": {"build": "webpack"},"devDependencies": {"css-loader": "^6.8.1","mini-css-extract-plugin": "^2.7.6","postcss": "^8.4.31","postcss-loader": "^7.3.3","postcss-plugin-px2rem": "^0.8.1","style-loader": "^3.3.3","webpack": "^5.89.0","webpack-cli": "^5.1.4"}
}

文件内容

webpack.config.cjs

"use strict";const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");module.exports = {// 生产环境mode: "production",// 打包入口entry: {index: "./src/index.js",},// 指定输出地址及打包出来的文件名output: {path: path.join(__dirname, "dist"),filename: "index.js",},module: {rules: [{test: /\.css$/i,use: [MiniCssExtractPlugin.loader,"css-loader",{loader: "postcss-loader",options: {postcssOptions: {plugins: [["postcss-plugin-px2rem",// 配置参数{rootValue: 100,},],],},},},],},],},plugins: [// 将 CSS 提取到单独的文件中new MiniCssExtractPlugin(),],
};

入口文件 index.js

import "./style.css";

样式文件 style.css

h1 {margin: 0 0 20px;font-size: 32px;line-height: 1.2;letter-spacing: 1PX; /* ignored */
}

运行打包

$ npm run build

输出结果

h1 {margin: 0 0 0.2rem;font-size: 0.32rem;line-height: 1.2;letter-spacing: 1PX; /* ignored */
}

大屏适配

原理

  • 打包阶段:根据设计稿的尺寸编写css代码(px为单位),将css代码转为rem为单位的数据
  • 浏览器运行阶段:根据根节点root的字体大小,将rem为单位的尺寸还原为px单位

引入文件:lib-flexible.js

因为lib-flexible.js 原本是用来适配移动端的,所以,需要改动一些代码才能适配PC大屏,只能通过整个文件引入,不要通过npm安装,否则每次安装都需要重新修改代码

需要改动的代码如下

function refreshRem() {var width = docEl.getBoundingClientRect().width;// 适配移动端// if (width / dpr > 540) {//   width = 540 * dpr;// }// 适配PC端// 最小宽度1200px// if (width / dpr < 1200) {//   width = 1200 * dpr;// }// 根据这个值计算postcss-plugin-px2rem的配置参数 rootValue// 设置px->rem的比例是:100// var rem = width / 10;var rem = width / 100;docEl.style.fontSize = rem + "px";flexible.rem = win.rem = rem;}

这里可以设置一个最小宽度,配置页面也设置一个最小宽度,避免屏幕过小而变形

body{min-width: 1200px;
}

完整代码

/*** lib-flexible* Version 0.3.2* https://www.npmjs.com/package/lib-flexible?activeTab=code*/
(function (win, lib) {var doc = win.document;var docEl = doc.documentElement;var metaEl = doc.querySelector('meta[name="viewport"]');var flexibleEl = doc.querySelector('meta[name="flexible"]');var dpr = 0;var scale = 0;var tid;var flexible = lib.flexible || (lib.flexible = {});if (metaEl) {console.warn("将根据已有的meta标签来设置缩放比例");var match = metaEl.getAttribute("content").match(/initial\-scale=([\d\.]+)/);if (match) {scale = parseFloat(match[1]);dpr = parseInt(1 / scale);}} else if (flexibleEl) {var content = flexibleEl.getAttribute("content");if (content) {var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);if (initialDpr) {dpr = parseFloat(initialDpr[1]);scale = parseFloat((1 / dpr).toFixed(2));}if (maximumDpr) {dpr = parseFloat(maximumDpr[1]);scale = parseFloat((1 / dpr).toFixed(2));}}}if (!dpr && !scale) {var isAndroid = win.navigator.appVersion.match(/android/gi);var isIPhone = win.navigator.appVersion.match(/iphone/gi);var devicePixelRatio = win.devicePixelRatio;if (isIPhone) {// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {dpr = 3;} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {dpr = 2;} else {dpr = 1;}} else {// 其他设备下,仍旧使用1倍的方案dpr = 1;}scale = 1 / dpr;}docEl.setAttribute("data-dpr", dpr);if (!metaEl) {metaEl = doc.createElement("meta");metaEl.setAttribute("name", "viewport");metaEl.setAttribute("content","initial-scale=" +scale +", maximum-scale=" +scale +", minimum-scale=" +scale +", user-scalable=no");if (docEl.firstElementChild) {docEl.firstElementChild.appendChild(metaEl);} else {var wrap = doc.createElement("div");wrap.appendChild(metaEl);doc.write(wrap.innerHTML);}}function refreshRem() {var width = docEl.getBoundingClientRect().width;// 适配移动端// if (width / dpr > 540) {//   width = 540 * dpr;// }// 适配PC端// 最小宽度1200px// if (width / dpr < 1200) {//   width = 1200 * dpr;// }// 根据这个值计算postcss-plugin-px2rem的配置参数 rootValue// 设置px->rem的比例是:100// var rem = width / 10;var rem = width / 100;docEl.style.fontSize = rem + "px";flexible.rem = win.rem = rem;}win.addEventListener("resize",function () {clearTimeout(tid);tid = setTimeout(refreshRem, 300);},false);win.addEventListener("pageshow",function (e) {if (e.persisted) {clearTimeout(tid);tid = setTimeout(refreshRem, 300);}},false);if (doc.readyState === "complete") {doc.body.style.fontSize = 12 * dpr + "px";} else {doc.addEventListener("DOMContentLoaded",function (e) {doc.body.style.fontSize = 12 * dpr + "px";},false);}refreshRem();flexible.dpr = win.dpr = dpr;flexible.refreshRem = refreshRem;flexible.rem2px = function (d) {var val = parseFloat(d) * this.rem;if (typeof d === "string" && d.match(/rem$/)) {val += "px";}return val;};flexible.px2rem = function (d) {var val = parseFloat(d) / this.rem;if (typeof d === "string" && d.match(/px$/)) {val += "rem";}return val;};
})(window, window["lib"] || (window["lib"] = {}));

webpack参数设置

{loader: "postcss-loader",options: {postcssOptions: {plugins: [["postcss-plugin-px2rem",// 配置参数{// 假设设计稿是1200px, px->rem的比例是:100// 1200 / 100 = 12rootValue: 12,},],],},},
},

比如:

设计稿尺寸为1200px

.box {width: 300px;height: 100px;background-color: green;font-size: 32px;line-height: 1.2;letter-spacing: 1px; /* ignored */
}

转换结果是

.box {width: 25rem;height: 8.33333rem;background-color: green;font-size: 2.66667rem;line-height: 1.2;letter-spacing: 0.08333rem; /* ignored */
}

在尺寸为1200px的屏幕宽度下,可以还原为代码中设置的尺寸

width: 25rem + 12px =  300px

在这里插入图片描述

在尺寸为1400px的屏幕宽度下,可以还原为代码中设置的尺寸

width: 25rem + 14px =  350px

在这里插入图片描述
这样,在不同的屏幕下,计算出来的根元素font-size就不一样,进而导致页面元素的尺寸也不一样,实现了缩放效果

需要注意的是,这个缩放是基于宽度缩放的,如果屏幕尺寸比例不一致,会导致竖向的内容会缺失,或者出现滚动

完整代码:https://github.com/mouday/webpack-lib-flexible

参考文章

  1. https://webpack.docschina.org/plugins/mini-css-extract-plugin
  2. https://webpack.docschina.org/loaders/postcss-loader/
  3. 使用lib-flexible和postcss-pxtorem解决大屏适配问题

相关文章:

PostCSS通过px2rem插件和lib-flexible将px单位转换为rem(root em)单位实现大屏适配

目录 文档postcss中使用postcss-plugin-px2rem安装postcss-plugin-px2rem示例默认配置 webpack中使用postcss-plugin-px2rem项目结构安装依赖文件内容 大屏适配参考文章 文档 类似的插件 postcss-plugin-px2rem https://www.npmjs.com/package/postcss-plugin-px2remhttps://g…...

什么是缓冲区溢出?

缓冲区溢出 1. 什么是缓冲区溢出2. 缓冲区溢出攻击的类型3. 攻击者如何利用缓冲区溢出4. 如何防止缓冲区溢出攻击 1. 什么是缓冲区溢出 &#xff08;1&#xff09;缓冲区 缓冲区是一块连续的计算机内存区域&#xff0c;用于在将数据从一个位置移到另一位置时临时存储数据。这…...

论文浅尝 | ChatKBQA:基于微调大语言模型的知识图谱问答框架

第一作者&#xff1a;罗浩然&#xff0c;北京邮电大学博士研究生&#xff0c;研究方向为知识图谱与大语言模型协同推理 OpenKG地址&#xff1a;http://openkg.cn/tool/bupt-chatkbqa GitHub地址&#xff1a;https://github.com/LHRLAB/ChatKBQA 论文链接&#xff1a;https://ar…...

软件测试的目的---防范项目风险

软件测试的目的到底是什么一直是困扰开发人员和测试人员的一个问题, 项目管理人员希望测试能够保证软件项目的成功 开发人员希望希望测试可以让他们理直气壮的说,他们的软件是没有问题的,从而证明他们的工作成果 软件测试经典理论说,测试无法证明软件是没有问题,而只能证明软…...

自己动手写编译器:创建由 C 语言编译而成的语法解析器

在上一章节&#xff0c;我们完成了由 c 语言设计的输入系统&#xff0c;本节我们看看如何在前一节的基础上完成一个由 c 语言设计并编译出来的词法解析器。整个解析器的基本设计思路是&#xff1a; 1&#xff0c;由我们上一节设计的输入系统将字符串从文件中读入。 2&#xff0…...

接口设计-增删改查

关于增删改查的 接口设计&#xff0c;比较简单&#xff0c;有一些固定的做法可以使用。 查询列表 查询列表的接口&#xff0c;带上分页的入参&#xff1a; pageNo&#xff0c;pageSize&#xff0c;非必选&#xff0c;并设置默认值。 入参为 dto&#xff0c;根据 dto 从数据库…...

持续持续集成部署-k8s-配置与存储-配置管理:Secret 的应用

持续持续集成部署-k8s-配置与存储-配置管理:Secret 的应用 1. 简介2. 创建 Secret3. docker-registry 的使用1. 简介 与 ConfigMap 类似,用于存储配置信息,但是主要用于存储敏感信息、需要加密的信息,Secret 可以提供数据加密、解密功能。 在创建 Secret 时,要注意如果要…...

ZYNQ7020开发(一):开发环境搭建

文章目录 一、配置Ubuntu 编译环境二、安装Petalinux三、安装JTAG驱动四、安装Vitis一、配置Ubuntu 编译环境 虚拟机环境:VMware Workstation 16 Pro 16.1.0 build-17198959Ubuntu 版本:No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.6 L…...

Spring Boot插件化开发概念原理及实现

Spring Boot 是一个开源的Java框架&#xff0c;它简化了基于Spring框架的应用程序的开发和部署过程。它提供了一种快速、简单的方式来构建独立的、可执行的Spring应用程序。在Spring Boot中&#xff0c;插件化开发是一种强大的开发模式&#xff0c;它允许开发人员将应用程序的不…...

Ps:PSDT 模板文件

自 Photoshop CC 2015.5 版以后&#xff0c;Ps 中新增了一种文件格式&#xff1a;.PSDT。 说明&#xff1a; PSD、PDD、PSDT 都是 Ps 的专用文件格式&#xff0c;需要继续在 Ps 中进行编辑的文件可存为此类格式。 PSD Photoshop document Photoshop 默认文档格式&#xff0c;支…...

Linux-----nginx的简介,nginx搭载负载均衡以及nginx部署前后端分离项目

目录 nginx的简介 是什么 nginx的特点以及功能 Nginx负载均衡 下载 安装 负载均衡 nginx的简介 是什么 Nginx是一个高性能的开源Web服务器和反向代理服务器。它的设计目标是为了解决C10k问题&#xff0c;即在同一时间内支持上万个并发连接。 Nginx采用事件驱动的异…...

presto插件机制揭秘:探索无限可能的数据处理舞台

文章目录 1. 前言2. Presto插件架构3. Plugin接口3.1 插件协议3.2 插件实现类 4. 插件加载过程4.1 PluginManager 5. 插件应用6. 总结 关键词&#xff1a;Presto Plugin 1. 前言 本文源码环境&#xff1a; presto: prestoDb 0.275版本 在Presto框架中插件机制设计是一种非常常见…...

acwing算法基础之数据结构--并查集算法

目录 1 基础知识2 模板3 工程化 1 基础知识 并查集支持O(1)时间复杂度实现&#xff1a; 将两个集合合并。询问两个元素是否在一个集合中。 基本原理&#xff1a;每个集合用一颗树来表示。树根的编号就是整个集合的编号。每个结点存储它的父结点&#xff0c;p[x]表示x的父结点…...

k8s:二进制搭建 Kubernetes v1.20

目录 1 操作系统初始化配置 2 部署 etcd 集群 2.1 准备签发证书环境 2.2 生成Etcd证书 3 部署 docker引擎 4 部署 Master 组件 5 部署 Worker Node 组件 k8s集群master01&#xff1a;192.168.30.105 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集…...

SpringBoot系列-1启动流程

背景 本文作为SpringBoot系列的开篇&#xff0c;介绍SpringBoot的启动流程&#xff0c;包括Spring容器和Tomcat启动过程。SpringBoot作为流行的微服务框架&#xff0c;其是基于约定和自动装配机制对Spring的封装和增强。 由于前面的Spring系列对Spring容器已经进行了较为细致的…...

【记】一次common模块导入无效的bug

首先Maven clean install无用 然后idea清除缓存重启无用 pom.xml文件重载无效 正确解决路径&#xff1a; 1.检查common模块的父工程导入和自身模块的声明是否正确 默认是继承父工程的groupid&#xff0c;可以不用再声明 2.检查子工程是否引入正确的common&#xff0c;org不要…...

1.Netty概述

原生NIO存在的问题(Netty要解决的问题) 虽然JAVA NIO 和 JAVA AIO框架提供了多路复用IO/异步IO的支持&#xff0c;但是并没有提供给上层“信息格式”的良好封装。JAVA NIO 的 API 使用麻烦,需要熟练掌握 ByteBuffer、Channel、Selector等 , 所以用这些API实现一款真正的网络应…...

YOLO目标检测——真实道路车辆检测数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;自动驾驶技术研发、交通安全监控数据集说明&#xff1a;真实道路车辆检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、coco(j…...

【Solidity】Solidity中的基本数据类型和复合数据类型

1. 基本数据类型 1.1 整数类型 Solidity支持有符号整数和无符号整数&#xff0c;可以指定位数和范围。以下是一些整数类型的示例&#xff1a; int&#xff1a;有符号整数&#xff0c;可以是正数或负数。2&#xff0c;-45&#xff0c;2023 uint&#xff1a;无符号整数&#x…...

Flutter Set存储自定义对象时 如何保证唯一

在Flutter中&#xff0c;Set和List是两种不同的集合类型&#xff0c;List中存储的元素可以重复&#xff0c;Set中存储的元素不可重复。 如果你想在Set中存储自定义对象&#xff0c;你需要确保对象的唯一性。 这可以通过在自定义类中实现hashCode方法和equals方法来实现。 has…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...