PostCSS and Autoprefixer

PostCSS 238,379 (https://github.com/postcss/postcss 28,977 ), created by Andrey Sitnik, is not a language but a CSS parser with a plugin API. It turns a stylesheet into a tree of Root, Rule, AtRule, Declaration and Comment nodes, lets plugins edit the tree, then prints it with a source map. Plugins include Autoprefixer 22,226 (https://github.com/postcss/autoprefixer 22,226 ), cssnano 4,977 and @tailwindcss/postcss (Tailwind CSS).

Autoprefixer compares your target browsers with Can I Use 3,038 data (the caniuse-lite package) and adds only the vendor prefixes they need, removing outdated ones. postcss-preset-env 1,053 (https://github.com/csstools/postcss-plugins 1,053 ) bundles Autoprefixer with plugins that rewrite newer syntax for older targets (stage: 2, the default, means reasonably stable features). Both read .browserslistrc. Install with npm 2,036 install --save-dev postcss postcss-cli postcss-preset-env.

postcss.config.js (.browserslistrc contains: safari 13, chrome 90, firefox 100)CSS
module.exports = {
  plugins: [
    require("postcss-preset-env")({ stage: 2 }),
    { postcssPlugin: "px-to-rem",       // a custom plugin: visits every declaration
      Declaration(d) { d.value = d.value.replace(/(\d*\.?\d+)px/g, (_, n) => `${n / 16}rem`); } },
  ],
};
in.css: modern CSS written onceCSS
@custom-media --wide (width >= 40rem);
.card {
  color: oklch(50% 0.15 255);
  padding: 24px;
  user-select: none;
  & .title { text-wrap: balance; }
}
@media (--wide) { .card { display: grid; } }
Compiled CSS: npx postcss in.css -o out.cssCSS
.card {
  color: rgb(23, 98, 182);
  padding: 1.5rem;
  -webkit-user-select: none;
          user-select: none;
}
.card .title { text-wrap: balance; }
@media (min-width: 40rem) { .card { display: grid; } }

Safari 13 10 lacks oklch(), nesting, custom and range media queries and unprefixed user-select, so each was rewritten; text-wrap passed through because no plugin emulates it, and the custom plugin converted 24px.