DevToys Web Pro iconDevToys Web ProBlog
Ohodnoťte nás:
Vyskúšajte rozšírenie prehliadača:
← Back to Blog

CSS Formatter Guide: Property Order, Nesting, and Minification

11 min read

CSS is deceptively easy to write messily. A blank stylesheet accepts declarations in any order, nests rules however you like in preprocessors, and permits whitespace ranging from zero to infinite. Without a formatter enforcing a consistent shape, every developer on a team produces a subtly different dialect, and diffs become noise. Run your stylesheets through the CSS Formatter to follow along with the examples in this guide.

This guide covers the four problems a CSS formatter solves: declaration ordering, shorthand handling, nesting serialization, and the minify-vs-beautify trade-off. It also explains how a formatter relates to a linter such as stylelint, and why that division of labor matters.

How a CSS Formatter Works

Like any good code formatter, a CSS formatter does not patch text with regular expressions. It parses the stylesheet into a tree of rules, selectors, and declarations, discards the original whitespace, and then reprints the tree using its own layout rules. That parse-then-print approach guarantees idempotency: running the formatter twice produces identical output, making it safe to run on every save and in CI.

The key consequence is that a formatter cannot fix a broken stylesheet. If a declaration is syntactically invalid, the parser will either reject the file or silently skip the unknown node. Always fix parse errors before relying on formatter output.

Declaration Ordering Strategies

The most visible thing a CSS formatter can do beyond indentation is sort declarations within a rule block. Three strategies dominate the ecosystem:

  • Alphabetical — sort every property name A-to-Z. Easy to learn, trivial to implement, zero ambiguity. The downside is that logically related properties such asflex-grow, flex-shrink, and flex-basis end up scattered.
  • Concentric — order properties from the outside in, following the box model: positioning and display first, then dimensions, then border, then background, then typography, then misc. This mirrors how the browser computes layout.
  • Grouped (categorical) — cluster properties into logical groups (layout, box model, visual, animation) separated by blank lines. The stylelint-order plugin ships a popular version of this ordering as a shareable config.
StrategyBest forTool support
AlphabeticalSmall teams, minimal configPrettier (default), many beautifiers
ConcentricTeams with strong box-model intuitionstylelint-order + concentric config
Grouped / categoricalLarge teams, design-system CSSstylelint-order, postcss-sorting

Prettier deliberately does not reorder declarations — it only normalizes whitespace and formatting. Enforcing a specific property order is the job of a linter rule such asstylelint-order/properties-order. This separation is intentional and is discussed more in the linter section below.

/* Unordered */
.card {
  color: #333;
  position: relative;
  background: white;
  display: flex;
  font-size: 1rem;
  z-index: 10;
  padding: 1rem;
}

/* Grouped ordering: layout → box model → visual → typography */
.card {
  position: relative;
  z-index: 10;
  display: flex;

  padding: 1rem;

  background: white;

  font-size: 1rem;
  color: #333;
}

Shorthand Expansion vs Collapse

CSS shorthands let you write one declaration where four would otherwise be required.margin: 1rem 2rem is more concise than four separate margin declarations, but it is also more surprising: a shorthand silently resets any longhand value you did not specify to its initial value.

Formatters generally leave shorthand choices to the author. A linter rule such asshorthand-property-no-redundant-values can flag cases where a shorthand can be collapsed further — for example, margin: 1rem 1rem can be written asmargin: 1rem. The complementary rule declaration-no-importantflags overuse of !important which often signals a specificity problem that formatting cannot fix.

/* Redundant shorthand values */
.box {
  margin: 1rem 1rem 1rem 1rem;   /* can be: margin: 1rem */
  padding: 0.5rem 1rem 0.5rem;   /* can be: padding: 0.5rem 1rem */
  border-width: 1px 1px;         /* can be: border-width: 1px */
}

/* After collapsing */
.box {
  margin: 1rem;
  padding: 0.5rem 1rem;
  border-width: 1px;
}

The reverse situation — expanding a shorthand into its longhands for clarity — is less common in automated tooling. It is occasionally done manually when a shorthand reset causes an unexpected cascade, making the individual longhand values explicit and easier to override in component styles.

Modern Native CSS Nesting vs SCSS Nesting

CSS nesting landed in all major browsers in 2023 and is now safe to use without a preprocessor. It lets you write child rules directly inside a parent rule block, reducing repetition. However, native nesting syntax has historically differed from SCSS nesting in one important detail: early implementations required a nesting selector when targeting element tags directly inside a parent.

/* Native CSS nesting — modern syntax (widely supported 2024+) */
.card {
  padding: 1rem;
  background: white;

  .title {
    font-size: 1.25rem;
    font-weight: bold;
  }

  &:hover {
    background: #f5f5f5;
  }

  /* Targeting a child element tag — use & to be safe in older parsers */
  & p {
    line-height: 1.6;
  }
}
// SCSS nesting — same visual structure, compiled to flat CSS
.card {
  padding: 1rem;
  background: white;

  .title {
    font-size: 1.25rem;
    font-weight: bold;
  }

  &:hover {
    background: #f5f5f5;
  }

  p {
    line-height: 1.6;
  }
}

When formatting SCSS files, use the SCSS Formatter rather than the plain CSS formatter — the parsers are different, and a CSS formatter may reject or mangle SCSS syntax such as variables, mixins, and @include directives. The same applies to LESS: use the LESS Formatter for LESS source files.

Formatters normalize nesting indentation consistently regardless of how deeply rules are nested, but they do not convert between native CSS nesting and SCSS nesting — that is a job for a migration tool or compiler. The formatter simply reprints whatever nesting structure it finds after parsing.

Minification for Production

Minifying CSS reduces the bytes sent over the network to the browser. A whitespace-only minifier strips comments, newlines, and spaces between tokens. A more aggressive minifier also applies semantic transformations: converting color hex values to shorter equivalents, removing unnecessary units from zero values, merging identical selectors, and collapsing shorthand values.

/* Original source */
.button {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1rem;
  background-color: #ffffff;
  border: 1px solid #cccccc;
  border-radius: 4px;
  color: #333333;
  font-size: 1rem;
  line-height: 0px;   /* zero px — unit can be stripped */
}

/* Whitespace-only minification */
.button{display:inline-flex;align-items:center;padding:.5rem 1rem;background-color:#fff;border:1px solid #ccc;border-radius:4px;color:#333;font-size:1rem;line-height:0}

Notice the transformations the aggressive minifier applied: #ffffff became#fff, #cccccc became #ccc, 0.5rembecame .5rem, and the unit was stripped from the zero line-height. All of these produce equivalent computed values while reducing byte count.

Source maps and minification

When you minify CSS for production, generate a source map alongside it. A source map is a JSON file that maps positions in the minified output back to lines in the original source, enabling browser DevTools to show you the unminified file during debugging. Most build tools — Vite, webpack, PostCSS — generate source maps automatically when minification is enabled.

# PostCSS with cssnano (minifier) and source maps
npx postcss src/styles.css   --use cssnano   --map   --output dist/styles.min.css

The resulting dist/styles.min.css.map file is only needed for development tools — do not serve it to end users unless you want the original source visible in DevTools. Many teams serve source maps only on staging environments and omit them from production CDN caches.

Formatter vs Linter: Division of Labor

Prettier and stylelint are the two dominant tools in the CSS quality ecosystem, and they solve different problems. Conflating them leads to duplicate configuration and contradictory fixes.

ConcernPrettier (formatter)stylelint (linter)
Indentation and whitespaceYes — owns this entirelyDisable these rules to avoid conflict
Quote style in valuesYes — normalizes to double quotesDisable string-quotes
Property orderingNo — not in scopeYes — via stylelint-order plugin
Unknown propertiesNo — formatter is not a validatorYes — property-no-unknown
Specificity issuesNoYes — selector-max-specificity
Color notation consistencyPartial — normalizes some valuesYes — color-function-notation

The recommended setup is to run Prettier first to normalize formatting, then run stylelint with all formatting-related rules disabled via stylelint-config-prettier. That config extends your stylelint config and turns off every rule that would conflict with Prettier output, leaving stylelint free to focus on correctness and conventions.

// .stylelintrc.json — formatter-safe configuration
// stylelint-config-standard (v15+) already omits formatting rules,
// so Prettier owns layout and stylelint owns correctness.
{
  "extends": ["stylelint-config-standard"],
  "plugins": ["stylelint-order"],
  "rules": {
    "order/properties-order": [
      "display",
      "position",
      "width",
      "height",
      "margin",
      "padding",
      "color"
    ],
    "color-function-notation": "modern",
    "property-no-unknown": true
  }
}

Why Consistent Formatting Reduces Diff Noise

The practical argument for a CSS formatter is the same as for any formatter: it eliminates a whole category of diff noise. Without a formatter, a developer who reformats a block to fix alignment produces a diff that mixes meaningful changes with whitespace churn. Reviewers must scan every line to find the actual logic change buried inside the formatting change.

With a formatter in place — run on save and enforced in CI — every diff is purely semantic. A property value change, a new rule, a removed selector: each appears cleanly without surrounding whitespace noise. Code review becomes faster and less error-prone.

# Format all CSS in the project
npx prettier --write "**/*.css"

# Check formatting in CI without writing (non-zero exit on drift)
npx prettier --check "**/*.css"

# Run stylelint after formatting
npx stylelint "**/*.css" --fix

Pair the Prettier check with a pre-commit hook using husky and lint-staged so only the changed files are formatted on commit. The CI check is the backstop ensuring the main branch stays consistent even when contributors skip the hook.

Common Pitfalls

Formatting CSS-in-JS and CSS Modules

Prettier formats CSS inside tagged template literals such as those used by styled-components and Emotion, and it formats .module.css files the same way as regular CSS. However, dynamic interpolations inside template literals are opaque to the CSS parser, so any expression inside ${...} is printed as-is. Keep dynamic values simple to avoid breaking the formatter's CSS understanding.

Vendor-prefixed properties

Alphabetical ordering places -webkit- and -moz- prefixed variants far from their unprefixed counterpart. If you use a property-ordering rule, make sure your config groups prefixed variants adjacent to their standard form. Modern PostCSS with Autoprefixer adds vendor prefixes at build time, so writing prefixed properties manually in source is increasingly unnecessary.

Excluding generated files

Build output, third-party CSS bundles, and minified assets should be excluded from formatting. Running a formatter over a minified file produces a large diff and can confuse source control history.

# .prettierignore
dist/
build/
*.min.css
vendor/

If you are exploring code formatting more broadly across languages, the Code Formatters Guide covers the shared principles that apply to JavaScript, JSON, HTML, and CSS formatters alike — parsing strategies, idempotency, and CI integration patterns.


Beautify or minify stylesheets directly in your browser with the CSS Formatter — it runs locally so your code never leaves your machine. For preprocessor files, use the SCSS Formatter or the LESS Formatter.