← All Documentation

Text & Spans

Single-String Text

The simplest form — one string, block-level style:

container.Text("Hello, world!");

Chain style methods on the returned TextDescriptor to format the whole block:

container.Text("Section Heading")
    .Bold()
    .FontSize(16)
    .FontColor(Color.Blue.Darken2)
    .AlignCenter();

All TextDescriptor style methods

Method Effect
.Bold() Bold weight
.SemiBold() Semi-bold (mapped to bold in the built-in font set)
.Italic() Italic style
.Strikethrough() Horizontal strikethrough line
.Underline() Underline beneath the text
.FontSize(double) Font size in PDF points
.LineHeight(double) Line-height multiplier (e.g. 1.0 = tight, 1.4 = default, 2.0 = double-spaced)
.FontColor(string) Hex colour, e.g. "#1a4a8a" or Color.Red.Medium
.AlignLeft() Left-align (default)
.AlignCenter() Centre-align
.AlignRight() Right-align
.Justify() Justify all lines except the last

Multi-Span Text

Use the Action<TextDescriptor> overload to compose a text block from multiple independently styled spans.

container.Text(t =>
{
    t.Span("Normal  ");
    t.Span("Bold  ").Bold();
    t.Span("Italic  ").Italic();
    t.Span("Struck  ").Strikethrough();
    t.Span("Coloured  ").FontColor(Color.Red.Medium);
    t.Span("Large").FontSize(16).FontColor("#1a4a8a");
});

Important: t.Span(...) returns a SpanDescriptor, not a TextDescriptor. Style methods chained after .Span() apply only to that span. This is intentional — it prevents accidental formatting of the whole block.

SpanDescriptor methods

Method Effect
.Bold() Bold weight for this span
.SemiBold() Semi-bold for this span
.Italic() Italic for this span
.Strikethrough() Strikethrough for this span
.Underline() Underline for this span
.FontSize(double) Font size for this span
.FontColor(string) Text colour for this span

Page Numbers

CurrentPageNumber() and TotalPages() also return SpanDescriptor so they can be individually styled:

page.Footer().AlignCenter().Text(t =>
{
    t.Span("Page ").FontSize(9).FontColor(Color.Grey.Medium);
    t.CurrentPageNumber().FontSize(9).FontColor(Color.Grey.Medium);
    t.Span(" of ").FontSize(9).FontColor(Color.Grey.Medium);
    t.TotalPages().FontSize(9).FontColor(Color.Grey.Medium);
});

Mixing Styles in One Block

Because the block's alignment is controlled at the TextDescriptor level, you can combine per-span colour/size with a block-level alignment:

container.Text(t =>
{
    t.Span("Status: ").Bold();
    t.Span("Approved").FontColor(Color.Green.Darken2).Bold();
    t.Span("  (June 2025)").FontColor(Color.Grey.Medium).FontSize(9);
})
.AlignRight();

Underline

.Underline() draws a line beneath the text. It works on both the whole block (TextDescriptor) and on individual spans (SpanDescriptor).

// Whole block underlined
container.Text("Important notice").Underline().Bold();

// Only one span underlined in a mixed block
container.Text(t =>
{
    t.Span("Visit ");
    t.Span("TerraPDF").Underline().FontColor(Color.Blue.Medium);
    t.Span(" for more info.");
});

// Underline and strikethrough can be combined
container.Text("Deprecated").Underline().Strikethrough().FontColor(Color.Grey.Medium);

Line Height

.LineHeight(double) sets a multiplier applied to the natural line height. The default multiplier is approximately 1.4.

container.Text("Tight paragraph.").LineHeight(1.0);
container.Text("Normal paragraph.").LineHeight(1.4);
container.Text("Relaxed paragraph.").LineHeight(1.6);
container.Text("Double-spaced paragraph.").LineHeight(2.0);

Line height can also be set page-wide via DefaultTextStyle:

page.DefaultTextStyle(s => s.FontSize(11).LineHeight(1.5));

Default Text Style

A page-wide default style is set on PageDescriptor and inherited by all text unless explicitly overridden at the block or span level:

page.DefaultTextStyle(s => s.FontSize(11).FontColor(Color.Grey.Darken2));

Style resolution order (highest wins):

Span style  >  Block style (TextDescriptor)  >  Page default style  >  Library default (12 pt, black)