Formatting and styles
Set font, paragraph, style, and hyperlink properties while preserving authored and inherited formatting.
Set character formatting through Body.font, Paragraph.font, or Range.font. Set paragraph formatting directly on Paragraph. The API does not provide a ParagraphFormat object or a style-creation API.
Create a runtime with Runtime and setup. Use context and document proxies inside runtime.run().
Format an exact phrase
Find the target, then batch related assignments on the same proxy:
await runtime.run(async (context) => {
const matches = context.document.body.search('Confidential', {
matchCase: true,
});
matches.load('items');
await context.sync();
for (const match of matches.items) {
const font = match.font;
font.bold = true;
font.color = '#A00000';
font.highlightColor = 'Yellow';
font.underline = 'Single';
}
await context.sync();
});Assignments on one Font proxy coalesce within a sync. Different proxies that address overlapping content can still conflict. The runtime tracks font, paragraph-format, and paragraph-style writes as property revisions. Accept retains the changes; reject restores previous properties. Never switch tracking off automatically to bypass that refusal.
Font writes use effective complex-script properties from direct formatting, character styles, paragraph styles, table styles, and document defaults. Bold, italic, size, and font-name writes update the complex-script properties when those properties control the text. Direct false values override inherited direction.
Read authored font values
Load only the properties you need:
await runtime.run(async (context) => {
const font = context.document.body.font;
font.load(['bold', 'name', 'size']);
await context.sync();
if (font.size !== null) console.log(`Authored size: ${font.size} pt`);
});Every font getter can return null. That means mixed values, no authored value, or formatting supplied through inheritance. These reads do not calculate the rendered style cascade. Do not convert null into a formatting write.
Font property | Write domain |
|---|---|
bold, italic, strikeThrough | Boolean |
name | Font family name; your rendering host supplies its font resources |
size | Positive finite point size within the supported OOXML range |
color | Concrete #RRGGBB color |
underline | Supported UnderlineType value or matching string |
highlightColor | Exact Word palette name or its hexadecimal color; null clears highlighting |
subscript, superscript | Boolean; both cannot be true in the same write |
Underline writes support None, Single, Word, Double, Thick, Dotted, DottedHeavy, DashLine, DashLineHeavy, DashLineLong, DashLineLongHeavy, DotDashLine, DotDashLineHeavy, TwoDotDashLine, TwoDotDashLineHeavy, Wave, WaveHeavy, and WaveDouble. The exported enum also includes Mixed, Hidden, and DotLine, which the runtime rejects on writes. For example, UnderlineType.single has the value Single.
Highlight names are Yellow, Lime, Turquoise, Pink, Blue, Red, DarkBlue, Teal, Green, Purple, DarkRed, Olive, Gray, LightGray, Black, and White. Reads return #RRGGBB or null. The runtime rejects colors outside that palette. The getter returns string | null; the setter keeps the Office.js string declaration.
Clear highlighting
Microsoft documents null for clearing highlights, despite the string declaration. See Word.Font.highlightColor. The runtime supports that documented value. Use an explicit compiler annotation for the assignment:
await runtime.run(async (context) => {
const font = context.document.body.font;
// @ts-expect-error Office.js declares string but documents null clearing.
font.highlightColor = null;
await context.sync();
});The compiler reports an unused annotation if the declaration later accepts null.
Format paragraphs
Paragraph measurements use points:
await runtime.run(async (context) => {
const paragraph = context.document.paragraphs.getFirst();
paragraph.load('text');
await context.sync();
paragraph.alignment = 'Left';
paragraph.leftIndent = 18;
paragraph.firstLineIndent = -9;
paragraph.lineSpacing = 14;
paragraph.spaceAfter = 6;
await context.sync();
});leftIndent, rightIndent, firstLineIndent, lineSpacing, spaceBefore, and spaceAfter accept finite values within their supported bounds. A negative first-line indent creates a hanging indent. ParagraphAlignment and Alignment provide Left, Centered, Right, and Justified writes. Mixed and Unknown are read values; the runtime rejects them on writes. Assignments on one paragraph proxy coalesce per sync.
Justified paragraphs in compatibility mode 15 or later can compress ordinary spaces to fit a word. Latin words retain their complete-word fit across formatting runs, including separate terminal punctuation.
Right-to-left paragraphs
Paragraph.alignment reads and writes the stored w:jc value. In a right-to-left paragraph, Left selects the leading edge at the right margin. Right selects the trailing edge at the left margin. Alignment does not change paragraph direction.
The document automation API does not expose a paragraph direction property. For browser editor commands, see Right-to-left text.
Apply an existing style
Body.style, Paragraph.style, and Range.style address paragraph styles by display name. The name must already exist in the document's styles part. The runtime rejects unknown style names. Assigning a name does not create a style. A body assignment applies to its paragraphs. A range assignment applies to its addressed paragraphs. Load style before reading it; mixed or unspecified authored styles can return null at runtime.
Use a template with known styles, then assign its exact style name:
paragraph.style = 'Heading 1'; // The template must define this display name.
await context.sync();Table.style is separate. See Tables and cells.
Set a hyperlink
Range.hyperlink reads or writes a hyperlink for supported text spans. Load hyperlink before reading it. For a write, assign a permitted URL and sync:
range.hyperlink = 'https://example.com/terms';
await context.sync();Assign an empty string to remove a hyperlink from an eligible text span. Ordinary partial spans inside an existing hyperlink support retargeting and unlinking. The unaffected linked text keeps its metadata and formatting. The runtime rejects collapsed ranges and complex or nested hyperlink wrappers. The runtime validates the URL and content boundaries. Failed edits leave unsupported or protected targets unchanged. There is no standalone Hyperlink or HyperlinkCollection object.
Hidden paragraph marks
The layout supports a bounded subset of style separators in the document body. Each joined mark must enable w:vanish after style resolution. The paragraph must contain ordinary visible text unless its mark also enables w:specVanish. Adjacent members must share continuation indents, alignment, line spacing, ordinary tabs, borders, shading, and keep constraints. Paragraph direction and paragraph line-breaking settings must also agree. The first member supplies numbering, first-line geometry, and before-spacing. The last member supplies after-spacing and final paragraph-mark formatting. Each member keeps its inherited text formatting and source offsets. Paragraph formatting edits still address the original source paragraph.
Mixed geometry, contextual spacing, tracked content, section boundaries, cross-paragraph fields, and chains above 64 members remain separate. Table cells, notes, headers, footers, and text boxes do not use this display join. Export reports unsupported-style-separator when visible-content hidden marks cannot use this join. The source content stays preserved on save.
Next steps
See Text and ranges for selecting the text target.