Styling and colors
TextStyle
Section titled “TextStyle”TextStyle is an immutable record where every property is optional:
public sealed record TextStyle( float? FontSize = null, FontWeight? FontWeight = null, // LIGHT … BLACK on the CSS scale bool? Italic = null, bool? Underline = null, Color? Color = null, TextAlignment? Alignment = null, // LEFT, CENTER, RIGHT, JUSTIFY string? FontFamily = null, bool? Strikethrough = null, TextScript? Script = null, // Superscript / Subscript float? LetterSpacing = null); // points per glyph, negative tightensFont weights beyond Normal/Bold render as true cuts only in PDF with fonts registered per weight (doc.RegisterFontVariant("Brand", FontWeight.Light, lightTtf)); the built-in fonts and DOCX/XLSX collapse to regular/bold (SemiBold and up count as bold). Letter spacing has no XLSX equivalent and is dropped there; sub/superscript in XLSX styles the whole cell (a worksheet cell holds one font).
Every property also has a fluent With* method, so TextStyle.Default (an all-null style) can be chained instead of naming every property up front:
TextStyle.Default.WithFontSize(24f).Bold().WithColor(Colors.Blue.Medium)Bold(), AlignLeft()/AlignCenter()/AlignRight()/AlignJustify(), and Superscript()/Subscript() are shortcuts over WithFontWeight, WithAlignment, and WithScript. Both forms produce the same immutable record - pick named-argument construction when building a style from data, and the fluent chain when composing one inline.
Unset properties inherit. A style you pass at a text run merges with the document’s DefaultTextStyle; whatever the run doesn’t specify falls back:
doc.DefaultTextStyle(TextStyle.Default.WithFontSize(10f).WithFontFamily("Liberation Sans")) .Paragraph(p => p.Text("10pt body text")) .Paragraph(p => p.Text("24pt heading, still Liberation Sans", TextStyle.Default.WithFontSize(24f)));Define your document’s styles once as constants and reuse them - see your first invoice for the pattern.
A run-appending call like Text(...) also accepts styling chained directly off it (.Text("...").FontSize(14).Bold()), as an alternative to passing a TextStyle argument - see Styling a run inline. To apply a whole style built elsewhere, chain WithStyle(preset): its explicit properties win, and it falls back to whatever the run already had for anything it leaves unset - the same fallback direction as Merge above, just applied at the call site instead of at layout time.
Paragraph styles
Section titled “Paragraph styles”Block-level layout options live on ParagraphStyle - same nullable-and-inherit pattern, with DefaultParagraphStyle as the document-wide fallback:
public sealed record ParagraphStyle( float? SpacingBefore = null, // points above the paragraph float? SpacingAfter = null, // points below float? LineSpacing = null, // multiple of the font size; built-in 1.2 float? IndentLeft = null, float? IndentRight = null, float? IndentFirstLine = null, Color? BackgroundColor = null);Same fluent With* methods and a ParagraphStyle.Default anchor apply here too: ParagraphStyle.Default.WithSpacingAfter(12f).WithLineSpacing(1.5f). These options are also chainable directly off Paragraph(...) (.Paragraph(...).SpacingAfter(12f).LineSpacing(1.5f)) with a WithStyle(preset) for a whole reusable style - see Paragraph layout.
Usage and per-format behavior are covered in text and paragraphs.
Cell styles
Section titled “Cell styles”Table cells take a CellStyle - built as a record or fluently from CellStyle.Default. Cell(...) also accepts the same styling chained directly off the call - see Cells.
var header = new CellStyle( Padding: new Thickness(8f, 6f), Border: new CellBorder(0.75f, Colors.Grey.Lighten1), BackgroundColor: Colors.Grey.Lighten3, HorizontalAlignment: TextAlignment.Left, VerticalAlignment: VerticalAlignment.Middle);
var sameHeader = CellStyle.Default .WithPadding(new Thickness(8f, 6f)) .WithBorder(new CellBorder(0.75f, Colors.Grey.Lighten1)) .WithBackgroundColor(Colors.Grey.Lighten3) .WithHorizontalAlignment(TextAlignment.Left) .WithVerticalAlignment(VerticalAlignment.Middle);CellBorder takes either one uniform width or an independent width per side (left, top, right, bottom) with one shared color and one shared stroke style - a side with width 0 is not drawn:
new CellBorder(1f, Colors.Grey.Lighten1); // all four sidesnew CellBorder(0f, 0f, 0f, 1f); // bottom only, explicitCellBorder.BottomOnly(1f, Colors.Grey.Lighten1); // same, via factoryCellBorder.TopOnly(2f); // also: Horizontal, Verticalnew CellBorder(1f, style: LineStyle.Dashed); // also: LineStyle.DottedThe style applies to all four sides, like the color. See the tables guide for the per-format mapping (XLSX’s single style axis makes non-solid styles lossy there).
Colors
Section titled “Colors”Color parses hex in four forms and converts implicitly from strings:
new TextStyle(Color: "#0F766E"); // #RRGGBBnew TextStyle(Color: "#80FF0000"); // #AARRGGBB - 50% alpha rednew TextStyle(Color: "#F00"); // #RGB shorthandTextStyle.Default.WithColor("#0F766E"); // fluent form - implicit string conversion still appliessomeColor.WithAlpha(128); // derive a translucent variantAlpha behaves differently per format: PDF renders true transparency, DOCX blends against white, XLSX stores the ARGB value. See the feature support matrix.
The Material palette
Section titled “The Material palette”The full Google Material palette ships as constants - 19 hues, each with Lighten5–Lighten1, Medium, Darken1–Darken4, and Accent1–Accent4:
Colors.Blue.MediumColors.Grey.Lighten3Colors.Teal.Darken2Colors.Red.Accent2A visual swatch grid is in page sizes and colors.
© 2026 Stefan Nikolei. Payments are processed by Paddle.com as merchant of record.