Inconsistent code style is a silent productivity killer. Every manual format pass before a commit, every "nit: indentation" comment in a PR, every diff polluted by whitespace-only lines — all of it disappears the moment you enable vs code format on save. One setting, and the editor handles style automatically every time you hit Ctrl+S. This guide covers the complete setup: enabling vscode auto format on save, choosing between Prettier and the built-in formatter, configuring per-language rules, resolving ESLint conflicts, and — a workflow no other guide covers — using a diff tool to verify a formatter changed only whitespace, not logic. If you want to level up adjacent VS Code habits alongside this one, see how to compare two files in VS Code and how multi-cursor editing pairs naturally with bulk reformatting. For a broader look at automated code quality tools that complement format-on-save, our overview of static code analysis tools is worth a read.

What Format on Save Actually Does

Before and after VS Code format on save Two code panels side by side. The left panel shows unformatted JavaScript with inconsistent spacing, mixed quotes, and misaligned indentation. The right panel shows the same code after format on save applied Prettier rules: consistent 2-space indentation, double quotes, and semicolons. BEFORE — unformatted function greet( name){ const msg = 'Hello, '+name return msg } const obj={a:1,b:2, c:3} extra spaces · mixed quotes bad indentation · missing semis AFTER — format on save function greet(name) { const msg = "Hello, " + name; return msg; } const obj = { a: 1, b: 2, c: 3, }; consistent · readable · reviewable Ctrl+S
Format on save transforms inconsistent code into clean, readable output automatically on every Ctrl+S. No manual formatting passes, no style nits in code review.

When you press Ctrl+S (or Cmd+S on macOS), VS Code normally just writes the file to disk. With editor.formatOnSave enabled, it first runs the active formatter against the entire file, applies the changes to the buffer, then saves. The round-trip is typically imperceptible — under 100 ms for most files.

What the formatter actually changes depends on which formatter you have selected, but common transformations include:

  • Indentation — normalizes tabs vs spaces and depth (2 or 4 spaces)
  • Quotes — enforces single or double quotes consistently
  • Semicolons — adds or removes them based on your rule set
  • Trailing commas — inserts them on multi-line structures
  • Print width / line wrapping — breaks long lines at a configured column
  • Blank line normalization — removes extra blank lines, enforces spacing between blocks
  • Bracket spacing — adds or removes spaces inside { and }

Crucially, a correctly configured formatter touches only whitespace and stylistic tokens — it never changes logic. That claim is verifiable, and we will show you exactly how to verify it with a diff later in this guide.

The practical upside extends beyond aesthetics. Consistent formatting means git diffs show only real changes, code reviews focus on logic instead of style, and new contributors cannot accidentally commit differently-formatted files. According to the VS Code documentation on code basics, formatting is one of the most commonly configured editor behaviors.

Quick Setup: Enable Format on Save in 60 Seconds

settings.json with editor.formatOnSave enabled A dark-themed code editor card showing a settings.json file. The key lines editor.formatOnSave set to true and editor.defaultFormatter set to esbenp.prettier-vscode are highlighted in blue, with annotation badges pointing to each. settings.json 1 2 3 4 5 6 7 8 9 { "editor.formatOnSave" : true , ← enable this "editor.defaultFormatter" : "esbenp.prettier-vscode" , ← set formatter "editor.tabSize" : 2 , "editor.insertSpaces" : true // …other settings }
Two lines in settings.json enable format on save. The first turns on auto-formatting; the second pins Prettier as the formatter so VS Code does not prompt when multiple formatters are installed.

The fastest path to working vscode auto format on save:

  1. Open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P), type Open User Settings JSON, and press Enter.
  2. Add these two lines inside the top-level object:
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  3. Save the file (Ctrl+S). The setting takes effect immediately.
  4. Open any JavaScript or TypeScript file, introduce some messy spacing, and save it. VS Code formats the file before writing it to disk.

If you do not have Prettier installed yet, open the Extensions panel (Ctrl+Shift+X), search for Prettier - Code formatter (publisher: Esben Petersen, ID: esbenp.prettier-vscode), and install it. Alternatively, if you prefer the VS Code built-in formatter, set "editor.defaultFormatter": "vscode.typescript-language-features" for JS/TS files, or simply omit the line — VS Code will fall back to the built-in formatter when no default is set.

The Settings UI route

If you prefer the GUI: open Settings (Ctrl+,), search for format on save, and check the Editor: Format On Save checkbox. To pick a formatter, search for default formatter and choose from the dropdown. Both routes write to the same settings.json file.

Choosing a Formatter: Prettier vs VS Code Built-in

The most important decision before enabling format on save is which formatter to use. Getting this wrong means either no formatting (if the formatter is missing) or unexpected results (if two formatters fight each other).

Prettier vs VS Code built-in formatter comparison A two-column comparison card. Left column shows Prettier with green checkmarks for its strengths: opinionated defaults, 20+ language support, .prettierrc config, CI enforcement, team consistency. Right column shows VS Code built-in with blue checkmarks for its advantages: zero setup, fast, works offline, good for quick edits. Prettier vs VS Code Built-in Formatter Prettier (esbenp.prettier-vscode) VS Code Built-in Opinionated defaults (no config needed) Zero setup — works out of the box 20+ languages (JS/TS/CSS/HTML/JSON…) Fast — no extra process to spawn .prettierrc config file for team rules Works without internet / npm CI enforcement via prettier --check No config file — settings only eslint-config-prettier for ESLint harmony Fewer language options Best for: teams, open-source, CI pipelines Use .prettierrc to pin rules Best for: quick solo edits, no-npm envs Good enough for JS/TS/JSON/CSS/HTML
Prettier wins on team consistency and language coverage. The built-in formatter wins on simplicity and zero dependencies. For any project with more than one contributor, Prettier plus a .prettierrc file is the standard choice.

The VS Code built-in formatter handles JavaScript, TypeScript, JSON, HTML, and CSS. It is fast and requires no extension, but it has limited configurability — you control indentation size and a handful of other options through settings.json, but not trailing commas, print width, or bracket spacing.

Prettier is the industry standard for JavaScript-ecosystem projects. The Prettier documentation shows it supports over 20 languages including TypeScript, JSX, TSX, HTML, CSS, SCSS, Less, JSON, GraphQL, Markdown, and YAML. Its key advantage is the .prettierrc config file: commit it to your repo and every team member and CI run uses identical rules, eliminating "formatting drift" across machines.

A minimal .prettierrc to pin the most commonly debated options:

{
  "semi": true,
  "singleQuote": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 100
}

Drop that file in the project root and Prettier uses it automatically. No arguments needed on the command line or in the VS Code extension.

Global vs Workspace Settings

VS Code applies settings in a layered hierarchy. Understanding which layer controls format on save is critical — many "format on save not working" reports come from a workspace override silently overriding a user-level setting.

Scope File Location When to Use
User (global) ~/.config/Code/User/settings.json (Linux) or ~/Library/Application Support/Code/User/settings.json (macOS) Personal defaults that apply everywhere — all projects on your machine
Workspace .vscode/settings.json in the project root Project-specific overrides — committed to the repo so everyone on the team gets the same behavior
Folder Per-folder settings in a multi-root workspace Monorepos where sub-packages need different formatters

Workspace settings override user settings. If your user settings have "editor.formatOnSave": true but a project's .vscode/settings.json has "editor.formatOnSave": false, format on save is disabled in that project. The VS Code status bar shows the active scope — look for the gear icon in the bottom-right when Settings is open.

Recommendation for teams: commit a .vscode/settings.json that sets "editor.formatOnSave": true and "editor.defaultFormatter" to your chosen formatter. This ensures every contributor gets format on save, regardless of their personal preferences, and eliminates whitespace-only commits from people who have different global settings.

// .vscode/settings.json (commit this to the repo)
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

Per-Language Format on Save Configuration

A single global editor.formatOnSave applies to every file type. Sometimes you want different behavior per language — for example, format Python but not Markdown, or use a different formatter for Go than for JavaScript. VS Code supports language-specific settings via the [languageId] override syntax in settings.json.

{
  // Global default: format everything
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",

  // JavaScript/TypeScript: Prettier
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },

  // Python: Black (ms-python.black-formatter)
  "[python]": {
    "editor.defaultFormatter": "ms-python.black-formatter",
    "editor.formatOnSave": true
  },

  // Go: built-in gopls formatter
  "[go]": {
    "editor.defaultFormatter": "golang.go",
    "editor.formatOnSave": true
  },

  // Markdown: disable format on save (too aggressive)
  "[markdown]": {
    "editor.formatOnSave": false
  }
}

The language identifier comes from the language mode shown in the VS Code status bar (bottom-right). Click it on any open file to see its ID — for example, javascriptreact for JSX, typescriptreact for TSX, shellscript for Bash.

Python: Black vs autopep8

Python has two popular formatters. Black (ms-python.black-formatter) is opinionated and uncompromising — it makes decisions for you and produces consistent output with no configuration. autopep8 (ms-python.autopep8) is gentler and stays closer to the original code structure. For new projects, Black is the current community preference. Set "editor.defaultFormatter": "ms-python.black-formatter" in the [python] block.

Go: gofmt is non-negotiable

Go enforces formatting through gofmt, which ships with the language. The VS Code Go extension (golang.go) hooks into it. With "editor.formatOnSave": true in the [go] block, every file is gofmt-formatted on save. There is no meaningful choice here — Go's ecosystem mandates it and goimports (which also organizes imports) is the extended version.

Rust: rustfmt

The rust-analyzer extension (rust-lang.rust-analyzer) includes rustfmt support. Add a [rust] block with "editor.defaultFormatter": "rust-lang.rust-analyzer" and format on save works identically to Go.

ESLint + Prettier Without Conflicts

Running ESLint and Prettier together is the most common source of format-on-save headaches. ESLint enforces code quality rules; Prettier enforces code style. When they overlap on stylistic rules — like semicolons or quote style — they can fight each other, with Prettier formatting one way and ESLint immediately flagging it as wrong.

The standard solution is two packages:

  • eslint-config-prettier — turns off all ESLint rules that would conflict with Prettier. Install with npm install --save-dev eslint-config-prettier and add "prettier" as the last item in your ESLint extends array.
  • eslint-plugin-prettier (optional) — runs Prettier as an ESLint rule, surfacing Prettier violations as ESLint errors. Useful for CI but adds overhead in the editor.

The cleanest VS Code setup for ESLint + Prettier uses two separate tools for two separate concerns: Prettier handles formatting on save, ESLint handles code quality on save via editor.codeActionsOnSave:

{
  // Prettier formats the file on save
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",

  // ESLint fixes auto-fixable lint errors on save
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  }
}

With this setup, saving a file triggers two passes: Prettier reformats style, then ESLint auto-fixes any fixable code-quality issues. Neither tool touches the other's domain — as long as eslint-config-prettier is installed and extends your ESLint config.

Order matters: VS Code runs editor.formatOnSave before editor.codeActionsOnSave. Prettier runs first, then ESLint's auto-fix pass. This order is correct — formatting first, then linting, prevents the two from fighting.

Using a vscode beautifier: Formatters Compared

The term vscode beautifier often refers to any code formatting extension for VS Code, not just one specific tool. The original "Beautify" extension (HookyQR.beautify) was popular in earlier VS Code versions but has been largely superseded by more modern options. Here is a current map of formatters by language:

Language Recommended Formatter Extension ID Config File
JS / TS / JSX / TSX Prettier esbenp.prettier-vscode .prettierrc
CSS / SCSS / Less Prettier esbenp.prettier-vscode .prettierrc
HTML Prettier or built-in esbenp.prettier-vscode .prettierrc
Python Black ms-python.black-formatter pyproject.toml
Go gofmt / goimports golang.go gofmt (no config)
Rust rustfmt rust-lang.rust-analyzer rustfmt.toml
Java Language Support for Java redhat.java .editorconfig
C / C++ clang-format ms-vscode.cpptools .clang-format
JSON Prettier or built-in esbenp.prettier-vscode .prettierrc
YAML Prettier esbenp.prettier-vscode .prettierrc

EditorConfig (.editorconfig) is not a formatter — it is a cross-editor configuration standard that normalizes indentation, end-of-line characters, and charset. VS Code respects .editorconfig files natively. It works alongside Prettier, not instead of it: EditorConfig handles the basic file-level settings, Prettier handles the deeper stylistic choices. If both exist in a project, Prettier takes precedence on any option it covers.

The old HookyQR Beautify extension is still available on the marketplace but is no longer actively maintained and does not support modern JavaScript syntax (ESM, optional chaining, nullish coalescing). Uninstall it if you see unexpected behavior — it may be intercepting save events before Prettier gets to run. Checking for this is a good first step in finding the difference between what you expect and what your editor actually does.

Verify Formatting With a Diff

Here is a workflow no other formatter guide covers: verifying that a formatter changed only whitespace, not logic. This matters in two scenarios:

  • You just enabled format on save on a legacy codebase and want to confirm the first formatting pass did not corrupt any strings, template literals, or ASI-sensitive semicolon placements.
  • You updated Prettier from v2 to v3 (or changed .prettierrc rules) and want to audit what changed before committing the reformatted files.

The format → diff workflow

  1. Copy the file content before saving. Open the file, select all (Ctrl+A), copy (Ctrl+C). This is your "before" state.
  2. Save to trigger format on save. Press Ctrl+S. VS Code formats and writes the file.
  3. Copy the formatted content. Select all again and copy the reformatted code. This is your "after" state.
  4. Open Diff Checker and paste both versions. The Diff Checker Chrome extension — built on Monaco Editor (the same engine that powers VS Code) — lets you paste the before version on the left and the after version on the right, then run a diff instantly in your browser. No file uploads, 100% local.
  5. Switch to "Ignore Whitespace" diff mode. Diff Checker includes three diff algorithms: Smart, Classic (LCS), and Ignore Whitespace. Select "Ignore Whitespace" and click Run Diff again. If the diff now shows zero changes, the formatter touched only whitespace — your logic is intact.
Format-then-diff verification workflow A four-step horizontal flow diagram. Step 1 shows original messy code in an editor. Step 2 shows a Ctrl+S action triggering format on save. Step 3 shows the formatted output. Step 4 shows the Diff Checker tool with Ignore Whitespace mode active, confirming zero logic changes. A green badge reads "Logic intact". Format → Diff verification: confirm only whitespace changed Before function f( a){ return a+1 } step 1: copy Ctrl +S 2 After function f(a) { return a + 1; } step 3: copy paste both Diff Checker — Ignore Whitespace function f(a) { return a + 1; } 0 logic changes — whitespace only ✓ Ignore Whitespace mode step 4: diff confirms logic intact
The format-then-diff workflow: copy the file before saving, save to trigger format on save, copy again, then paste both into Diff Checker. Switch to "Ignore Whitespace" mode — zero remaining changes means the formatter touched only whitespace.

This workflow is especially useful when onboarding Prettier onto a large existing codebase. Run it on a representative sample of files before committing all the reformatted code. If the "Ignore Whitespace" diff shows changes, something unexpected happened — perhaps a template literal or a regex that Prettier re-arranged.

Diff Checker also has a Format Code button powered by Prettier, supporting the same 20+ languages as the VS Code extension. If you want to preview what Prettier would do to a snippet without saving a file, paste the code into Diff Checker, click Format Code, and compare the before/after directly in the split view. It is a quick sanity check for one-off questions like "what will Prettier do to this JSX?"

Another use case: after running collapse all regions in a large file (see our guide on VS Code collapse all), you can quickly scan the formatted output at a high level, then use the diff view to confirm what changed between versions.

Troubleshooting: Format on Save Not Working

Format on save not working — troubleshooting decision tree A decision tree flowchart. Start at "Format on save not working." Branch 1: Is editor.formatOnSave true? If no, add it to settings.json. If yes, proceed. Branch 2: Is a default formatter set? If no, add editor.defaultFormatter. If yes, proceed. Branch 3: Multiple formatters installed? If yes, pick one explicitly. Branch 4: Check Output panel for errors. Branch 5: Is it a workspace override? Check .vscode/settings.json. Format on save not working? Is "editor.formatOnSave": true in settings? NO Add to settings.json "formatOnSave": true YES Is "editor.defaultFormatter" set? Add defaultFormatter e.g. esbenp.prettier YES Workspace .vscode/settings.json overriding? YES Check / fix .vscode/settings.json NO Any errors in Output panel (Ctrl+Shift+U)? YES Read the error & fix extension NO Reload window: Ctrl+Shift+P → Reload Extension state sometimes stale after install
Format on save troubleshooting decision tree. Work through each step in order — the most common causes are a missing setting, missing defaultFormatter, or a workspace override silently disabling the user-level setting.

Problem: "There are multiple formatters" warning

A yellow notification appears in VS Code: "There are multiple formatters for [language]. Select a default formatter to continue." This happens when two or more extensions both register as formatters for the same language ID. The fix is explicit: add "editor.defaultFormatter" to your settings, either globally or in the appropriate language-specific block. VS Code shows the formatter IDs in the dropdown that appears when you click the notification.

Problem: Prettier not detecting .prettierrc

Prettier searches for config files by walking up the directory tree from the file being formatted. If your .prettierrc is not in the project root or any parent directory of the open file, Prettier falls back to defaults. Common causes:

  • You opened VS Code on a subdirectory inside a monorepo instead of the root.
  • The .prettierrc file has a typo in the name (it's case-sensitive on Linux).
  • The Prettier version installed globally differs from the one in node_modules — install locally with npm install --save-dev prettier and the VS Code extension will prefer the local version.

Problem: Format on save is too slow

For very large files (>10,000 lines), formatting can take noticeable time. Options:

  • Set "editor.formatOnSaveMode": "modificationsIfAvailable" — this formats only the lines you actually changed (when git diff info is available), not the whole file. Significantly faster on large files.
  • Add large auto-generated files (build output, dist/, compiled CSS) to .prettierignore so Prettier skips them entirely.

Problem: ESLint and Prettier both running but conflicting

If you see Prettier format a file one way but ESLint immediately flags style errors in the same file, eslint-config-prettier is either not installed or not placed last in your ESLint extends array. The last item in extends wins. The correct order is:

// eslint.config.js (ESLint v9 flat config)
import eslint from "@eslint/js";
import prettier from "eslint-config-prettier";

export default [
  eslint.configs.recommended,
  // ... your other configs ...
  prettier, // must be last — disables ESLint style rules that conflict
];

Problem: File saves without formatting (one-off bypass)

Sometimes you need to save a file without triggering the formatter — for example, saving mid-edit when the code is intentionally incomplete. Use File: Save without Formatting from the Command Palette, or bind it to a key. There is no default keybinding — add one to keybindings.json:

{
  "key": "ctrl+k s",
  "command": "workbench.action.files.saveWithoutFormatting"
}

How to Turn Off Format on Save

Three scenarios where disabling makes sense: you are working on a project with no style conventions, you are in a quick debug session and formatting noise is distracting, or you are editing an auto-generated file you do not want reformatted.

Globally

// User settings.json
"editor.formatOnSave": false

Per workspace

// .vscode/settings.json
"editor.formatOnSave": false

Per language

// Disable only for Markdown, keep for everything else
"[markdown]": {
  "editor.formatOnSave": false
}

One-off save without formatting

Use the Command Palette → File: Save without Formatting. This is a single-use bypass — the next Ctrl+S goes back to normal format-on-save behavior. It is the cleanest way to handle the occasional "I just need to save this draft" case without permanently changing settings.

After disabling, you can still format manually at any time with the keyboard shortcut Shift+Alt+F (Windows/Linux) or Shift+Option+F (macOS), or via the Command Palette → Format Document. See the VS Code formatting documentation for the full list of formatting commands and their keybindings.

For teams where individual contributors have different habits, the best practice is to enforce formatting at the CI level (using prettier --check . in a pre-push hook or CI job) rather than relying solely on editor settings. That way the repo stays clean regardless of what any individual developer has in their local settings.json. This is the same category of static enforcement covered by static code analysis tools — format checking is a lightweight form of static analysis.

Frequently Asked Questions

How do I auto-format on save in VS Code?
Add "editor.formatOnSave": true to your settings.json to enable vs code format on save. If multiple formatters are installed for the same language, also add "editor.defaultFormatter": "extension.id" — for example "esbenp.prettier-vscode". For team projects, commit a .vscode/settings.json with both lines so everyone gets the same vscode auto format on save behavior automatically.
What is the best formatter for VS Code?
For JavaScript, TypeScript, CSS, HTML, and JSON: Prettier (esbenp.prettier-vscode). For Python: Black (ms-python.black-formatter). For Go: the official Go extension (golang.go) which uses gofmt. For Rust: rust-analyzer (rust-lang.rust-analyzer). For multi-language projects, Prettier covers the most ground with a single .prettierrc config file.
Why is my formatter not working in VS Code?
Check in this order: (1) Is "editor.formatOnSave": true? (2) Is "editor.defaultFormatter" set and the extension installed? (3) Is a workspace .vscode/settings.json overriding your user settings with "editor.formatOnSave": false? (4) Open the Output panel (Ctrl+Shift+U) and select your formatter from the dropdown — error messages appear there. (5) Try reloading the window (Ctrl+Shift+P → Reload Window).
Does VS Code have a built-in formatter?
Yes. VS Code ships with built-in formatters for JavaScript, TypeScript, JSON, HTML, and CSS that handle basic indentation, semicolons, and quote style — no extension required. For more opinionated formatting (trailing commas, print width, bracket spacing) you need an extension like Prettier. The built-in formatter is identified as vscode.typescript-language-features in the editor.defaultFormatter setting.
How do I turn off format on save?
Set "editor.formatOnSave": false in your user settings (global) or in .vscode/settings.json (workspace). To disable it for a single language only, use a language-specific block — for example [markdown] with "editor.formatOnSave": false. To skip formatting on a one-off save, run File: Save without Formatting from the Command Palette.

Enabled format on save and want to verify the formatter only touched whitespace? Paste the before and after versions of your file into Diff Checker, switch to "Ignore Whitespace" mode, and confirm zero logic changes — all locally, no uploads. Diff Checker also includes a Format Code button (Prettier, 20+ languages) so you can preview exactly what Prettier will do to any snippet before committing.

Install Diff Checker — Free Chrome Extension