postcss-px-convert
Version:
A PostCSS plugin and Node tool for converting px to rem or vw, suitable for CSS, JS, Vue, React and other scenarios.
450 lines (364 loc) • 9.88 kB
Markdown
[](https://www.npmjs.com/package/postcss-px-convert)
[](https://www.npmjs.com/package/postcss-px-convert)
[](https://github.com/chao921125/postcss-px-convert/blob/main/LICENSE)
A powerful PostCSS plugin and Node.js tool that converts px units to rem or vw in CSS, suitable for responsive mobile development.
English | [中文文档](./README.md)
- 🚀 **High Performance**: Based on the PostCSS ecosystem, fast conversion
- 🎯 **Precise Conversion**: Supports accurate value calculation and unit conversion
- 🔧 **Flexible Configuration**: Rich configuration options for various needs
- 📱 **Mobile Optimization**: Optimized for responsive mobile design
- 🛠️ **Multi-scenario Support**: Compatible with CSS, JS, Vue, React and more
- 🔌 **Plugin Ecosystem**: Provides PostCSS plugin and Vite plugin
- 📦 **Auto Generation**: Supports automatic generation and injection of flexible.js
- 🎨 **Filtering**: Supports selector, property, and file-based filtering
```bash
npm install postcss-px-convert --save-dev
```
Or with pnpm:
```bash
pnpm add postcss-px-convert --save-dev
```
Or with yarn:
```bash
yarn add postcss-px-convert --dev
```
```js
// postcss.config.js
module.exports = {
plugins: {
'postcss-px-convert': {
unitToConvert: 'rem',
rootValue: 37.5, // 1/10 of design width, 37.5 for 375px designs, 75 for 750px designs
unitPrecision: 5,
propList: ['*'], // Convert all properties
selectorBlackList: [], // Selectors to ignore
replace: true, // Replace original px after conversion
mediaQuery: false, // Convert px in media queries
minPixelValue: 1 // Values <= 1px won't be converted
}
}
}
```
```js
// postcss.config.js
module.exports = {
plugins: {
'postcss-px-convert': {
unitToConvert: 'vw',
viewportWidth: 375, // Design width
unitPrecision: 5,
propList: ['*'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
minPixelValue: 1
}
}
}
```
```js
// .postcssrc.js or postcss.config.js
module.exports = {
plugins: {
autoprefixer: {
overrideBrowserslist: ["Android >= 4.1", "iOS >= 7.1", "Chrome > 31", "ff > 31", "ie >= 8"]
},
'postcss-px-convert': {
unitToConvert: 'rem',
rootValue: 37.5,
unitPrecision: 5,
propList: ["*"],
selectorBlackList: ["ignore"],
replace: true,
mediaQuery: false,
minPixelValue: 0,
exclude: /node_modules/i
}
}
}
```
```js
// vite.config.js
import { defineConfig } from 'vite';
import postcssPxConvert from 'postcss-px-convert';
import { viteFlexibleInject } from 'postcss-px-convert';
export default defineConfig({
css: {
postcss: {
plugins: [
postcssPxConvert({
unitToConvert: 'rem',
rootValue: 37.5,
injectFlexibleScript: true
})
]
}
},
plugins: [
viteFlexibleInject()
]
});
```
```js
// postcss.config.js
import postcssPresetEnv from "postcss-preset-env";
import postcssPxConvert from "postcss-px-convert";
export default {
plugins: [
postcssPresetEnv({
autoprefixer: {
grid: true,
},
}),
postcssPxConvert({
unitToConvert: 'rem',
rootValue: 16
})
]
};
```
This configuration format is fully compatible with your example. The plugin supports standard PostCSS array format configuration.
- [API Documentation](./docs/api.en.md) - Detailed API reference | [中文](./docs/api.md)
- [Configuration Guide](./docs/configuration.en.md) - Complete configuration options | [中文](./docs/configuration.md)
- [Usage Examples](./docs/examples.en.md) - Rich examples | [中文](./docs/examples.md)
- [Contributing Guide](./docs/CONTRIBUTING.en.md) - How to contribute | [中文](./docs/CONTRIBUTING.md)
Convert px to rem or vw:
```css
/* Input */
body {
font-size: 32px;
margin: 16px;
width: 375px;
}
/* Output (rem) */
body {
font-size: 0.85333rem;
margin: 0.42667rem;
width: 10.00000rem;
}
/* Output (vw) */
body {
font-size: 8.53333vw;
margin: 4.26667vw;
width: 100.00000vw;
}
```
Support multiple filtering methods:
```js
{
selectorBlackList: ['.ignore', /^\.ant-/], // Selector filtering
propList: ['font-size', 'margin*'], // Property filtering
exclude: [/node_modules/] // File filtering
}
```
Support different conversion rules for landscape mode:
```js
{
landscape: true,
landscapeUnit: 'vw',
landscapeWidth: 568
}
```
```js
{
injectFlexibleScript: true,
flexibleScriptPath: './public/flexible.js'
}
```
| Option | Type | Default | Description |
|------------------------|-------------------------|-----------|-----------------------|
| `unitToConvert` | `'rem' \| 'vw'` | `'rem'` | Target unit |
| `rootValue` | `number` | `16` | rem base value |
| `viewportWidth` | `number` | `375` | vw base width |
| `unitPrecision` | `number` | `5` | Unit precision |
| `minPixelValue` | `number` | `1` | Min value to convert |
| `selectorBlackList` | `(string \| RegExp)[]` | `[]` | Selector blacklist |
| `propList` | `string[]` | `['*']` | Property filter list |
| `mediaQuery` | `boolean` | `false` | Convert media queries |
| `landscape` | `boolean` | `false` | Landscape adaptation |
| `injectFlexibleScript` | `boolean` | `false` | Generate flexible.js |
For more configuration options, see the [Configuration Guide](./docs/configuration.en.md).
Recommended to set `rootValue` to 1/10 of the design draft width:
```js
// Design width 375px
{
unitToConvert: 'rem',
rootValue: 37.5
}
// Design width 750px
{
unitToConvert: 'rem',
rootValue: 75
}
```
When a project has multiple design widths (e.g., main project is based on 750px while some third-party components are based on 375px), you can set rootValue dynamically:
```js
{
unitToConvert: 'rem',
rootValue: ({ file }) => {
// Use 37.5 as base for Vant components
if (file.indexOf('node_modules/vant') !== -1) {
return 37.5;
}
// Use 75 as base for other files
return 75;
}
}
```
Use the design draft width directly:
```js
// Design width 375px
{
unitToConvert: 'vw',
viewportWidth: 375
}
```
```js
// Object syntax
{
plugins: {
'postcss-px-convert': options
}
}
// Function syntax
{
plugins: [
postcssPxConvert(options)
]
}
```
```js
// vue.config.js
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-px-convert')({
unitToConvert: 'rem',
rootValue: 37.5
})
]
}
}
}
};
```
```js
// next.config.js
const withCSS = require('@zeit/next-css');
module.exports = withCSS({
webpack: (config) => {
config.module.rules.push({
test: /\.css$/,
use: [{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-px-convert')({
unitToConvert: 'vw',
viewportWidth: 375
})
]
}
}
}]
});
return config;
}
});
```
```js
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-px-convert')({
unitToConvert: 'rem',
rootValue: ({ file }) => {
// Dynamically set rootValue
return file.indexOf('node_modules/vant') !== -1 ? 37.5 : 75;
}
})
]
}
}
}
]
}]
}
};
```
```js
import { viteFlexibleInject } from 'postcss-px-convert';
export default {
plugins: [
viteFlexibleInject({ flexibleScriptPath: '/flexible.js' })
]
}
```
```js
const { px2any } = require('postcss-px-convert');
const css = 'body { font-size: 32px; }';
const result = px2any(css, {
unitToConvert: 'rem',
rootValue: 37.5
});
```
```bash
npm test
```
Run test cases:
```bash
npm run test:watch
```
Issues and Pull Requests are welcome! Please see the [Contributing Guide](./docs/CONTRIBUTING.en.md) for details.
MIT License - See the [LICENSE](LICENSE) file for details.
- [PostCSS](https://postcss.org/)
- [Vite](https://vitejs.dev/)
- [amfe-flexible](https://github.com/amfe/lib-flexible)
---
If this project helps you, please give it a ⭐️!