rangeStart β the start of a partial format, and how Format Selection actually works
The Prettier Range Start option
rangeStart is the character offset where Prettier begins formatting, leaving everything before it untouched. Together with rangeEnd it is the mechanism behind every editor's Format Selection command, and it is an API option rather than something you put in a config file.
Format code starting at a given character offset.
The range will extend backwards to the start of the first line containing the selected statement.- Default
0- Type
int- CLI flag
--range-start
What the option does
Prettier normally reformats a whole file. rangeStart and rangeEnd narrow that to a slice, measured in characters from the beginning of the file. Text outside the range is emitted exactly as it was.
import * as prettier from 'prettier';
const output = await prettier.format(source, {
parser: 'typescript',
rangeStart: 120,
rangeEnd: 340,
});The default is 0 β the start of the file β and rangeEnd defaults to the end, so together they format everything unless you narrow them.
Why the range gets widened
Prettier will not format a fragment of a statement, because a fragment usually is not parseable and would not have a well-defined layout in isolation. So the range you request is expanded outwards to the nearest enclosing statement boundaries before anything is formatted.
This is why selecting the middle of an expression in your editor and asking for Format Selection reformats the whole statement. It is not the editor being imprecise β it is Prettier refusing to produce output whose correctness it cannot guarantee.
Indentation of the surrounding context is preserved, so the formatted slice lines up with the code around it rather than being re-indented to column zero.
Practical limits
- Offsets are characters, not bytes and not line/column pairs. Multi-byte characters count as one.
- Not every parser supports ranges equally well; the CSS and Markdown parsers are more restrictive than the JavaScript ones.
- Range formatting can produce output that differs from formatting the whole file, because decisions such as where a line breaks depend on context the range excludes.
- It is not a substitute for
.prettierignoreor// prettier-ignore. Those express a durable intent; a range is a one-off instruction.
Common mistakes
- Putting
rangeStartin.prettierrc. It is meaningful per invocation, and a config file applies to every invocation β the result is a project that only ever formats from that offset. - Expecting the exact selection to be formatted rather than the enclosing statements.
- Computing offsets in bytes on a file containing non-ASCII characters.
- Assuming a ranged format gives the same result as a whole-file format. It often does, but it is not guaranteed.
How far the range actually expands
The expansion is to statement boundaries, not to the nearest newline or the nearest brace. Prettier walks up the syntax tree from the offsets you gave until it reaches nodes it can print independently, and formats from the start of the first to the end of the last.
In practice that means selecting half of one function and half of the next reformats both in full. Selecting a single property of an object literal reformats the whole literal, because a property is not something Prettier can lay out without knowing whether its siblings fit.
Text outside the expanded region is copied through byte for byte, including trailing whitespace and unusual indentation. A ranged format never tidies what it did not touch.
On the command line
Both range options exist as CLI flags, though they are rarely the right tool there because the CLI has no notion of a selection:
npx prettier --range-start 120 --range-end 340 src/app.tsCombining them with --write across a glob is a mistake worth naming: the same offsets would be applied to every matched file, slicing each at positions that mean nothing in that file. Ranges are a single-file operation.
Use it in .prettierrc
Drop rangeStart into your Prettier config file:
{
"rangeStart": 0
}Try it in the generatorCommon questions
- Why did Format Selection reformat more than I selected?
- Prettier expands the range to the nearest enclosing statement boundaries, because a partial statement has no well-defined formatting.
- Should I set rangeStart in my .prettierrc?
- No. It is a per-invocation API option. In a config file it would apply to every format and skip the beginning of every file.
- Are the offsets in bytes?
- Characters. A multi-byte character counts once.
Other Special options
Generated from Prettier 3.9.6.