What does Prettier change, and why?
Prettier Defaults Explained
Prettier parses your code into a syntax tree, throws away almost all of the original formatting, and prints the tree again using a fixed algorithm and a small set of options. With the defaults, that means lines that aim to fit within 80 columns, two-space indentation, semicolons at the end of statements, double quotes unless single quotes avoid escaping, trailing commas wherever the language allows them, spaces inside object braces, and parentheses around every arrow function parameter. The only things it keeps from your input are the code itself, comments, single blank lines, and a couple of deliberate hints such as whether an object literal started on a new line. The reasoning behind every default is the same: remove style from code review by making one consistent choice that produces small, predictable diffs.
What happens to a file
The input below has inconsistent quotes, a cramped object, an arrow function without parentheses, and a function whose signature and body are far too long for one line. Paste it into the JavaScript Formatter, which runs Prettier with its default options:
const user = {
name: 'Asha', role: 'admin' }
const inline = { name: 'Ben',
role: 'editor' }
const double = x => x * 2
export async function loadOrders(customerId, { status, limit, cursor }, signal) { return fetchJson(`/api/customers/${customerId}/orders`, { status, limit, cursor, signal }) }The output:
const user = {
name: "Asha",
role: "admin",
};
const inline = { name: "Ben", role: "editor" };
const double = (x) => x * 2;
export async function loadOrders(
customerId,
{ status, limit, cursor },
signal,
) {
return fetchJson(`/api/customers/${customerId}/orders`, {
status,
limit,
cursor,
signal,
});
}Almost every default is visible here. The rest of this guide goes through them one by one.
The defaults
| Option | Default | History | What it does |
|---|---|---|---|
printWidth |
80 |
Unchanged | Target line length Prettier tries to fit within |
tabWidth |
2 |
Unchanged | Spaces per indentation level |
useTabs |
false |
Unchanged | Indent with spaces |
semi |
true |
Unchanged | Semicolon at the end of every statement |
singleQuote |
false |
Unchanged | Prefer double quotes |
jsxSingleQuote |
false |
Added in 1.15 | Double quotes in JSX attributes |
quoteProps |
"as-needed" |
Added in 1.17 | Quote object keys only where required |
trailingComma |
"all" |
Default since 3.0; "es5" in 2.x, "none" before |
Trailing commas in every multi-line list the syntax allows |
bracketSpacing |
true |
Unchanged | { a } rather than {a} |
objectWrap |
"preserve" |
Added in 3.5; the behaviour is older | Keep an object expanded if its first key is on a new line |
bracketSameLine |
false |
Added in 2.4 | Put the > of a multi-line JSX or HTML tag on its own line |
arrowParens |
"always" |
Default since 2.0; "avoid" before |
(x) => x, never x => x |
endOfLine |
"lf" |
Default since 2.0; "auto" before |
Unix line endings |
proseWrap |
"preserve" |
Added in 1.8.2 | Leave Markdown line breaks alone |
htmlWhitespaceSensitivity |
"css" |
Added in 1.15 | Respect the CSS display of inline elements |
embeddedLanguageFormatting |
"auto" |
Added in 2.1 | Format CSS, GraphQL and HTML embedded in template literals |
singleAttributePerLine |
false |
Added in 2.6 | Allow several attributes per line in JSX and HTML |
The Formattr code formatters expose the options that teams most often change (Print width, Tab width, Semicolons, Single quotes and Trailing commas) and use Prettier's defaults for the rest.
printWidth: 80
This is a target, not a limit. Prettier fits each construct on one line if it can and breaks it at the outermost group if it cannot, so loadOrders above broke its parameter list first, then its body. Long strings, URLs and comments are never broken, so lines can exceed 80. Prettier's own guidance is to keep the default: with a wider limit, fewer lines break, but the lines that remain get harder to read, and wide values make side-by-side diffs awkward.
semi: true
JavaScript's automatic semicolon insertion (ASI) lets you omit semicolons, but a line starting with (, [ or a template literal (among a few other characters) continues the previous statement. With semi: false, Prettier protects you by adding a leading semicolon exactly where that hazard exists:
let x = 1
;[1, 2].forEach((n) => console.log(n))Both styles are safe under Prettier. The default is true because it is what most JavaScript is written in and it needs no explanation to newcomers.
Quotes: singleQuote: false
Prettier normalises all string quotes to double quotes, except where the other quote character would require fewer escapes: 'say "hi"' stays single-quoted, and "it's" stays double-quoted. Double quotes are the default; they match JSON and HTML attributes, and apostrophes in English text never need escaping inside them. Setting singleQuote: true keeps the same escape-minimising rule with the preference reversed. JSX attributes have a separate option, because HTML convention is double quotes regardless of the JavaScript style.
quoteProps: "as-needed" removes quotes from object keys when they are valid identifiers: {'a': 1, 'b-c': 2} prints as { a: 1, "b-c": 2 }.
trailingComma: "all"
A trailing comma after the last element of a multi-line array, object, parameter list or argument list means that adding an item changes one line in the diff instead of two, and reordering lines never produces a missing-comma error. The default moved from "es5" to "all" in Prettier 3.0 because trailing commas in function parameters and calls (standardised in ES2017) are supported by every runtime Prettier targets. With "es5", the loadOrders parameters above end with signal and no comma; object and array literals keep theirs. Choose "none" only if your code must run in an engine older than ES2017 without a compiler.
The same reasoning is why JSON's lack of trailing commas causes so many JSON errors: the habit is correct everywhere else.
bracketSpacing and objectWrap
{ name: "Ben" } gets spaces inside the braces. More interesting is when an object is expanded. Prettier collapses an object onto one line if it fits, unless there is a newline between the { and the first key in the input. In the example, user stayed multi-line because its first key was on a new line, while inline collapsed because its first key followed the brace. This is one of the few places where your input formatting matters, and it gives you a way to keep configuration objects expanded. Prettier 3.5 made the behaviour configurable as objectWrap; "collapse" ignores the hint.
arrowParens: "always"
x => x * 2 becomes (x) => x * 2. The reason is edit stability: adding a second parameter or a type annotation to a parenthesised parameter changes only what is inside the parentheses. In TypeScript, a type annotation requires them anyway.
endOfLine: "lf"
Prettier writes LF line endings regardless of the input. Before 2.0 the default was "auto", which kept whatever the file had and let mixed CRLF and LF endings persist across a team. With "lf", pair it with * text=auto eol=lf in .gitattributes so that Git on Windows does not convert files back; the Line Ending Converter fixes files that are already mixed.
Things Prettier decides without an option
Blank lines. Runs of blank lines collapse to one; single blank lines are kept. Blank lines at the start of a block are removed.
Method chains. A chain of several calls with function arguments usually breaks one call per line even when it would fit, because long chains are easier to read vertically:
JavaScriptconst r = items .filter((i) => i.active) .map((i) => i.id) .slice(0, 10) .join(",");JSX. Multi-line JSX is wrapped in parentheses, and text children move to their own line when the element breaks.
TypeScript. Types follow the same rules as values. In a
.tsfile,function id<T,>(x: T)prints asfunction id<T>(x: T); the comma is only needed in.tsx, where<T>alone would parse as a JSX tag. The TypeScript Formatter uses the TypeScript parser, so it applies these rules.Escape hatch. A
// prettier-ignorecomment leaves the next statement or node exactly as written, which is useful for hand-aligned matrices and tables.
What Prettier does not do is equally deliberate: it does not reorder imports, rename anything, remove unused code, or change behaviour. Those belong to linters and compilers. A common setup runs Prettier for layout and a linter only for correctness rules, with the linter's formatting rules disabled so the two never disagree.
When to change the defaults
Prettier's option philosophy is to add options only for long-standing, strongly held preferences, and to resist new ones. In practice, teams change at most three:
printWidth, to 100 or 120, when identifiers are long (common in Java-influenced TypeScript codebases).singleQuote: true, when the codebase already uses single quotes and a mass reformat is unwanted.semi: false, as a matter of taste; it is safe under Prettier.
Whatever you choose, commit a configuration file so that editors, CI and every contributor produce identical output, and format the whole codebase once in a dedicated commit so that later diffs only show real changes. For naming, which Prettier never touches, see naming conventions.