A PostCSS plugin that converts px units to rem units for responsive design.
npx @tessl/cli install tessl/npm-postcss-pxtorem@6.1.0PostCSS PxToRem is a PostCSS plugin that converts pixel (px) units to rem units in CSS stylesheets. It enables responsive design by allowing browsers to scale based on user font size preferences, while providing comprehensive configuration options for selective conversion.
npm install postcss postcss-pxtorem --save-devconst pxtorem = require('postcss-pxtorem');For ES modules:
import pxtorem from 'postcss-pxtorem';const postcss = require('postcss');
const pxtorem = require('postcss-pxtorem');
// Basic usage with default options
const result = postcss()
.use(pxtorem())
.process(css)
.css;
// With custom options
const result = postcss()
.use(pxtorem({
rootValue: 16,
propList: ['*'],
replace: true
}))
.process(css)
.css;PostCSS PxToRem follows the standard PostCSS plugin architecture with three main processing hooks:
@media queries when mediaQuery option is enabledThe plugin uses several internal utility modules from the lib/ directory:
url(), and var() functions! prefix)propList patterns and selector blacklists before conversionCreates a PostCSS plugin instance with the specified configuration options.
/**
* Creates a PostCSS plugin for converting px to rem units
* @param {Object} options - Configuration options for the plugin
* @returns {Object} PostCSS plugin object
*/
function pxtorem(options = {});The plugin accepts a comprehensive set of configuration options to control conversion behavior.
interface PxToRemOptions {
/** Root element font size or function returning root size */
rootValue?: number | ((input: PostCSSInput) => number);
/** Decimal precision for rem units */
unitPrecision?: number;
/** Properties to convert from px to rem */
propList?: string[];
/** Selectors to ignore during conversion */
selectorBlackList?: (string | RegExp)[];
/** Replace px values instead of adding fallbacks */
replace?: boolean;
/** Convert px in media queries */
mediaQuery?: boolean;
/** Minimum pixel value to convert */
minPixelValue?: number;
/** File exclusion pattern */
exclude?: string | RegExp | ((filePath: string) => boolean);
/** Unit to convert from (default: "px") */
unit?: string;
}The plugin uses the following default configuration:
const defaultOptions = {
rootValue: 16,
unitPrecision: 5,
selectorBlackList: [],
propList: ['font', 'font-size', 'line-height', 'letter-spacing', 'word-spacing'],
replace: true,
mediaQuery: false,
minPixelValue: 0,
exclude: null,
unit: 'px'
};The propList option supports various matching patterns for selective property conversion:
// Property list pattern examples
const propListPatterns = {
/** Exact property names */
exact: ['font-size', 'margin', 'padding'],
/** All properties */
all: ['*'],
/** Properties containing substring */
contains: ['*position*'], // matches background-position-x, etc.
/** Properties starting with prefix */
startsWith: ['font*'], // matches font-size, font-weight, etc.
/** Properties ending with suffix */
endsWith: ['*-spacing'], // matches letter-spacing, word-spacing, etc.
/** Negated patterns (exclude from conversion) */
exclude: ['*', '!border*'], // all properties except those starting with 'border'
};/* Input CSS */
h1 {
margin: 0 0 20px;
font-size: 32px;
line-height: 1.2;
letter-spacing: 1px;
}
/* Output CSS (with default options) */
h1 {
margin: 0 0 20px;
font-size: 2rem;
line-height: 1.2;
letter-spacing: 0.0625rem;
}const postcss = require('postcss');
const pxtorem = require('postcss-pxtorem');
const result = postcss()
.use(pxtorem({
propList: ['*'], // Convert all properties
replace: false // Keep px as fallback
}))
.process(css)
.css;/* Input */
.element {
width: 320px;
margin: 10px 20px;
border: 1px solid #ccc;
}
/* Output */
.element {
width: 320px;
width: 20rem;
margin: 10px 20px;
margin: 0.625rem 1.25rem;
border: 1px solid #ccc;
border: 0.0625rem solid #ccc;
}const options = {
propList: ['*', '!border*', '!outline*'],
selectorBlackList: ['.ignore', /^\.mobile-/],
minPixelValue: 2
};
const result = postcss()
.use(pxtorem(options))
.process(css)
.css;const options = {
rootValue: (input) => {
// Different root values based on file path
if (input.file.includes('mobile')) {
return 14;
}
return 16;
}
};const options = {
exclude: /node_modules/i, // Exclude node_modules files
// or function-based exclusion
exclude: (file) => file.includes('vendor')
};const options = {
mediaQuery: true // Enable px to rem conversion in media queries
};
const result = postcss()
.use(pxtorem(options))
.process(css)
.css;/* Input */
@media (min-width: 768px) {
.container {
max-width: 1200px;
}
}
/* Output */
@media (min-width: 48rem) {
.container {
max-width: 75rem;
}
}interface PostCSSPlugin {
/** Plugin identifier */
postcssPlugin: 'postcss-pxtorem';
/** Initialize plugin for each CSS file */
Once(css: PostCSSRoot): void;
/** Process each CSS declaration */
Declaration(decl: PostCSSDeclaration): void;
/** Process CSS at-rules (like @media) */
AtRule(atRule: PostCSSAtRule): void;
}interface PostCSSInput {
/** File path of the CSS being processed */
file: string;
/** CSS source content */
css: string;
}By default, only lowercase 'px' units are converted. Uppercase variants ('Px', 'PX') are ignored:
/* This allows selective ignoring within the same file */
.convert {
font-size: 16px; /* converted to 1rem */
}
.ignore {
border: 1Px solid; /* ignored - keeps Px */
border-width: 2PX; /* ignored - keeps PX */
}// Gulp integration
const gulp = require('gulp');
const postcss = require('gulp-postcss');
const pxtorem = require('postcss-pxtorem');
gulp.task('css', () => {
return gulp.src('src/**/*.css')
.pipe(postcss([
pxtorem({
replace: false
})
]))
.pipe(gulp.dest('dist'));
});
// Webpack integration (postcss.config.js)
module.exports = {
plugins: [
require('postcss-pxtorem')({
rootValue: 16,
propList: ['*']
})
]
};This plugin follows PostCSS plugin conventions and includes the required compatibility flag:
// Plugin compatibility marker
pxtorem.postcss = true;