Elements
Text
The most fundamental element. Add text with optional styling:
c.Text("Hello, World!")
c.Text("Styled text", template.FontSize(18), template.Bold())
c.Text("Red centered", template.TextColor(pdf.Red), template.AlignCenter())
Text Options
| Option | Description |
|---|---|
FontSize(size) | Font size in points (default: 12) |
Bold() | Bold weight |
Italic() | Italic style |
FontFamily(name) | Use a registered font |
TextColor(color) | Foreground color |
BgColor(color) | Background color |
AlignLeft() | Left alignment (default) |
AlignCenter() | Center alignment |
AlignRight() | Right alignment |
Underline() | Underline decoration |
Strikethrough() | Strikethrough decoration |
LetterSpacing(pts) | Extra space between characters |
TextIndent(value) | First-line indent |
Rich Text
Mixed-style inline text using RichText():
c.RichText(func(rt *template.RichTextBuilder) {
rt.Span("Normal text ")
rt.Span("bold", template.Bold())
rt.Span(" and ")
rt.Span("red", template.TextColor(pdf.Red))
rt.Span(" in one line.")
})
┌─────────────────────────────────────────────┐
│ Normal text bold and red in one line. │
│ ^^^^ ^^^ │
│ bold red color │
└─────────────────────────────────────────────┘
Table
Tables with headers and data rows:
// Basic table
c.Table(
[]string{"Name", "Age", "City"},
[][]string{
{"Alice", "30", "Tokyo"},
{"Bob", "25", "New York"},
{"Charlie", "35", "London"},
},
)
┌──────────┬──────┬──────────┐
│ Name │ Age │ City │ ← header (bold)
├──────────┼──────┼──────────┤
│ Alice │ 30 │ Tokyo │
│ Bob │ 25 │ New York│
│ Charlie │ 35 │ London │
└──────────┴──────┴──────────┘
Styled Table
darkBlue := pdf.RGBHex(0x1A237E)
lightGray := pdf.RGBHex(0xF5F5F5)
c.Table(
[]string{"Product", "Category", "Qty", "Unit Price", "Total"},
[][]string{
{"Laptop Pro 15", "Electronics", "2", "$1,299.00", "$2,598.00"},
{"Wireless Mouse", "Accessories", "10", "$29.99", "$299.90"},
{"USB-C Hub", "Accessories", "5", "$49.99", "$249.95"},
{"Monitor 27\"", "Electronics", "3", "$399.00", "$1,197.00"},
{"Keyboard", "Accessories", "10", "$79.99", "$799.90"},
{"Webcam HD", "Electronics", "4", "$89.99", "$359.96"},
},
template.ColumnWidths(30, 20, 10, 20, 20),
template.TableHeaderStyle(
template.TextColor(pdf.White),
template.BgColor(darkBlue),
),
template.TableStripe(lightGray),
)
┌─────────────┬────────────┬─────┬───────────┬──────────┐
│ Product │ Category │ Qty │Unit Price │ Total │ ← white on dark blue
├─────────────┼────────────┼─────┼───────────┼──────────┤
│ Laptop Pro │ Electronics│ 2 │ $1,299.00 │$2,598.00 │ ← white bg
│ Wireless.. │ Accessories│ 10 │ $29.99 │ $299.90 │ ← gray stripe
│ USB-C Hub │ Accessories│ 5 │ $49.99 │ $249.95 │ ← white bg
│ Monitor 27"│ Electronics│ 3 │ $399.00 │$1,197.00 │ ← gray stripe
│ Keyboard │ Accessories│ 10 │ $79.99 │ $799.90 │ ← white bg
│ Webcam HD │ Electronics│ 4 │ $89.99 │ $359.96 │ ← gray stripe
└─────────────┴────────────┴─────┴───────────┴──────────┘
Table Options
| Option | Description |
|---|---|
ColumnWidths(widths...) | Column width percentages (must sum to 100) |
ColumnAlign(aligns...) | Since v1.0.10 Per-column horizontal alignment: AlignLeft, AlignCenter, AlignRight (applies to header + body) |
TableHeaderStyle(opts...) | Style for header row |
TableStripe(color) | Alternating row background color |
TableCellVAlign(align) | Vertical alignment: VAlignTop, VAlignMiddle, VAlignBottom |
WithTableBorder(spec) | Outer border around the table |
WithTableCellBorder(spec) | Same border drawn around every header + body cell (Excel-style grid) |
WithTableBorderCollapse(b) | Collapse adjacent cell borders |
WithTableBackground(color) | Fill the table's outer box |
Borders & Backgrounds
Since v1.0.7Add an outer frame, per-cell grid lines, or a backdrop fill. Build a BorderSpec with template.Border(...) and apply it via WithTableBorder (outer) or WithTableCellBorder (every header + body cell):
outer := template.Border(
template.BorderWidth(document.Pt(1)),
template.BorderColor(pdf.RGBHex(0x1A237E)),
)
grid := template.Border(
template.BorderWidth(document.Pt(0.5)),
template.BorderColor(pdf.Gray(0.5)),
)
// Outer frame only
c.Table(header, rows, template.WithTableBorder(outer))
// Excel-style grid lines on every cell
c.Table(header, rows, template.WithTableCellBorder(grid))
// Outer frame + grid + background fill
c.Table(header, rows,
template.WithTableBorder(outer),
template.WithTableCellBorder(grid),
template.WithTableBackground(pdf.RGBHex(0xFAFAFA)),
)
// Dashed cell grid
dashed := template.Border(
template.BorderWidth(document.Pt(0.75)),
template.BorderColor(pdf.RGBHex(0x0D47A1)),
template.BorderLine(document.BorderDashed),
)
c.Table(header, rows, template.WithTableCellBorder(dashed))
See Borders for the full BorderSpec builder reference.
Table Vertical Alignment
c.Table(
[]string{"Align", "Short", "Long Content"},
[][]string{
{"Top", "A", "This is a longer text that wraps to multiple lines"},
{"Middle", "B", "Another longer text for demonstration purposes"},
},
template.TableCellVAlign(document.VAlignMiddle),
)
Table Column Alignment
Since v1.0.10Set horizontal alignment per column — typical use case is right-aligning numeric or currency columns. Each argument applies to the column at the same index, in both the header and body rows. Columns without a provided alignment fall back to the default left alignment.
c.Table(
[]string{"Item", "Qty", "Price"},
[][]string{
{"Apple", "3", "$1.50"},
{"Banana", "12", "$0.30"},
{"Cherry", "120", "$5.00"},
},
template.ColumnAlign(
document.AlignLeft, // Item
document.AlignRight, // Qty
document.AlignRight, // Price
),
)
Image
Add JPEG or PNG images:
imgData, _ := os.ReadFile("photo.jpg")
c.Image(imgData)
c.Image(imgData, template.FitWidth(document.Mm(80)))
c.Image(imgData, template.FitHeight(document.Mm(50)))
Image Options
| Option | Description |
|---|---|
FitWidth(value) | Scale to specified width |
FitHeight(value) | Scale to specified height |
WithFitMode(mode) | Fit mode: FitContain, FitCover, FitStretch, FitOriginal |
WithAlign(align) | Horizontal alignment: AlignLeft, AlignCenter, AlignRight |
MinDisplayWidth(v) | Overflow to next page if shrunk below this width |
MinDisplayHeight(v) | Overflow to next page if shrunk below this height |
WithImageBorder(spec) | Border around the image |
WithImageBackground(color) | Fill the image's box (useful for transparent PNGs) |
Image Fit Modes
// Contain: scale to fit, preserve aspect ratio (default)
c.Image(data, template.WithFitMode(document.FitContain))
// Cover: scale to fill, may crop
c.Image(data, template.WithFitMode(document.FitCover))
// Stretch: fill bounds, may distort
c.Image(data, template.WithFitMode(document.FitStretch))
// Original: use original dimensions
c.Image(data, template.WithFitMode(document.FitOriginal))
Image Alignment
c.Image(data, template.FitWidth(document.Mm(40)), template.WithAlign(document.AlignCenter))
c.Image(data, template.FitWidth(document.Mm(40)), template.WithAlign(document.AlignRight))
Border & Background
Since v1.0.7Frame an image and fill its box (handy for transparent PNGs):
c.Image(pngData,
template.FitWidth(document.Mm(60)),
template.WithImageBorder(template.Border(
template.BorderWidth(document.Pt(2)),
template.BorderColor(pdf.RGBHex(0xE53935)),
)),
template.WithImageBackground(pdf.RGBHex(0xFFF8E1)),
)
See Borders for the full BorderSpec builder reference.
Box
Since v1.0.7Wrap arbitrary column content in a styled rectangular container with a border, fill, and padding. Useful for callouts, notice boxes, or grouping related elements:
c.Box(func(c *template.ColBuilder) {
c.Text("Inside a box", template.Bold())
c.Text("with two lines of body copy.")
},
template.WithBoxBorder(template.Border(
template.BorderWidth(document.Pt(1)),
template.BorderColor(pdf.RGBHex(0x1A237E)),
)),
template.WithBoxBackground(pdf.RGBHex(0xE8EAF6)),
template.WithBoxPadding(document.UniformEdges(document.Mm(4))),
)
Box Options
| Option | Description |
|---|---|
WithBoxBorder(spec) | Border around the box |
WithBoxBackground(color) | Fill color |
WithBoxPadding(edges) | Inner spacing |
WithBoxMargin(edges) | Outer spacing |
WithBoxWidth(value) | Explicit width |
WithBoxHeight(value) | Explicit height |
Borders
Since v1.0.7template.Border(...) builds a reusable BorderSpec that can be applied to tables (WithTableBorder / WithTableCellBorder), images (WithImageBorder), boxes (WithBoxBorder), and text (WithTextBorder):
spec := template.Border(
template.BorderWidth(document.Pt(1)), // uniform edges
template.BorderColor(pdf.RGBHex(0x1A237E)),
template.BorderLine(document.BorderSolid), // BorderSolid | BorderDashed | BorderDotted
)
The default is 1pt black solid when no width is specified.
Border Helpers
| Option | Description |
|---|---|
Border(opts...) | Build a BorderSpec |
BorderWidth(v) | Uniform width on all four edges |
BorderWidths(t, r, b, l) | Per-edge widths in CSS order: top, right, bottom, left |
BorderColor(c) | Edge color |
BorderLine(style) | Line style: BorderSolid, BorderDashed, BorderDotted, BorderNone |
List
Unordered List
c.List([]string{
"Declarative document definition",
"All element types supported",
"Style options (bold, italic, color, align)",
"Header and footer support",
})
┌─────────────────────────────────────────────┐
│ • Declarative document definition │
│ • All element types supported │
│ • Style options (bold, italic, color, ...) │
│ • Header and footer support │
└─────────────────────────────────────────────┘
Ordered List
c.OrderedList([]string{
"Text with styles",
"Tables with headers",
"Lists (ordered/unordered)",
"Lines and spacers",
"QR codes and barcodes",
})
┌─────────────────────────────────────────────┐
│ 1. Text with styles │
│ 2. Tables with headers │
│ 3. Lists (ordered/unordered) │
│ 4. Lines and spacers │
│ 5. QR codes and barcodes │
└─────────────────────────────────────────────┘
List Options
| Option | Description |
|---|---|
ListIndent(value) | Indentation from left |
Line
Horizontal rules with optional color and thickness:
// Default line (gray, 1pt)
c.Line()
// Colored line
c.Line(template.LineColor(pdf.Red))
c.Line(template.LineColor(pdf.Blue))
// Custom thickness
c.Line(template.LineThickness(document.Pt(0.5))) // thin
c.Line(template.LineThickness(document.Pt(2))) // medium
c.Line(template.LineThickness(document.Pt(5))) // thick
// Color + thickness
c.Line(
template.LineColor(pdf.RGBHex(0x1A237E)),
template.LineThickness(document.Pt(2)),
)
┌─────────────────────────────────────────────┐
│ Default line: │
│ ─────────────────────────────── (gray 1pt) │
│ Red line: │
│ ─────────────────────────────── (red) │
│ Thin (0.5pt): │
│ ─────────────────────────────── (thin) │
│ Thick (5pt): │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (thick) │
└─────────────────────────────────────────────┘
Line Options
| Option | Description |
|---|---|
LineColor(color) | Line color |
LineThickness(value) | Line thickness |
Spacer
Add vertical space between elements:
c.Text("Before spacer")
c.Spacer(document.Mm(10)) // 10mm gap
c.Text("After spacer")
c.Spacer(document.Mm(5)) // 5mm
c.Spacer(document.Mm(15)) // 15mm
c.Spacer(document.Mm(30)) // 30mm
┌─────────────────────────────────────────────┐
│ Before spacer │
│ │
│ ↕ 10mm │
│ │
│ After spacer │
└─────────────────────────────────────────────┘
QR Code
Generate QR codes from text or URLs:
// Basic QR code
c.QRCode("https://gpdf.dev")
// With custom size
c.QRCode("https://gpdf.dev", template.QRSize(document.Mm(30)))
// With error correction level
c.QRCode("HELLO", template.QRSize(document.Mm(25)),
template.QRErrorCorrection(qrcode.LevelH))
// Japanese content
c.QRCode("こんにちは世界", template.QRSize(document.Mm(30)))
QR Codes with Different Sizes
page.AutoRow(func(r *template.RowBuilder) {
r.Col(4, func(c *template.ColBuilder) {
c.Text("20mm", template.FontSize(9))
c.QRCode("https://gpdf.dev", template.QRSize(document.Mm(20)))
})
r.Col(4, func(c *template.ColBuilder) {
c.Text("30mm", template.FontSize(9))
c.QRCode("https://gpdf.dev", template.QRSize(document.Mm(30)))
})
r.Col(4, func(c *template.ColBuilder) {
c.Text("40mm", template.FontSize(9))
c.QRCode("https://gpdf.dev", template.QRSize(document.Mm(40)))
})
})
┌───────────────┬───────────────┬───────────────┐
│ 20mm │ 30mm │ 40mm │
│ ┌──┐ │ ┌────┐ │ ┌──────┐ │
│ │QR│ │ │ QR │ │ │ QR │ │
│ └──┘ │ └────┘ │ │ │ │
│ │ │ └──────┘ │
└───────────────┴───────────────┴───────────────┘
Error Correction Levels
| Level | Recovery | Best For |
|---|---|---|
qrcode.LevelL | ~7% | Clean environments |
qrcode.LevelM | ~15% | General use (default) |
qrcode.LevelQ | ~25% | Industrial use |
qrcode.LevelH | ~30% | Harsh environments |
import "github.com/gpdf-dev/gpdf/qrcode"
c.QRCode("HELLO", template.QRErrorCorrection(qrcode.LevelH))
QR Code Options
| Option | Description |
|---|---|
QRSize(value) | Display size (width = height) |
QRMinSize(value) | Minimum display size — overflow to next page instead of shrinking below |
QRErrorCorrection(level) | Error correction level |
QRScale(s) | Pixels per QR module |
Minimum Size
Since v1.0.6QRMinSize prevents the layout from shrinking a QR code below a configured minimum. When the remaining space on the current page would force the QR below that size, it overflows to the next page instead of rendering at an unscannable size.
c.QRCode("https://gpdf.dev",
template.QRSize(document.Mm(30)),
template.QRMinSize(document.Mm(20)))
Barcode
Generate Code 128 barcodes:
// Basic barcode
c.Barcode("INV-2026-0001")
// With custom width
c.Barcode("PRODUCT-A-12345", template.BarcodeWidth(document.Mm(80)))
// With custom height
c.Barcode("SMALL-BAR", template.BarcodeHeight(document.Mm(10)))
// Numeric data (automatically optimized with Code C)
c.Barcode("1234567890")
Barcodes in Columns
page.AutoRow(func(r *template.RowBuilder) {
r.Col(6, func(c *template.ColBuilder) {
c.Text("Item A", template.FontSize(9))
c.Barcode("ITEM-A-001", template.BarcodeWidth(document.Mm(60)))
})
r.Col(6, func(c *template.ColBuilder) {
c.Text("Item B", template.FontSize(9))
c.Barcode("ITEM-B-002", template.BarcodeWidth(document.Mm(60)))
})
})
┌────────────────────────┬────────────────────────┐
│ Item A │ Item B │
│ ║║│║║│║║║│║║│║║│ │ ║║│║║│║║║│║║│║║│ │
│ ITEM-A-001 │ ITEM-B-002 │
└────────────────────────┴────────────────────────┘
Barcode Options
| Option | Description |
|---|---|
BarcodeWidth(value) | Display width |
BarcodeHeight(value) | Display height |
BarcodeFormat(format) | Barcode format (default: Code 128) |
Absolute Positioning
Place elements at exact XY coordinates on the page, outside the normal grid flow. Useful for watermarks, stamps, logos, and overlays.
page.Absolute(document.Mm(120), document.Mm(20), func(c *template.ColBuilder) {
c.Text("CONFIDENTIAL", template.FontSize(20), template.Bold(), template.TextColor(pdf.Red))
})
// With explicit size
page.Absolute(document.Mm(10), document.Mm(250), func(c *template.ColBuilder) {
c.QRCode("https://gpdf.dev", template.QRSize(document.Mm(20)))
}, gpdf.AbsoluteWidth(document.Mm(25)), gpdf.AbsoluteHeight(document.Mm(25)))
// Use page corner as origin (ignores margins)
page.Absolute(document.Mm(0), document.Mm(0), func(c *template.ColBuilder) {
c.Text("Top-left corner of page")
}, gpdf.AbsoluteOriginPage())
┌─ Page ──────────────────────────────────────────┐
│ ┌─ Content Area ───────────────────────────┐ │
│ │ │ │
│ │ [Normal flow content] │ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ CONFIDENTIAL │ ← absolute │ │
│ │ └──────────────┘ (120,20) │ │
│ │ │ │
│ │ ┌──┐ │ │
│ │ │QR│ ← absolute (10,250) │ │
│ │ └──┘ │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
Coordinate Origins
| Origin | Description | Default |
|---|---|---|
| Content Area | XY relative to top-left of content area (inside margins) | Yes |
| Page | XY relative to top-left corner of the page (ignores margins) | No |
Absolute Positioning Options
| Option | Description |
|---|---|
AbsoluteWidth(value) | Explicit width for the absolute block |
AbsoluteHeight(value) | Explicit height for the absolute block |
AbsoluteOriginPage() | Use page corner as origin instead of content area |
Page Number / Total Pages
Automatic page numbering in headers or footers:
// Current page number (e.g., "1", "2", "3")
c.PageNumber(template.AlignRight(), template.FontSize(8))
// Total page count (e.g., "4 total pages")
c.TotalPages(template.AlignRight(), template.FontSize(9))
Both accept standard text options for styling.