PostCSS Introduction — Complete Guide
In this tutorial, you will learn about PostCSS Introduction. We cover key concepts, practical examples, and best practices to help you master this topic.
PostCSS transforms CSS with JavaScript plugins for autoprefixing, future CSS syntax, minification, and linting in a flexible pipeline architecture.
What You'll Learn
- What PostCSS is and how it differs from preprocessors
- Setting up PostCSS with a config file
- Core plugins: Autoprefixer, PostCSS Preset Env
- Using future CSS syntax today
- Custom plugin basics
- Integration with build tools
Why It Matters
- PostCSS is the most popular CSS tool after Sass
- Autoprefixer is the standard for vendor prefixes
- Future CSS features become available today
- Plugin architecture is extensible
Real-World Use
- A build pipeline uses Autoprefixer for cross-browser support
- A project uses CSS Nesting (draft spec) via PostCSS
- A team uses Stylelint through PostCSS for linting
- A bundler (Vite) uses PostCSS by default
flowchart LR A[PostCSS] --> B[Parser] B --> C[Plugin 1: Autoprefixer] B --> D[Plugin 2: Preset Env] B --> E[Plugin 3: CSSNano] C --> F[Stringifier] D --> F E --> F F --> G[Transformed CSS]
PostCSS Basics
Code Example: Installation and Setup
# Install PostCSS CLI
npm install --save-dev postcss postcss-cli
# Install popular plugins
npm install --save-dev autoprefixer postcss-preset-env cssnano
# Run PostCSS
npx postcss src/style.css -o dist/style.css
# With plugins
npx postcss src/style.css -o dist/style.css -u autoprefixer -u postcss-preset-env
# Watch mode
npx postcss src/style.css -o dist/style.css -w
// postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')({
stage: 2, // Use stage 2+ CSS features
browsers: 'last 2 versions'
}),
require('autoprefixer'),
require('cssnano')({
preset: 'default'
})
]
};
// package.json
{
"scripts": {
"build:css": "postcss src/style.css -o dist/style.css",
"build:css:prod": "NODE_ENV=production postcss src/style.css -o dist/style.min.css",
"watch:css": "postcss src/style.css -o dist/style.css -w"
},
"devDependencies": {
"postcss": "^8.4.0",
"postcss-cli": "^11.0.0",
"autoprefixer": "^10.4.0",
"postcss-preset-env": "^9.0.0",
"cssnano": "^6.0.0"
}
}
Expected output: PostCSS processes CSS through a plugin pipeline. postcss-preset-env enables future CSS syntax. Autoprefixer adds vendor prefixes. cssnano minifies the output.
Code Example: Future CSS with PostCSS Preset Env
/* Input: future CSS syntax */
:root {
--primary: #0066CC;
--spacing: 1rem;
}
/* CSS Nesting (draft spec) */
.card {
background: #fff;
border: 1px solid #eee;
& .card__title {
font-size: 1.25rem;
color: var(--primary);
}
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
}
/* Custom Media Queries */
@custom-media --viewport-md (min-width: 768px);
@custom-media --viewport-lg (min-width: 1024px);
@media (--viewport-md) {
.container {
max-width: 720px;
}
}
/* Color Functions */
.element {
background: color-mix(in srgb, #0066CC, white 30%);
color: color(display-p3 0.5 0.5 1);
}
/* Logical Properties */
.element {
margin-inline: auto;
padding-block: 1rem;
}
/* Lab colors (gamut beyond sRGB) */
.element {
background: lab(50% 40 -30);
}
/* Output: standard CSS with fallbacks */
:root {
--primary: #0066CC;
--spacing: 1rem;
}
.card {
background: #fff;
border: 1px solid #eee;
}
.card .card__title {
font-size: 1.25rem;
color: #0066CC;
color: var(--primary);
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
.container {
max-width: 720px;
}
}
@media (min-width: 1024px) {
/* ... */
}
Expected output: PostCSS Preset Env transpiles future CSS (nesting, custom media, color-mix) to widely-supported CSS. It handles fallbacks and polyfills automatically.
Code Example: Autoprefixer
/* Input */
.element {
display: flex;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
user-select: none;
appearance: none;
mask-image: linear-gradient(black, transparent);
}
/* Output with Autoprefixer */
.element {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-transition: all 0.3s ease;
transition: all 0.3s ease;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
-webkit-mask-image: linear-gradient(black, transparent);
mask-image: linear-gradient(black, transparent);
}
Expected output: Autoprefixer adds vendor prefixes based on the browserslist configuration in package.json or .browserslistrc.
Code Example: Custom PostCSS Plugin
// postcss-rem.js - Custom plugin to convert px to rem
module.exports = (opts = {}) => {
const base = opts.base || 16;
return {
postcssPlugin: 'postcss-rem',
Declaration(decl) {
const value = decl.value;
// Match px values and convert to rem
const newValue = value.replace(/(\d+)px/g, (match, px) => {
const rem = parseFloat(px) / base;
return `${rem}rem`;
});
if (newValue !== value) {
decl.cloneBefore({ value: newValue });
decl.remove();
}
}
};
};
module.exports.postcss = true;
// postcss.config.js
module.exports = {
plugins: [
require('./postcss-rem')({ base: 16 }),
require('autoprefixer'),
require('cssnano')
]
};
/* Input */
.element {
padding: 16px;
margin: 24px;
font-size: 14px;
}
/* Output */
.element {
padding: 1rem;
margin: 1.5rem;
font-size: 0.875rem;
}
Expected output: Custom PostCSS plugins are JavaScript functions that traverse and transform the CSS AST. This px-to-rem plugin converts all pixel values to rem based on a configurable base.
PostCSS vs Preprocessors
| Feature | PostCSS | Sass/Less/Stylus |
|---|---|---|
| Syntax | Standard CSS | Custom syntax |
| Variables | CSS custom properties | Preprocessor variables |
| Nesting | Plugin (future spec) | Native |
| Mixins | Not native | Native |
| Functions | Not native | Native |
| Plugins | 200+ | Limited |
| Future CSS | Yes (Polyfill) | No |
| Build time | Faster | Slower |
Common Mistakes
- Using PostCSS as a preprocessor replacement — PostCSS lacks native mixins and functions. Use a preprocessor WITH PostCSS for the best results.
- Not using a config file — postcss.config.js centralizes plugin configuration. Avoid inline CLI flags.
- Plugin order matters — Some plugins depend on others. Autoprefixer should run after preset-env. cssnano should be last.
- Over-using future syntax — Stage 0-1 features may change. Stick to stage 2+ features for production.
- Not setting browserslist — Autoprefixer and preset-env need a browserslist configuration to know which browsers to target.
- Expecting Sass-like behavior — PostCSS transforms CSS, it does not add programming constructs. Use Sass for logic, PostCSS for transformations.
- Not testing output — Transpiled CSS can behave differently from the input. Always test in target browsers.
Practice Questions
- What is the primary difference between PostCSS and Sass? PostCSS transforms standard CSS with plugins. Sass uses its own custom syntax with programming features.
- What does Autoprefixer do? Adds vendor prefixes (-webkit-, -moz-, -ms-) based on browser support data.
- What is postcss-preset-env? A plugin that lets you use future CSS features today by transpiling to current browser support.
- How do you create a custom PostCSS plugin? Export a JavaScript function that returns an object with a postcssPlugin property and AST Visitor methods.
FAQ
Mini Project
Set up a PostCSS pipeline with 4 plugins: postcss-preset-env (stage 2), autoprefixer, cssnano, and a custom px-to-rem plugin. Create a CSS file that uses nesting, custom media queries, color-mix(), and Flexbox. Configure browserslist for "last 2 versions". Build a development version (expanded, source maps) and production version (minified, no source maps). Verify: autoprefixing works for flexbox and backdrop-filter, nesting is transpiled to flat selectors, px values are converted to rem, and the production build is minified.
What's Next
Continue with Lesson 26: PostCSS Plugins for advanced PostCSS plugin usage.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro