Overview

EggPdf.Fluent lets you describe a document with C# method calls. It builds the same DOM the HTML parser would produce and hands it to the normal pipeline — cascade, layout, pagination, paint, PDF writer — so there is no HTML string in the middle, no escaping to get wrong, and the output is byte-for-byte the kind of PDF the HTML API makes. Because it is the same engine, anything HTML/CSS can express, the fluent API can express (see escape hatches).

It ships inside the main EggPdf package — there is nothing extra to install. Add using EggPdf.Fluent; and call Document.Create(...).

dotnet add package EggPdf

Quick start

using EggPdf.Fluent;

byte[] pdf = Document.Create(doc => doc
    .Title("Invoice INV-142")
    .Page(page => page
        .Size(PageSize.A4)
        .Margin(top: 70, right: 30, bottom: 50, left: 30)
        .Header(h => h.Text("Acme Corp").Bold().FontSize(18))
        .Footer(f => f.AlignCenter().PageNumberOfTotal())      // "Page 2 of 5"
        .Watermark("DRAFT")
        .Content(c =>
        {
            c.Heading(HeadingLevel.H1, "Invoice");              // also a PDF bookmark
            c.Item().Row(row =>
            {
                row.RelativeItem().Text("Bill to: Jane Doe");
                row.ConstantItem(Length.Mm(40)).AlignRight().Text("2026-09-24");
            });
            c.Item().Table(table =>
            {
                table.Header(h => { h.Cell().Text("Item").Bold(); h.Cell().Text("Qty").Bold(); });
                foreach (var line in lines)
                    table.Row(r => { r.Cell().Text(line.Name); r.Cell().Text(line.Qty.ToString()); })
                         .AvoidBreakInside();
            });
            c.Item().PinBottom().Border(1, Colors.Gray).Padding(10).Text("Signature");
        })))
    .Render();

Document.Create(...) returns a DocumentBuilder with Render(), RenderAsync(ct) and RenderToFileAsync(path, ct).

Building step by step

The nested form above is one style. You can equally create the document, keep it in a variable, and fill in the header, footer and body in separate statements — or separate methods. Every callback method has a parameterless twin that returns the thing to fill in (Header(), Footer(), Content(), Row(), Table(), Grid(...), BulletList(), NumberedList(), Column()), and Document.New() / AddPage() replace Document.Create / Page. Both styles produce byte-identical PDFs.

var doc  = Document.New().Title("Report");
var page = doc.AddPage().Size(PageSize.A4).Margin(30);

page.Header().Text("Acme").Bold();
page.Footer().AlignCenter().PageNumberOfTotal();

var body = page.Content();
body.Heading(HeadingLevel.H1, "Summary");
body.Item().Text("Quarterly results");
AddSalesTable(body);                       // ordinary helper method: one per report section

byte[] pdf = doc.Render();                 // or RenderAsync(ct) / RenderToFileAsync(path, ct)

static void AddSalesTable(ColumnDescriptor content)
{
    var table = content.Item().Table();
    table.Header(h => { h.Cell().Text("Region").Bold(); h.Cell().Text("Sales").Bold(); });
    table.Row(r => { r.Cell().Text("North"); r.Cell().Text("1,200"); });
}
  • Page settings can be changed at any point before rendering (page.Size(...) after adding content is fine) — the @page rule is written when the document is built.
  • page.Content() can be called more than once; items append in call order.
  • Rendering builds and freezes the document. You can render it again (identical output), but any further change — AddPage(), Text(...), Bold(), Title(...), … — throws InvalidOperationException rather than being silently lost. Call Build() to freeze it explicitly.
  • The nested callbacks also accept normal statements and calls to helper methods that take a Container/ColumnDescriptor, so you can mix the two styles freely.

Method chaining

Styling and configuration methods return the object they were called on, so they chain (.Text("Hi").FontSize(20).Bold().Padding(8)). The methods that add a child (Item, Cell, RelativeItem, ConstantItem, Heading, table Header/Row) normally return that child, which is what lets you style it. Each also has an overload taking a callback that returns the parent instead, so siblings chain too and a whole document is one expression:

Document.Create(doc => doc
    .Title("Chained")
    .Page(p => p.Size(PageSize.A4).Margin(30).Content(c => c
        .Item(i => i.Text("Intro").Bold())
        .Heading(HeadingLevel.H2, "Section", h => h.FontColor(Colors.Navy))
        .Item(i => i.Row(r => r
            .Gap(5)
            .RelativeItem(x => x.Text("Left"))
            .ConstantItem(60, x => x.Text("Mid"))
            .RelativeItem(2, x => x.Text("Wide"))))
        .Item(i => i.Grid(2, g => g
            .Item(x => x.Text("G1"))
            .Item(2, x => x.Text("Spans both columns"))))
        .Item(i => i.BulletList(l => l.Item(x => x.Text("One")).Item(x => x.Text("Two"))))
        .Item(i => i.Table(t => t
            .Header(h => h.Cell(x => x.Text("Item")).Cell(x => x.Text("Qty")), r => r.Background(Colors.LightGray))
            .Row(r => r.Cell(x => x.Text("Widget")).Cell(x => x.Text("3")), r => r.AvoidBreakInside()))))))
    .Render();

The table overloads take a second callback that styles the row box itself. All three styles — chained, nested statements, and step by step — can be mixed freely and produce identical PDFs. Pages chain through Page(...): doc.Page(...).Page(...).

Structure

The builder is a tree of small descriptor types; each callback receives the one you need next:

TypeWhat it configures
DocumentDescriptorDocument-wide: title, author, language, CSS, fonts, PDF options, and Page(...) groups.
PageDescriptorOne page group: size, margins, header, footer, watermark, Content(...).
ColumnDescriptorStacked children: Item() and Heading(level, text).
ContainerA box. Everything you place returns a Container, so styling always applies to what you just placed.
RowDescriptor / GridDescriptor / TableDescriptor / ListDescriptorChildren of a row (flex), grid, table or list.

Typed values — no magic strings

A misspelled CSS keyword, color or unit is silently ignored by a CSS engine, which makes for PDFs that look wrong with no error anywhere. Every typed method therefore takes a typed value, and constructing an invalid one fails immediately.

TypeUseValidation
Color / ColorsColors.Red, Color.FromRgb(255, 0, 0), Color.FromRgba(0, 0, 0, 128), Color.FromHex("#f00")FromHex accepts #rgb, #rgba, #rrggbb, #rrggbbaa only. There is deliberately no implicit conversion from string.
LengthLength.Px/Pt/Mm/Cm/In/Em/Percent, Length.Auto. A bare number converts to pixels: Width(200).NaN / infinity throw.
Keyword enumsOverflowMode, PositionMode, DisplayMode, FloatSide, FlexJustify, FlexAlign, TextCase, BorderLineStyle, WhiteSpaceMode, TextDirection, HeadingLevelExhaustive mapping to CSS; an undefined value throws.
CssTransformCssTransform.Rotate(10).Then(CssTransform.Scale(1.2f)); also Translate, SkewX, SkewYComposes in order.
GridTrackGridTrack.Fr(2), GridTrack.Fixed(Length.Px(80)), GridTrack.AutoFr must be positive.

Numeric ranges are checked too: Opacity (0–1), FontWeight (1–1000), LineHeight (positive), grid column counts and spans (≥ 1). Plain string parameters remain only where the value is genuinely free text: content, URLs and paths, ids and class names, font family names, titles.

Content

Text and styling

c.Item()
    .Text("Quarterly report")
    .FontSize(20).Bold().FontColor(Colors.Navy)
    .LetterSpacing(Length.Px(0.5f)).TextTransform(TextCase.Uppercase)
    .Padding(8, 12).Background(Color.FromHex("#f1f5f9"))
    .Border(1, Colors.LightGray, BorderLineStyle.Dashed).BorderRadius(6)
    .BoxShadow(0, 2, 6, Color.FromRgba(0, 0, 0, 64));
AreaMethods
TypographyFontSize, FontFamily, Bold, Italic, FontWeight, FontColor, LineHeight (multiplier or Length), LetterSpacing, Underline, StrikeThrough, NoTextDecoration, TextTransform, WhiteSpace, AlignLeft/AlignCenter/AlignRight
Box modelPadding and Margin (1, 2 or 4 values), Width, Height, MinWidth, MaxWidth, MinHeight, MaxHeight
DecorationBackground, Border, BorderTop/Right/Bottom/Left, BorderRadius, BoxShadow, Opacity
Layout / effectsOverflow, Position, Display, Float, Transform
AttributesId, Class (repeatable), Direction

Column and Row

A column is normal block flow (Item() per child). A row is a flex container: items are RelativeItem(weight) (shares remaining space) or ConstantItem(width) (fixed). The row itself is styled through RowDescriptor:

c.Item().Row(row =>
{
    row.Gap(12).JustifyContent(FlexJustify.SpaceBetween).AlignItems(FlexAlign.Center).Wrap();
    row.RelativeItem(2).Text("Wide");
    row.RelativeItem(1).Text("Narrow");
    row.ConstantItem(Length.Mm(30)).Text("Fixed");
});

Grid

c.Item().Grid(new[] { GridTrack.Fr(1), GridTrack.Fr(2) }, g =>
{
    g.Gap(10).AutoRows(Length.Px(40));
    g.Item().Text("A");
    g.Item().Text("B");
    g.Item(columnSpan: 2).Text("Spans both columns");
});
c.Item().Grid(3, g => { /* three equal columns */ });

Tables

table.Header(...) emits a real <thead>, which repeats at the top of every continuation page when the table spans pages (see Tables). Header and Row return the row so you can style it — .AvoidBreakInside() keeps a row from splitting across a page break. Cells default to 4×8 px padding and a light 1 px border; restyle any cell through the returned Container. Tables default to 100% width with collapsed borders.

c.Item().BulletList(l => { l.Item().Text("One"); l.Item().Text("Two"); });
c.Item().NumberedList(l => l.Item().Text("First"));
c.Item().Image("logo.png", widthPx: 80, heightPx: 40);      // path, URL or data: URI
c.Item().Hyperlink("https://example.com", "Visit us");
c.Heading(HeadingLevel.H2, "Section");                       // real <h2>: bookmark + PDF/UA heading

Relative image paths resolve against DocumentDescriptor.BasePath(...). Headings must be created with Heading(...) (not a styled Item()) — bookmarks and the accessibility structure tree key off the real h1–h6 tags.

Give a box an id and link to it. The link is a real PDF destination (page + position), so it jumps forward or backward to any page:

c.Item().Hyperlink("#terms", "See the terms");
// ...
c.Item().Id("terms").Text("Terms and conditions");
ℹ️
The same works in HTML (<a href="#terms"> + <div id="terms">). If the id doesn't exist (or its element is display: none) the link is dropped rather than written as a dead annotation. When an id appears twice, the first one wins, as in a browser. As in a browser, href="#" and href="#top" jump to the top of the document when no element has that id, and a visibility: hidden element is still a valid target. An element that repeats on every page (a position: fixed header or footer, e.g. PageDescriptor.Header) has a single destination: its first occurrence, on page 1.

Pages, headers, footers

page.Size(PageSize.Letter.Landscape())
    .Margin(top: 60, right: 20, bottom: 60, left: 20)   // reserve room for the header/footer
    .Header(h => h.Text("Confidential").FontColor(Colors.Gray))
    .Footer(f => f.AlignRight().PageNumberOfTotal(prefix: "Page ", separator: " / "))
    .Watermark("DRAFT", fontSize: Length.Px(120), rotationDegrees: -35, opacity: 0.1f, color: Colors.Red)
  • Sizes: PageSize.A3/A4/A5/Letter/Legal, .Landscape(), or new PageSize(widthMm, heightMm).
  • Header / footer repeat on every physical page of the group (position: fixed). They don't push content down — leave room with the page margins.
  • Page numbers: CurrentPageNumber(), TotalPages(), PageNumberOfTotal(). CSS allows a single generated ::after per element, so use one of these per Container — a second call on the same container throws instead of silently replacing the first. Use separate containers (e.g. row items) for separate pieces.
  • Watermark is composed from position: fixed, transform and opacity — there is no dedicated watermark feature in the CSS engine either.
  • PinBottom() pins a box (e.g. a signature block) to the bottom of whichever page the preceding content ends on.

Multiple page groups (mixed sizes)

Content that overflows a page flows onto the next automatically. Call Page(...) more than once to change size or orientation partway through — the first group is the base @page rule and each later group gets its own named page (CSS Paged Media named pages):

Document.Create(doc => doc
    .Page(p => p.Size(PageSize.A4).Content(c => c.Item().Text("Report body")))
    .Page(p => p.Size(PageSize.A4.Landscape()).Content(c => c.Item().Text("Wide appendix table"))));

Document-level options

Document.Create(doc => doc
    .Title("Annual report").Author("Finance team").Language("en")
    .BasePath(@"C:\assets")                                  // resolves relative images/fonts/CSS
    .FontFace("Brand Sans", "fonts/brand.ttf", weight: 700)
    .Css(".total { font-weight: 700 } @media print { .noprint { display: none } }")
    .Conformance(PdfAConformance.PdfA2b)                     // PDF/A archival
    .Tagged()                                                // PDF/UA accessible
    .Page(...));
MethodEffect
Title, AuthorPDF document info.
Languagelang on the root; used by tagged output.
CssRaw stylesheet in <head>; target boxes with Class(...)/Id(...).
FontFace@font-face webfont (URL, file path or data: URI); see Fonts.
BasePathBase directory for relative resources.
EncryptRC4 permission/password protection (PdfEncryption).
Conformance, InvoicePDF/A levels; Factur-X e-invoice (needs PDF/A-3b/3u). See Compliance.
TaggedPDF/UA-1 (or UA-2) tagged output.

Escape hatches

When a feature has no typed method yet, four explicitly unchecked hatches guarantee you are never blocked. They are named Raw* on purpose, so unchecked strings are visible at every call site:

c.Item().RawStyle("column-count", "2");                     // any CSS declaration
c.Item().RawAttribute("data-section", "intro");              // any HTML attribute
c.Item().Raw("<dl><dt>Term</dt><dd>Definition</dd></dl>");   // any HTML markup, spliced into the tree
doc.Css("@page :first { @top-center { content: 'Cover' } }"); // any stylesheet
ℹ️
Raw values are not validated: a typo in a property name or value is silently ignored by the CSS engine. Prefer the typed methods, and treat a Raw* call as a sign a typed method is missing.

Validation and errors

  • Invalid typed values throw at the call site: Color.FromHex("red") and Length.Px(float.NaN) throw ArgumentException/ArgumentOutOfRangeException.
  • Out-of-range numbers (Opacity(1.5f), FontWeight(0), Grid(0, ...), Heading((HeadingLevel)9, ...)) throw ArgumentOutOfRangeException.
  • A second page-number/generated-content call on one container throws InvalidOperationException.
  • Rendering problems behave exactly as in the HTML API (missing images and fonts degrade gracefully; PDF/A rule violations throw).

How it works

Fluent calls accumulate typed style declarations per element. When Document.Create returns, they are serialized once into style/class attributes on an in-memory HtmlDocument, which is passed to HtmlToPdf.RenderDocument(...) — the same entry the HTML string API reaches after parsing. See Architecture. Because nothing is generated as text, content is never HTML-escaped or re-parsed, and a fluent document and the equivalent HTML render identically.

API reference

Every public type and member of EggPdf.Fluent, with its purpose. This section is generated from the code and its XML doc comments (dotnet run --project tools/EggPdf.DocGen), so it always matches the API; the same summaries appear as IntelliSense in your editor. A callback overload takes an Action and returns the parent (for chaining); the parameterless overload returns the child (to style it or fill it in with separate statements).

Types: Document, DocumentBuilder, DocumentDescriptor, PageDescriptor, ColumnDescriptor, Container, RowDescriptor, GridDescriptor, ListDescriptor, TableDescriptor, TableRowDescriptor, Color, Colors, Length, CssTransform, GridTrack, PageSize, and the keyword enums.

Document (static)

Entry point for defining PDF content in C# instead of HTML. It builds a DOM directly from the fluent calls and hands it to HtmlToPdf unchanged -- same cascade/layout/paint/ PDF-write pipeline as the HTML API, just without ever going through an HTML string. Two styles, same result: declarative (Create, one callback) or step by step (New).

MemberPurpose
static DocumentBuilder Create(Action<DocumentDescriptor> build)Builds a document from build's fluent calls, ready to render.
static DocumentDescriptor New()Starts an empty document to fill in step by step -- keep the returned descriptor, add pages, headers, footers and content in separate statements (or separate methods), then call Render:
var doc = Document.New().Title("Report"); var page = doc.AddPage().Size(PageSize.A4); page.Header().Text("Acme"); page.Footer().PageNumberOfTotal(); var body = page.Content(); body.Item().Text("Hello"); byte[] pdf = doc.Render();

DocumentBuilder

The finished document, ready to render. Returned by Create.

MemberPurpose
byte[] Render()Renders the document to PDF bytes. May be called repeatedly; the output is identical each time.
Task<byte[]> RenderAsync(CancellationToken ct = default)Renders the document to PDF bytes asynchronously.
Task RenderToFileAsync(string filePath, CancellationToken ct = default)Renders the document and writes the PDF to filePath.

DocumentDescriptor

Root of the fluent builder: a document is one or more page groups, plus document-wide PDF options. Build it either declaratively inside Create's callback, or step by step: var doc = Document.New(); var page = doc.AddPage(); page.Header().Text("..."); ... doc.Render(); Both produce the same document. Once built or rendered a document is frozen -- further changes throw.

MemberPurpose
PageDescriptor AddPage()Adds a page group and returns it to configure imperatively (size, margins, header, footer, content) at any later point before the document is built. The first group is the document's base (unnamed) page size; every group after that gets its own named @page rule and a matching page: <name> on its content root, so later groups can use a different size/orientation (e.g. a landscape appendix) -- the same CSS Paged Media named-page mechanism HTML documents use for mixed page sizes.
DocumentDescriptor Page(Action<PageDescriptor> build)Adds a page group configured inside build (see AddPage).
DocumentBuilder Build()Finishes the document: serializes every accumulated style and page rule, and freezes it. Called automatically by Render, RenderAsync and RenderToFileAsync; calling it again returns the same result. After this, changing the document throws.
byte[] Render()Builds the document (see Build) and renders it to PDF bytes.
Task<byte[]> RenderAsync(CancellationToken ct = default)Builds the document and renders it to PDF bytes asynchronously.
Task RenderToFileAsync(string filePath, CancellationToken ct = default)Builds the document and renders it to a PDF file.
DocumentDescriptor Title(string title)The PDF's title metadata (HTML <title>).
DocumentDescriptor Author(string author)The PDF's author metadata (HTML <meta name="author">).
DocumentDescriptor Language(string lang)The document language (lang on <html>), e.g. "en"; used by tagged (PDF/UA) output.
DocumentDescriptor Css(string css)Adds a raw stylesheet to the document's <head> -- the head-level counterpart to Style/Raw: selectors, @media print, @import, anything. Pair with Attribute to give elements classes/ids to target.
DocumentDescriptor FontFace(string family, string src, int weight = 400, bool italic = false)Declares an @font-face webfont; src is a URL, file path or data: URI.
DocumentDescriptor BasePath(string basePath)Base directory for resolving relative resource paths (images, stylesheets, fonts).
DocumentDescriptor Encrypt(PdfEncryption encryption)Encrypts the PDF (RC4 view-only protection / permission flags).
DocumentDescriptor Conformance(PdfAConformance conformance)Renders a PDF/A-conformant PDF (ICC output intent, XMP conformance metadata, forced font embedding).
DocumentDescriptor Invoice(FacturXInvoice invoice)Attaches a Factur-X/ZUGFeRD e-invoice XML. Conformance must be set to PdfA3b or PdfA3u first.
DocumentDescriptor Tagged(PdfUaVersion uaVersion = PdfUaVersion.Ua1)Renders a PDF/UA tagged (accessible) PDF: structure tree, headings, landmarks, alt text, tagged links.

PageDescriptor

Configures one page group's size, margins, running header/footer/watermark and content. Size/margin become an injected @page rule (named, for every group after the first -- see Page); content becomes the group's stacked (Column) body, the same way HTML's <body> is.

MemberPurpose
PageDescriptor Size(PageSize size)The physical page size and orientation.
PageDescriptor Margin(Length all)Same margin on all four sides.
PageDescriptor Margin(Length top, Length right, Length bottom, Length left)Per-side margins, in CSS shorthand order (top, right, bottom, left).
PageDescriptor Header(Action<Container> build)A running header repeated on every physical page of this group (CSS position: fixed pinned to the page's top edge). Reserve room for it with Margin.
Container Header()The running header (see Header) as a Container to fill in with separate statements.
PageDescriptor Footer(Action<Container> build)A running footer repeated on every physical page of this group, pinned to the page's bottom edge.
Container Footer()The running footer (see Footer) as a Container to fill in with separate statements.
PageDescriptor Watermark(string text, Length? fontSize = null, float rotationDegrees = -30f, float opacity = 0.12f, Color? color = null)A rotated, translucent text overlay ("DRAFT", "CONFIDENTIAL", ...) repeated centered on every physical page of this group. Composed from position:fixed/transform/opacity, the same primitives an HTML author would reach for -- there's no dedicated watermark keyword in the CSS engine either. color defaults to mid gray.
PageDescriptor Content(Action<ColumnDescriptor> build)Builds the group's content, stacked top to bottom like a <body>.
ColumnDescriptor Content()The group's content column, to add items to with separate statements. May be used more than once (items append in call order) -- e.g. one method per section of the report.

ColumnDescriptor

Builds the stacked (top-to-bottom) children of a Column.

MemberPurpose
Container Item()Appends a new block-level item to the column and returns it for styling/content.
ColumnDescriptor Item(Action<Container> build)Appends an item configured inside build and returns the column, so items chain: col.Item(i => ...).Item(i => ...).
ColumnDescriptor Heading(HeadingLevel level, string text, Action<Container> style)Appends a heading styled inside style and returns the column, so it chains with Item.
Container Heading(HeadingLevel level, string text)Appends a real <h1>-<h6> (not a styled div): headings are what the PDF/UA structure tree and auto-generated PDF bookmarks key off, so this is the only way to get a document's table of contents/outline from the fluent API.

Container

A single box in the document tree (a <div> under the hood). Every content-producing fluent call (Column, Row, page content, row/column items) hands back a Container, so text and styling always apply to "whatever was placed last". Styling takes typed values (Color, Length, keyword enums); the Raw* methods are the explicit, unchecked escape hatches.

MemberPurpose
Container Text(string text)Appends text to this container (each call adds another text node, so Text("a").Text("b") renders "ab").
Container Column(Action<ColumnDescriptor> build)Stacks children top to bottom (normal block flow -- CSS's default).
ColumnDescriptor Column()The children column of this container, to add items to with separate statements.
Container Row(Action<RowDescriptor> build)Lays out children left to right (display: flex).
RowDescriptor Row()Starts a row (flex container) appended here and returns it to fill in with separate statements.
Container Table(Action<TableDescriptor> build)Builds a <table> -- <thead> rows added via Header repeat on every continuation page for tables that span more than one page, the same as a hand-written <thead> does.
TableDescriptor Table()Starts a table appended here and returns it to fill in with separate statements (see Table).
Container BulletList(Action<ListDescriptor> build)Appends a bulleted list (<ul>).
ListDescriptor BulletList()Starts a bulleted list and returns it to add items to with separate statements.
Container NumberedList(Action<ListDescriptor> build)Appends a numbered list (<ol>).
ListDescriptor NumberedList()Starts a numbered list and returns it to add items to with separate statements.
Container Grid(GridTrack[] columns, Action<GridDescriptor> build)Lays out children in a CSS grid with the given column tracks.
GridDescriptor Grid(GridTrack[] columns)Starts a grid with the given column tracks and returns it to add cells to with separate statements.
Container Grid(int columnCount, Action<GridDescriptor> build)Lays out children in a CSS grid of columnCount equal columns.
GridDescriptor Grid(int columnCount)Starts a grid of columnCount equal columns and returns it to add cells to with separate statements.
Container Image(string src, float? widthPx = null, float? heightPx = null)Appends an <img>. Width/height (in px) are HTML attributes, matching plain <img width height> sizing.
Container Hyperlink(string url, string text)Appends a clickable <a href> link.
Container Id(string id)Sets this box's id, the target of internal links (Hyperlink("#id", ...)) and of Css selectors.
Container Class(string className)Adds a CSS class (repeatable; classes accumulate) for Css selectors to target.
Container Direction(TextDirection direction)Text direction of this box (dir).
Container PinBottom()Pins this box to the bottom of whichever physical page its surrounding dynamic content ends on (e.g. a signature block).
Container AvoidBreakInside()Keeps this box from being split across a page break (break-inside: avoid) -- e.g. a table row that must not straddle two pages.
Container CurrentPageNumber()Renders as the current physical page number, e.g. inside a Footer. Generated content (CSS counter()) can only be expressed via a real ::after rule, not an inline style="" attribute, so this registers one under a fresh class name.
Container TotalPages()Renders as the document's total physical page count.
Container PageNumberOfTotal(string prefix = "Page ", string separator = " of ", string suffix = "")Renders as e.g. "Page 3 of 12".
Container FontSize(Length size)Font size (a bare number is px).
Container FontFamily(string family)Font family name or comma-separated fallback list, e.g. "Inter, Arial" (free text -- a family, not a CSS keyword).
Container Bold()Bold text (font-weight: bold).
Container Italic()Italic (slanted) text.
Container FontWeight(int weight)Numeric weight, 1-1000 (400 = normal, 700 = bold).
Container FontColor(Color color)Text color.
Container LineHeight(float multiplier)Unitless line-height multiplier (1.4 = 140% of the font size).
Container LineHeight(Length height)Absolute line-height.
Container LetterSpacing(Length spacing)Extra space between characters.
Container Underline()Underlined text.
Container StrikeThrough()Struck-through text.
Container NoTextDecoration()Removes text decoration (e.g. the underline links get by default).
Container TextTransform(TextCase textCase)Upper/lower/capitalize case transformation of the rendered text.
Container WhiteSpace(WhiteSpaceMode mode)How white space and line breaks in the text are handled.
Container AlignLeft()Aligns text to the left edge.
Container AlignCenter()Centers text.
Container AlignRight()Aligns text to the right edge.
Container Padding(Length all)Inner spacing on all four sides.
Container Padding(Length vertical, Length horizontal)Inner spacing: vertical (top and bottom), then horizontal (left and right).
Container Padding(Length top, Length right, Length bottom, Length left)Inner spacing per side, in CSS order: top, right, bottom, left.
Container Margin(Length all)Outer spacing on all four sides.
Container Margin(Length vertical, Length horizontal)Outer spacing: vertical (top and bottom), then horizontal (left and right).
Container Margin(Length top, Length right, Length bottom, Length left)Outer spacing per side, in CSS order: top, right, bottom, left.
Container Width(Length width)Box width.
Container Height(Length height)Box height.
Container MinWidth(Length width)Minimum box width.
Container MaxWidth(Length width)Maximum box width.
Container MinHeight(Length height)Minimum box height.
Container MaxHeight(Length height)Maximum box height.
Container Background(Color color)Background fill color.
Container Border(Length width, Color color, BorderLineStyle style = BorderLineStyle.Solid)Border on all four sides.
Container BorderTop(Length width, Color color, BorderLineStyle style = BorderLineStyle.Solid)Top border only.
Container BorderRight(Length width, Color color, BorderLineStyle style = BorderLineStyle.Solid)Right border only.
Container BorderBottom(Length width, Color color, BorderLineStyle style = BorderLineStyle.Solid)Bottom border only.
Container BorderLeft(Length width, Color color, BorderLineStyle style = BorderLineStyle.Solid)Left border only.
Container BorderRadius(Length radius)Rounded corners.
Container BoxShadow(Length offsetX, Length offsetY, Length blur, Color color)Drop shadow: horizontal offset, vertical offset, blur radius, color.
Container Opacity(float value)0 (transparent) to 1 (opaque).
Container Overflow(OverflowMode mode)What happens to content that doesn't fit the box (Hidden clips it).
Container Position(PositionMode mode)Positioning scheme (position).
Container Display(DisplayMode mode)Display type (display).
Container Float(FloatSide side)Floats the box left or right so following inline content wraps around it.
Container Transform(CssTransform transform)Applies a 2D transform (rotate, scale, translate, skew), e.g. CssTransform.Rotate(10).
Container RawStyle(string property, string value)Unchecked escape hatch: sets any CSS declaration by name and value. Nothing validates either string, so a typo is silently ignored by the CSS engine -- prefer the typed methods above, and use this only for a property that has none yet.
Container RawAttribute(string name, string value)Unchecked escape hatch: sets any HTML attribute by name. class is added to the classes the builder manages (so it combines with Class and page-number classes instead of being overwritten); a style attribute is rejected -- use RawStyle, which merges with the typed styles. For any other name the first value set wins.
Container Raw(string html)Unchecked escape hatch: parses html as an HTML fragment and appends its nodes as children -- anything expressible in HTML is expressible here, even before a typed wrapper exists for it.

RowDescriptor

Builds the side-by-side (flex) children of a Row.

MemberPurpose
RowDescriptor Gap(Length gap)Space between items along the row (gap). It applies to the row itself, so it can be set before or after adding items.
RowDescriptor JustifyContent(FlexJustify justify)How items distribute along the row (justify-content).
RowDescriptor AlignItems(FlexAlign align)How items align across the row's height (align-items).
RowDescriptor Wrap()Lets items wrap onto additional lines instead of shrinking to fit one row (flex-wrap: wrap).
Container RelativeItem(float weight = 1f)Appends an item that shares the row's remaining space by weight (flex-grow).
RowDescriptor RelativeItem(Action<Container> build)Appends a flexible item configured inside build and returns the row, so items chain.
RowDescriptor RelativeItem(float weight, Action<Container> build)Appends a flexible item of the given weight configured inside build and returns the row.
RowDescriptor ConstantItem(Length width, Action<Container> build)Appends a fixed-width item configured inside build and returns the row, so items chain.
Container ConstantItem(Length width)Appends an item with a fixed width that does not grow or shrink.

GridDescriptor

Builds the cells of a CSS grid container (Grid).

MemberPurpose
GridDescriptor Gap(Length gap)Space between rows and columns (gap).
GridDescriptor AutoRows(Length height)Height of implicitly created rows (grid-auto-rows).
GridDescriptor Item(Action<Container> build)Appends a single-column cell configured inside build and returns the grid, so cells chain.
GridDescriptor Item(int columnSpan, Action<Container> build)Appends a cell spanning columnSpan columns configured inside build and returns the grid.
Container Item(int columnSpan = 1)Appends a cell spanning columnSpan columns and returns it for content/styling.

ListDescriptor

Builds the <li> items of a bullet (<ul>) or numbered (<ol>) list.

MemberPurpose
ListDescriptor Item(Action<Container> build)Appends a list item configured inside build and returns the list, so items chain.
Container Item()Appends a list item and returns it for content/styling (it may itself hold nested lists, tables, etc.).

TableDescriptor

Builds a table's <thead> and <tbody> rows.

MemberPurpose
Container Header(Action<TableRowDescriptor> build)Adds a header row inside <thead>, which repeats on every continuation page for tables spanning more than one page. Returns the row for styling (e.g. a header background).
TableDescriptor Header(Action<TableRowDescriptor> cells, Action<Container> rowStyle)Adds a header row whose cells are built by cells and whose row box is styled by rowStyle; returns the table, so rows chain.
TableDescriptor Row(Action<TableRowDescriptor> cells, Action<Container> rowStyle)Adds a body row whose cells are built by cells and whose row box is styled by rowStyle; returns the table, so rows chain.
Container Row(Action<TableRowDescriptor> build)Adds a body row inside <tbody>. Returns the row for styling (e.g. striping, AvoidBreakInside).

TableRowDescriptor

Builds one table row's cells.

MemberPurpose
TableRowDescriptor Cell(Action<Container> build)Appends a cell configured inside build and returns the row, so cells chain.
Container Cell()Appends a cell (<th> in a header row, <td> otherwise) and returns it for content/styling.

Color (struct)

A validated color. There is deliberately no implicit conversion from string: a typo like "rde" must fail at the call site (FromHex throws) rather than be silently ignored by the CSS engine. default(Color) is fully transparent.

MemberPurpose
static Color FromRgb(byte r, byte g, byte b)An opaque color from red, green and blue components (0-255).
static Color FromRgba(byte r, byte g, byte b, byte a)RGB plus alpha (0 = transparent, 255 = opaque).
static Color FromHex(string hex)Parses "#rgb", "#rgba", "#rrggbb" or "#rrggbbaa"; anything else throws.

Colors (static)

Common named colors, as Color values.

Named colors: Transparent, Black, White, Red, Green, Blue, Yellow, Orange, Purple, Pink, Brown, Navy, Teal, Gray, LightGray, DarkGray.

Length (struct)

A CSS length with its unit. A bare number converts implicitly to pixels, so Width(200) still works; use Mm, Percent etc. for anything else. default(Length) is 0px.

MemberPurpose
static Length Px(float value)A length in CSS pixels.
static Length Pt(float value)A length in points (1/72 inch).
static Length Mm(float value)A length in millimeters.
static Length Cm(float value)A length in centimeters.
static Length In(float value)A length in inches.
static Length Em(float value)A length relative to the element's font size (1 em = one font size).
static Length Percent(float value)A length as a percentage of the containing box.
implicit operator Length(float px)A bare number converts to pixels, so Width(200) means 200 px.
static Length Zero { get; }A zero length (0 px).
static Length Auto { get; }The CSS keyword auto (the browser/engine picks the size).

CssTransform (struct)

A 2D transform, composable with Then: CssTransform.Rotate(10).Then(CssTransform.Scale(1.2f)).

MemberPurpose
static CssTransform Rotate(float degrees)Rotates clockwise by degrees around the box's center.
static CssTransform Scale(float factor)Scales uniformly by factor (1 = unchanged, 2 = double size).
static CssTransform Scale(float x, float y)Scales by separate horizontal and vertical factors.
static CssTransform Translate(Length x, Length y)Moves the box by a horizontal and a vertical offset.
static CssTransform SkewX(float degrees)Skews (slants) horizontally by degrees.
static CssTransform SkewY(float degrees)Skews (slants) vertically by degrees.
CssTransform Then(CssTransform next)Applies next after this transform.

GridTrack (struct)

One column of a Grid.

MemberPurpose
static GridTrack Fr(float share)A flexible share of the remaining space (Nfr).
static GridTrack Fixed(Length size)A fixed-size column.
static GridTrack Auto { get; }Sized to its content.

PageSize (struct)

A page's physical dimensions in millimeters, matching CSS @page { size: ... }.

MemberPurpose
static readonly PageSize A3A3 portrait (297 x 420 mm).
static readonly PageSize A4A4 portrait (210 x 297 mm) -- the default.
static readonly PageSize A5A5 portrait (148 x 210 mm).
static readonly PageSize LetterUS Letter portrait (8.5 x 11 in).
static readonly PageSize LegalUS Legal portrait (8.5 x 14 in).
PageSize(float widthMm, float heightMm)A custom page size in millimeters.
PageSize Landscape()Same physical page, rotated: width and height swapped.
float WidthMm { get; }Page width in millimeters.
float HeightMm { get; }Page height in millimeters.

Keyword enums

EnumPurposeValues
BorderLineStyleBorder line style.None, Solid, Dashed, Dotted, Double, Groove, Ridge, Inset, Outset
DisplayModedisplay.None, Block, Inline, InlineBlock, Flex, Grid
FlexAlignFlex align-items: alignment across the row's height.Stretch, Start, Center, End, Baseline
FlexJustifyFlex justify-content: distribution along the row.Start, Center, End, SpaceBetween, SpaceAround, SpaceEvenly
FloatSidefloat.None, Left, Right
HeadingLevelHeading level; the value is the N of <hN>.H1, H2, H3, H4, H5, H6
OverflowModeoverflow: what happens to content that doesn't fit the box.Visible, Hidden, Clip, Scroll, Auto
PositionModeposition.Static, Relative, Absolute, Fixed, Sticky
TextCasetext-transform.None, Uppercase, Lowercase, Capitalize
TextDirectionText direction (dir).Ltr, Rtl
WhiteSpaceModewhite-space.Normal, NoWrap, Pre, PreWrap, PreLine