Skip to content

hex-ci/postcss-unit-processor

Repository files navigation

postcss-unit-processor

npm version codecov Downloads

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.

Features

  • 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

Install

npm install postcss postcss-unit-processor --save-dev

Usage

const 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.

processor Function

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; if value cannot be parsed as a number (e.g. undefined, NaN), it is treated as 0
  • 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
}

Examples

px to rem

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;
}

px to vw (responsive design)

unitProcessor({
  processor: (value, unit) => {
    if (unit === 'px') {
      return {
        value: (value / 375) * 100,
        unit: 'vw'
      };
    }
  }
})

Scale all px values by half

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;
}

Append fallback instead of replacing

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;
}

Options

{
  processor: (value) => value,  // default: identity function
  unitPrecision: 5,
  propList: ['*'],
  unitList: ['*'],
  selectorBlackList: [],
  replace: true,
  mediaQuery: false,
  exclude: /node_modules/i,
  customUnitList: []
}

processor

Type: Function

The unit processing function. See processor Function above.

unitPrecision

Type: Number Default: 5

Decimal places to round the processed value to.

unitList

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']

propList

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']

selectorBlackList

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 */

replace

Type: Boolean Default: true

  • true — replace the original value
  • false — insert the processed value as a new declaration after the original (useful for fallbacks)

mediaQuery

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) { ... }

exclude

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')

customUnitList

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

Framework Integration

Vite / Vue / React

// 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'
              };
            }
          }
        })
      ]
    }
  }
};

webpack (postcss-loader)

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-unit-processor')({
      processor: (value, unit) => {
        if (unit === 'px') {
          return {
            value: value / 16,
            unit: 'rem'
          };
        }
      }
    })
  ]
};

gulp

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'));
});

License

MIT

About

PostCSS plugin to process CSS unit values via a custom function. Convert px to rem, px to vw, or apply any unit transformation.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors