A PostCSS plugin that processes CSS unit values through a user-defined function. Use it to convert units (e.g. px to rem, px to vw), scale values, or apply any custom transformation to CSS numeric values.
- Process any CSS unit (
px,rem,vw,em,%, etc.) with a custom function - Filter by property name with wildcard and negation patterns
- Filter by unit type
- Skip specific selectors via blacklist
- Support for media query processing
- Support for custom/non-standard units (e.g.
rpx,dp) - Exclude files by path string, regex, or function
- Optionally append fallback values instead of replacing
npm install postcss postcss-unit-processor --save-devconst postcss = require('postcss');
const unitProcessor = require('postcss-unit-processor');
postcss([
unitProcessor({
processor: (value, unit) => {
if (unit === 'px') {
return value / 16; // returns a number, unit stays px
}
}
})
]).process(css).css;The processor function receives the numeric value and unit name, and returns the new value. If nothing is returned (or undefined), the original value is kept unchanged.
The core of the plugin. It is called for every matched unit value.
processor(value, unit, node, root)| Parameter | Type | Description |
|---|---|---|
value |
Number |
The numeric value |
unit |
String |
The unit name (e.g. 'px') |
node |
Object |
The current PostCSS node |
root |
Object |
The PostCSS root node |
Return value:
- Return a
Number— replaces the value, keeps the original unit - Return an
Object{ value, unit }— replaces both value and unit; ifvaluecannot be parsed as a number (e.g.undefined,NaN), it is treated as0 - Return
undefined/ nothing — keeps the original value unchanged
// Return a number: value changes, unit stays the same
processor: (value, unit) => value / 16
// 32px → 2px (unit stays px, only the number changes)
// Return an object: both value and unit change
processor: (value, unit) => ({ value: value / 16, unit: 'rem' })
// 32px → 2rem (both value and unit change)
// Return nothing: no change
processor: (value, unit) => {
if (unit === 'px') return value / 16;
// other units: implicitly returns undefined, no change
}unitProcessor({
processor: (value, unit) => {
if (unit === 'px') {
return {
value: value / 16,
unit: 'rem'
};
}
}
})Input/Output:
/* input */
h1 {
font-size: 32px;
margin: 0 0 16px;
border: 1px solid #ccc;
}
/* output */
h1 {
font-size: 2rem;
margin: 0 0 1rem;
border: 0.0625rem solid #ccc;
}unitProcessor({
processor: (value, unit) => {
if (unit === 'px') {
return {
value: (value / 375) * 100,
unit: 'vw'
};
}
}
})unitProcessor({
processor: (value, unit) => {
if (unit === 'px') {
return value / 2;
}
}
})Input/Output:
/* input */
h1 {
margin: 0 0 20px;
font-size: 32px;
line-height: 1.2;
letter-spacing: 1px;
}
/* output */
h1 {
margin: 0 0 10px;
font-size: 16px;
line-height: 1.2;
letter-spacing: 0.5px;
}unitProcessor({
replace: false,
processor: (value, unit) => {
if (unit === 'px') {
return {
value: value / 16,
unit: 'rem'
};
}
}
})/* input */
.box {
font-size: 16px;
}
/* output */
.box {
font-size: 16px;
font-size: 1rem;
}{
processor: (value) => value, // default: identity function
unitPrecision: 5,
propList: ['*'],
unitList: ['*'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
exclude: /node_modules/i,
customUnitList: []
}Type: Function
The unit processing function. See processor Function above.
Type: Number
Default: 5
Decimal places to round the processed value to.
Type: Array
Default: ['*']
Which units to pass to the processor function.
// All units (default)
unitList: ['*']
// Only px
unitList: ['px']
// px and rem
unitList: ['px', 'rem']
// All units except rem
unitList: ['*', '!rem']Type: Array
Default: ['*']
Which CSS properties to process.
// All properties (default)
propList: ['*']
// Only font-size
propList: ['font-size']
// All properties except letter-spacing
propList: ['*', '!letter-spacing']
// Properties containing "size"
propList: ['*size*']
// Properties starting with "font"
propList: ['font*']
// Properties ending with "width"
propList: ['*width']Type: Array
Default: []
Selectors to skip. Accepts strings (substring match) or regular expressions.
selectorBlackList: ['.ignore', /^\.no-convert/]/* .ignore matches the blacklist, skipped */
.ignore { font-size: 16px; } /* → 16px (unchanged) */
/* normal selector, processed */
.convert { font-size: 16px; } /* → processed by your processor function */Type: Boolean
Default: true
true— replace the original valuefalse— insert the processed value as a new declaration after the original (useful for fallbacks)
Type: Boolean
Default: false
Whether to process values inside @media queries.
// Enable media query processing
mediaQuery: true/* input */
@media (max-width: 768px) { ... }
/* output (with px→rem processor) */
@media (max-width: 48rem) { ... }Type: String | RegExp | Function
Default: /node_modules/i
File paths to exclude from processing.
// String: skip files whose path contains this string
exclude: 'src/legacy'
// RegExp
exclude: /\/legacy\//i
// Function
exclude: (filePath) => filePath.includes('legacy')Type: Array
Default: []
Additional non-standard units to recognize and process (e.g. rpx used in WeChat Mini Programs, dp used in Android).
customUnitList: ['rpx', 'dp']Only strings consisting entirely of letters (a-z, A-Z) or the % character are accepted. Invalid entries are silently ignored.
Default recognized units: px, pt, pc, cm, mm, in, %, em, rem, ch, vh, vw, vmin, vmax, ex
// vite.config.js
import unitProcessor from 'postcss-unit-processor';
export default {
css: {
postcss: {
plugins: [
unitProcessor({
processor: (value, unit) => {
if (unit === 'px') {
return {
value: value / 16,
unit: 'rem'
};
}
}
})
]
}
}
};// postcss.config.js
module.exports = {
plugins: [
require('postcss-unit-processor')({
processor: (value, unit) => {
if (unit === 'px') {
return {
value: value / 16,
unit: 'rem'
};
}
}
})
]
};const gulp = require('gulp');
const postcss = require('gulp-postcss');
const unitProcessor = require('postcss-unit-processor');
gulp.task('css', () => {
return gulp.src('src/**/*.css')
.pipe(postcss([
unitProcessor({
processor: (value, unit) => {
if (unit === 'px') {
return value / 2;
}
}
})
]))
.pipe(gulp.dest('dist'));
});MIT