Feature Showcase
Every document below is rendered by PeachPDF itself when this site is built, so the
output always reflects the current release. Where a card has a View SVG link, the same document was also rendered through the
SVG backend as one continuous sheet - no paper pages, no forced page breaks - as vector content. Each card pairs the exact input — the HTML given to
PdfGenerator.GeneratePdf, or for the declarative-API showcases the C# given to
PdfGenerator.CreateDocument — with the PDF that came out. Open both and compare.
The previews show the first page of each PDF, rendered on Linux with Liberation fonts
(the same font substitution any Linux server without Microsoft fonts would use).
Want to render your own? Try PeachPDF in your browser — drop in an HTML
file, an MHTML archive, or a ZIP of a site folder and get a PDF back. It runs entirely on your
machine, in the page, with no server involved. Prefer the command line or plain C#? See the
peachpdf CLI and the
declarative API, which build PDFs without an HTML string.
Backgrounds & Borders
CSS Gradients
linear-gradient, radial-gradient, and conic-gradient: directions, angles, multi-stop and hard-stop color lists, gradient layers over a background color, and CSS Color Level 4 interpolation spaces.
Border Radius
border-radius from simple uniform rounding to per-corner and elliptical radii, on filled and bordered boxes, plus overflow:hidden clipping descendant content to the curve and background-clip's inset curves reduced by border width.
Border Radius (96 DPI)
The same border-radius coverage as the Border Radius showcase, rendered at PixelsPerInch=96 instead of the library's default 72 — confirms rounded borders, backgrounds, and overflow-clip curves render identically regardless of PixelsPerInch.
Border Pixel Snapping: Exact (default)
A 1px border at a fractional position drawn on its exact geometry, the default: at 100% zoom it straddles two device columns, each about half covered, so it reads wider and paler than in a browser. Compare with the snapped showcase.
Border Pixel Snapping: SnapBoxDecorationsToCssPixels
The same document with SnapBoxDecorationsToCssPixels on: each border edge is rounded to a whole CSS pixel like a browser does, so a 1px border covers exactly one device column at 100% zoom. Backgrounds, outlines and shadows move to the same snapped edges, so they still meet the border.
Border Width Snapping: As Written (default)
Border widths used exactly as written: 0.5px is drawn 0.5px wide and 1.5px 1.5px wide.
Border Width Snapping: SnapBorderWidthsToCssPixels
The same document with SnapBorderWidthsToCssPixels on: 0.5px becomes a visible 1px line, 1.5px becomes 1px and 2.9px becomes 2px, as in a browser. Box sizes follow the snapped widths.
Box Shadow
box-shadow: drop shadows, Gaussian blur, spread, inset (following the padding edge's rounded corners), colored and multiple layered shadows, with border-radius and calc() lengths.
Border Image
border-image: the standard 9-slice algorithm (corners scaled, edges stretched/tiled per border-image-repeat — stretch, repeat, round or space — with an optional filled center) from a raster texture or any CSS <image> including gradients, plus border-image-outset extending the painted frame past the border box.
Box Decoration Break
box-decoration-break: slice vs clone at both line-box and page breaks — continuous sliced decorations against independently wrapped per-fragment ones, for backgrounds, gradients, border-radius, borders and box-shadow.
Background Origin & Clip
background-origin and background-clip controlling where a background paints relative to the border, padding, and content boxes.
background-clip: text (Gradient Text)
Clips a background gradient to the shape of the text itself, with the glyphs still selectable and extractable in the PDF.
Background Position & Size
background-position and background-size combinations: keywords, lengths, percentages, cover, and contain.
Border Styles
The full set of CSS border styles, from solid and dashed to groove, ridge, inset, and outset.
Outline
outline / outline-color / outline-style / outline-width / outline-offset: a layout-neutral ring drawn outside the border edge, including a true per-pixel color inversion for outline-color: invert.
Canvas Background
CSS1 canvas background propagation: body and html backgrounds covering the full page.
clip-path basic shapes
CSS clip-path with basic shapes: polygon(), inset() (including a round <border-radius>), circle(), ellipse(), path(), and url(#id) clip an element (here a gradient fill) to a shape resolved against its border-box by default, or another box a <geometry-box> keyword (e.g. padding-box) selects. A shared basic-shape grammar validates the value at parse time (path() by parsing its SVG path-data string with the same parser <path d="..."> uses; url() by referencing a <clipPath> defined in a hidden, defs-only <svg> elsewhere in the document) and the resolved region is pushed as a PDF clip path.
Lists & Generated Content
::marker Styling
Styling list markers with the ::marker pseudo-element, including real per-item numbering via the list-item counter.
List Style Type Coverage
The full CSS Counter Styles Level 3 predefined-style coverage list-style-type now supports - numeric, fixed, symbolic, and additive systems, plus a literal <string> marker.
symbols() and @counter-style
Inline symbols() counter styles and author-defined @counter-style rules (cyclic, alphabetic, additive, numeric with pad, extends) driving list markers.
Paged Media
Paged Media
@page rules with margin boxes, running headers and footers, and page counters, including a url() logo image in a margin box (@top-left-corner).
Panels At The Page Foot
A panel whose top border or padding crosses the page foot moves whole to the next page, and its first child's text starts inside the child's own box instead of above it.
Margin-box Image Alignment
An image in a @page margin box follows the box's alignment like text does: default from the box position (@top-left/@top-center/@top-right) plus an explicit text-align override.
Running Elements
Running headers with full formatting fidelity via position: running() and content: element() - unlike string-set/string(), the margin box shows a real, laid-out element (colors, badges, nested spans), not just captured text.
Footnotes
css-gcpm-3's float: footnote: a numbered in-flow reference, a note area whose height is reserved dynamically per page based on how many footnotes land there, break-inside: avoid content correctly kept clear of the reserved strip, an @footnote rule styling the note area's own divider and giving it a fixed height, a real cascaded footnote counter (continuous numbering via @page counter-reset), column-scoped areas via float-reference: column, footnote-display: compact packing short notes onto one row, and footnote-policy: block/line forcing a page break when a note doesn't fit.
Page floats
css-page-floats' float: top/bottom/top-bottom/snap/inside/outside: a float: top figure landing flush at the true top of its landing page with flow content starting below the reserved strip, a float: bottom callout landing flush at the true bottom with flow content stopping above it, float: top-bottom falling back to the bottom edge once the top edge has no room left, inside/outside resolving to opposite physical sides depending on whether the landing page is a right-hand (recto) or left-hand (verso) page, and float-reference: column pinning a float to the edge of the column its anchor sits in so only that column gives up room.
Scroll Containers Across Pages
An auto-height overflow: auto code listing and an overflow: hidden panel breaking cleanly between their lines across page boundaries, and a fixed-height overflow: auto box moving whole to the next page instead.
Capped Scroll Containers Across Pages
An auto-height overflow: auto or hidden box with a max-height breaking between its lines across a page boundary, ending where its lines reach the cap, with the content after it kept.
Cards At The Page Foot
An auto-height overflow: hidden or auto card whose title has a top margin, starting just above the page foot, is drawn whole on the following pages instead of vanishing.
Absolute Boxes Across Pages
An absolutely positioned sidebar taller than a page breaking between its lines across pages while the paragraphs after it flow on undisturbed, and a DRAFT stamp declared at the end of the document drawn at the top of the first page.
Table of Contents & Cross-References (target-counter / target-text / leader)
A hand-authored table of contents with real, non-stale page numbers - leader(dotted) fills the gap and target-counter(attr(href), page) resolves the actual page each chapter lands on after pagination, including split across separate elements on the same line. A cross-reference list demonstrates all four target-text() modes: content, before, after, and first-letter.
Per-page Margins
Layout-affecting per-page margins: each page's own @page margins define its content band, so text flows into visibly different-height pages (deep first page, mirrored :left/:right bands) - with relative units (%, em) supported in per-page rules too.
Per-page Reflow
Left/right per-page margins reflow content to each page's own width: mirrored :left/:right binding gutters re-wrap the justified body text to each page's own measure (CSS Paged Media page-area containing block), not just shift it.
Flex Across Pages of Different Widths
A flex container that continues onto a page of a different width sizes each fragment to its own page (CSS Fragmentation 5.1): the columns of a row re-fit as they cross a page boundary, a wrapping row collects its later lines against the measure of the page each lands on, and the container's own frame follows.
Full-Bleed Pages
An edge-to-edge cover via @page :first { margin: 0 } - the first page's content band is the entire sheet (corner marks touch all four paper edges), followed by a normally margined page.
Named Pages
Routing content to differently-styled pages with named @page rules and the page property.
Mixed Page Orientation
One PDF mixing portrait and landscape pages via a named @page rule's own size - the landscape section's body text genuinely re-wraps to its own wider measure, and a fixed-position corner badge (percentage left/top/width) stays correctly placed and sized on every page despite the sheet itself changing shape.
Directional Page Breaks
Chapters that always open on a right-hand page: break-before: recto inserts a blank verso page when it needs one, and the outer-edge folios show the left/right alternation. The closing colophon declares its break on the heading rather than the division, so it is resolved against the division's own predecessor.
Monolithic Content
A box with break-inside: avoid moves to the next page whole instead of being cut in half by the page boundary. A flex line and a grid row that ask not to be broken move as a unit for the same reason, and the lines below a moved one follow it rather than staying put. A forced break is taken from either side of a break point, so break-after on one line opens the next page for the line after it — and break-after: avoid there moves the earlier line too, so a heading is not stranded on the page its section body just left. Under flex-wrap: wrap-reverse all of this is read down the page rather than down the source, which is the reverse order there.
Orphans and Widows
CSS Fragmentation §5.4's line minimums either side of a page break. widows moves the minimum number of lines across the break rather than relocating the whole paragraph; orphans is decided at the break point, so too few lines before it makes the break fall before the paragraph instead.
Keep With Next
CSS Fragmentation §3.1's break-after: avoid, honored even where the heading was placed in a fragmentainer the layout driver had already finished with.
Table Cell Text Across Pages
CSS Fragmentation §4.1: a line box is a monolithic break unit, so a table cell's own text breaks between lines rather than through one.
Table Row Break Values
CSS Fragmentation §3.1's forced break values honored at the break point between two table rows, with the table's repeating header carried onto the page the break opens.
Table Row Continuation
css-tables-3 §6.1: a row whose cell runs out of room continues on the next page, and the cells of that row are fragmented independently - a short cell finishes where it finishes, while its box continues with the row, its tint and borders running the full depth of each continuation with no content in it. The repeating header is carried onto every page the row reaches, above the continuation rather than over it, and the repeating footer closes each of those pages below it - css-tables-3 §6.2's "leave room" applied at both ends of the band.
Table Row Taller Than a Page
CSS Fragmentation §4.3: a table row whose cell holds a block taller than the page's content band has no page that could hold it, so it is left where it is and overflows across pages - and the rows after it continue immediately below where it ends, rather than being placed back on a page it is still filling and drawn over its content. The repeating header is carried onto every page the table spans, including the ones the row only overflows through: css-tables-3 6.2 asks for room to be left for it there, and 4.3 allows a UA to slice the graphical representation of content it cannot break, so the block resumes below the header on each page rather than running under it.
Rowspan Across a Page Break
css-tables-3 §6.1: a cell whose rowspan reaches out of the page it was placed in is fragmented like any other content - its box closes at the foot of that page and continues at the head of the next, its tint and borders running the full depth of each fragment. The row that ends the span is carried onto the next page whole, like any other row, rather than being left straddling the boundary and drawn cut through by it. This is what both other engines do: Gecko re-reflows the spanning cell against the remaining space and continues it, and Blink treats every cell as its own §2.1 parallel flow. Q4 adds the case where the cell's own content, not just its span, overflows the page it opened on: it is fragmented across every page it passes through rather than left stretched from where it opened to where the span ends (issue #521).
Repeating a Header, or Not
css-tables-3 §6.2 makes repeating a <thead>/<tfoot> conditional: the group repeats only where it carries an avoiding break-inside and where doing so costs under a quarter of the page. The user-agent print stylesheet supplies break-inside: avoid, so repetition is what a table gets by default - and break-inside: auto is the author's way to turn it off, laying the group out once, in flow, and giving the pages after it wholly to the rows.
Page & Margin Box Background/Border
css-page-3 §3.1's @page box background (a cover page tinted independently of the body pages via @page :first, painted below the CSS2.1 canvas fill and the document's own content) plus a footer margin box with its own background-color and border-top. The cover page also gives the page box itself a border and padding (issue #1147), genuinely reserving layout space so the cover's own heading sits inset from the border rather than under it, with background-clip: content-box confining the cover gradient to inside the padding.
Layout
Floats Taller Than A Page
A float taller than a page continues onto the following pages with the text beside it, a block that clears the float starts below its last line, and a tall float inside a break-inside: avoid box keeps its content.
Flexbox
Flexbox layout: direction, wrapping, justification (including start/right and self-start/self-end), alignment, gaps, auto margins on both axes, flexible item sizing, and replaced elements (img/svg) as flex items.
Stretch Sizing
width: stretch (and the legacy -webkit-fill-available): flex items that fill and equally share their container, plus a border-box column flex container that centres its items in the content box.
Replaced Grid Items
Replaced content as grid items: images keep their size or stretch by their ratio (clamped by max-width against the grid area), percentage widths resolve against the area, iframes and one-sided SVGs take the 300x150px default size, and justify-self: baseline lines items of a column up.
Grid Item Content Across Pages
A grid row's own content now fragments across a page break instead of being lost or duplicated: CssLayoutEngineGrid's commit pass lays each row's items out for real once they sit at their final position, live against the fragmentainer they land in - the same content-fragmentation guarantee flex and ordinary block flow already had (issues #517/#526).
Flex Line Content Across Pages
A wrapped flex row container's own item content now fragments across a page break for every line, not only a single-line container: CssLayoutEngineFlex's commit pass walks every line in one pass, committing as many as fit before a later line's content continues on the next page (issues #517/#526).
Flex Column Item Content Across Pages
A flex-direction:column container's items are a sequential flow, and each one's own content now fragments across a page break the same way a row-direction line's items already did: CssLayoutEngineFlex walks a column-direction line's items in turn, committing each one's content live and continuing a later item's remaining content on the next page (issues #517/#526).
Break Points Between Column Flex Items
A break-before/break-after/break-inside:avoid value between two items of the same flex-direction:column line is now honored, moving just that item (and whatever follows it in the line) rather than being read only from the container's own first child - each line of a wrapping column container relocates independently of the others (issue #455).
Flex Item Background Past Its Pinned Height
A flex-direction:column item whose own content is entirely block-level children (no direct text on the item itself) and whose committed content-box size falls short of what it actually holds now keeps its background and border on every page its content spills onto, not only the first - FragmentEmitter.BuildDraft previously had a decoration rectangle only for a box with no content at all in a fragmentainer (a pure continuation shell) or one whose own bounds already reached it, missing the case where a page-grid box's item-content-commit-pinned bounds fall short of the children it genuinely holds there (issue #569).
Blockified Flex and Grid Items
Every in-flow child of a flex or grid container now computes to its block-level display (inline-block to block, inline-flex to flex, inline-grid to grid, inline-table to table), so a nested inline-flex, inline-grid or inline-table item lays out its own gap, alignment, tracks and cells instead of collapsing them. Images stay the item themselves and keep their natural size in a flex row and in a grid, including under the common img { display: block } reset.
Block Placement in ltr and rtl
Where a narrower block-level box sits in a left-to-right and a right-to-left container, including auto margins and overflow.
Positioned Boxes and Inline Content
Absolutely positioned boxes among inline text, anchored to wrapped inlines, and isolated from a preceding float.
Horizontal Rule Attributes
Horizontal rules with their default margins, align, size, color and noshade attributes, and an author margin overriding them.
Atomic Inline Sizing
CSS 2.1 §10.3.9/§10.6.3: a declared width, height, or min-height on a display: inline-block sizes the box itself — fixed-width labels, empty checkbox glyphs, percentage sizing, box-sizing, and the block axis.
display: contents
CSS Display 3 §2.5: an element with display: contents generates no box — its children become flex items, table cells and inline content of its parent — while its id, string-set, links and the body's canvas background still work.
display: flow-root
CSS Display 3 section 2.4: display: flow-root is a block that establishes its own formatting context - it contains its floats and its margins do not collapse with its children's.
aspect-ratio
CSS aspect-ratio in both directions: width→height (with a percentage-height child resolving against the ratio-derived height) and height→width for shrink-to-fit boxes, replaced-element natural ratio vs. a specified/auto ratio, and indefinite-percentage-height sizing.
CSS Grid
CSS Grid layout: fixed and `fr` tracks, item spanning (`grid-column: span 2`, `grid-row: span 2`), dense auto-placement backfilling a hole, and the responsive `repeat(auto-fill, minmax(150pt, 1fr))` card idiom — all laid out by PeachPDF's own grid track-sizing and placement engine.
CSS Grid Template Areas
CSS `grid-template-areas`: a classic "holy grail" page layout where each region places itself with `grid-area: <name>`, plus named grid lines (`[main-start]`) referenced from `grid-column` — the named placement model of PeachPDF's grid engine.
CSS Grid Subgrid
CSS Grid Level 2 `subgrid`: independent rows adopting the parent's columns (`grid-template-columns: subgrid`) so their cells align, and a card deck adopting the parent's rows (`grid-template-rows: subgrid`) so title/body/footer bands line up across cards — the nested grid adopts its parent's tracks.
CSS Grid Intrinsic Sizing & Baseline
CSS Grid sizing/placement depth: `min-content` vs `max-content` tracks, `calc()` inside `minmax()`/`fit-content()`, a spanning item growing the shared intrinsic columns it covers, an explicit line past the grid generating implicit columns, `auto` tracks stopping at the container rather than overflowing it, and `align-items: baseline` sharing one text baseline.
Table Row/Column Collapse
visibility: collapse on table rows, row-groups, columns, and column-groups (CSS 2.1 §17.6.1): the collapsed row/column takes no layout space and its neighbors shift in to close the gap, unlike visibility: hidden which still reserves the space.
Table Captions (caption-side)
caption-side: top (the initial value) and bottom (CSS 2.1 §17.4), stacking a <table>'s <caption> above or below its row grid and stretching it to the table's own content width, with the <table>'s own border/background wrapping the row grid only.
Table & Row Height (height / min-height)
height/min-height on a <table> or <tr> (CSS 2.1 §17.5.3): a minimum, never a clip - the table grows to fit an explicit height taller than its content, with the surplus distributed proportionally across rows, giving vertical-align real room to differ within a row.
Fixed vs Automatic Table Layout (table-layout)
CSS 2.1 §17.5.2's two column-width algorithms on identical markup: auto measures every cell and lets the widest content win its column, while fixed sizes columns from <col> elements and the first row alone - never measuring cell content - and splits the remaining space equally, so long text wraps inside its column instead of widening it. Also shows fixed layout's priority order (<col> beats a first-row cell), a colspan width divided over its spanned columns, and a later row's width being correctly ignored.
Auto Margins on Tables
A fixed-width table with one auto horizontal margin takes all remaining space on that side: margin-left:auto aligns it to the end edge, margin-right:auto leaves it at the start, and two auto margins center it.
Collapsed Table Border Resolution
CSS 2.1 §17.6.2's full border-conflict resolution for border-collapse: collapse - width, then style priority, then cell/row/row-group/column/column-group/table origin, then position - plus <col>/<colgroup> border/background participation and a repeated <thead> whose boundary to the body re-resolves correctly on every page (issue #735).
CSS Values & Functions
Custom Properties
CSS custom properties resolved through var(), including fallbacks and cascading overrides.
Graphics & Effects
Effects on inline-block boxes
transform, clip-path and filter on inline-block boxes and images that sit in a line of text.
SVG
Inline and embedded SVG rendered as true vector PDF content: shapes, paths, gradients, patterns, masks, and text.
SVG: display
display on SVG elements: none removes an element and its subtree from rendering, and contents strips a group, use or text content child while keeping its content and what it inherits.
SVG: styled from a stylesheet
Rules in the document's stylesheet reach a gradient stop's stop-color and stop-opacity, a rule's fill: url(#id) paints a gradient, unitless stroke-width and stroke-dashoffset work as SVG allows, and a CSS transform with units (turn, grad, translateX, skew) is read on SVG elements.
SVG Form XObject Reuse
The same SVG logo and SVG border-image on all twelve pages, plus a small icon referenced by four separate <img> elements on one page: each is stored once as a document-local Form XObject and invoked wherever it appears, rather than written into the PDF again per page or per element - three copies of the artwork instead of twenty-eight, and a file around 18% smaller.
SVG Text: Gradient, Stroke & Path
SVG text with gradient/pattern fill, stroke, and glyphs laid along a path (textPath) - all rendered as real vector PDF content.
SVG textPath: Stretch & Fixed Paint
textPath method=stretch bends glyph outlines along the curve; gradients on curved text stay fixed or span the whole text; objectBoundingBox clip-path on text uses the text bounds.
SVG foreignObject
HTML embedded in an inline SVG with foreignObject: wrapped text, lists, a table, and a rotated, translucent box, laid out by the HTML engine and painted in SVG user space.
SVG Text: Vertical Writing Mode
SVG <text> under writing-mode: vertical-rl/vertical-lr with real per-character text-orientation - CJK glyphs upright, Latin/digits rotated, composing with gradient fill.
Opacity
Element opacity composited as real group transparency over text, images, and nested content.
Stacking Contexts
z-index and stacking contexts: paint order across positioned, floated, and transformed boxes.
SVG context paint
SVG 2 context-fill and context-stroke: a shape defined once takes the fill and stroke of each <use> that instantiates it, a marker draws with the fill and stroke of the shape it is placed on - including a gradient or pattern, mapped through the marker's own placement - and a use's context paint follows a transform between what it instantiates and the shape that actually paints it, including when the use targets a symbol or a nested svg.
SVG Text: Arabic-Family Joining & Devanagari USE
Native SVG <text>/<tspan> content shaped with the same real per-character joining-form resolution, GSUB substitution (including a font's own rlig lam-alef ligature and GPOS cursive attachment), and Devanagari USE syllable reordering HTML text already had - previously SVG rendered this text as isolated, unjoined, unreordered nominal glyphs only.
CSS Filter
filter: opacity(), brightness(), contrast(), and invert() - genuinely native PDF color math via ExtGState /TR, composed into a single transfer function per element.
CSS Filter (Portable)
filter: brightness(), contrast(), and invert() written as blend-mode layers instead of a transfer function, so readers that ignore /TR still show them.
CSS Filter (Rasterized)
filter: blur(), grayscale(), sepia(), saturate(), and hue-rotate() - rendered into a bitmap at the configured RasterizationDpi and embedded at exactly the element's own size, while the rest of the page stays vector.
Hinted Raster Text
PdfGenerateConfig.TextHinting = Standard: text that has to be drawn into a bitmap (here under filter: grayscale(1), at a deliberately low RasterizationDpi of 72) follows the font's own TrueType hinting, so stems and baselines land on pixel edges. The PDF's vector text is not affected.
Raster Text Without Hinting
The same page as the hinted raster text showcase with TextHinting left at its default, None: outlines are only scaled, so edges cut through pixels and small text is softer.
Hinted Raster Text (CFF Outlines)
PdfGenerateConfig.TextHinting = Standard with a font whose outlines are CFF (Source Code Pro, an OpenType font): the stem hints and blue zones of its charstrings, run by a port of Adobe's CFF engine, put stems, x-heights and baselines on pixel edges in the bitmaps this page rasterizes at 72 dpi.
Raster Text Without Hinting (CFF Outlines)
The same page as the hinted CFF raster text showcase with TextHinting left at its default, None: the outlines are only scaled, so edges cut through pixels.
Stem-Darkened Raster Text (CFF Outlines)
PdfGenerateConfig.TextStemDarkening = true on top of TextHinting = Standard, with a font whose outlines are CFF: Adobe's stem darkening makes the thinnest stems a little heavier, which offsets the way anti-aliasing thins small text; stems of more than about two and a third pixels are left alone. Compare with the hinted CFF page without it.
Hinted Raster Text (CFF2 Variable Font)
PdfGenerateConfig.TextHinting = Standard with a variable font whose outlines are CFF2: the hints and blue zones of its charstrings are blended for the weight of each line (300 to 900) before Adobe's CFF engine applies them, so the top, the bars and the baseline of the letters land on pixel edges at every weight, in the bitmaps this page rasterizes at 72 dpi.
Raster Text Without Hinting (CFF2 Variable Font)
The same page as the hinted CFF2 raster text showcase with TextHinting left at its default, None: the outlines are only scaled at each weight, so bars and tops cut through pixels.
Raster Anti-Aliasing (On, Default)
PdfGenerateConfig.RasterAntiAliasing left at its default, true: a circle, a rotated square and small text, all drawn into a bitmap (here under filter: grayscale(1), at a deliberately low RasterizationDpi of 72), have smoothed, fractional-coverage edges. This is a whole-graphics setting - it affects shape fills, images and text alike, not text alone. Compare with the same page with it off.
Raster Anti-Aliasing (Off)
The same page with PdfGenerateConfig.RasterAntiAliasing = false: every pixel PeachPDF rasterizes itself is thresholded to fully transparent or fully opaque instead of smoothed, so the curved and diagonal edges look stair-stepped and the small text looks harder-edged. The PDF's own vector text and paths are unaffected either way, since a viewer anti-aliases those itself.
Shadows (Gaussian blur)
text-shadow, blurred box-shadow (outer and inset), and filter: drop-shadow() - real Gaussian blurs rendered into bitmaps beneath vector content, following the actual glyph, image, and SVG shapes.
SVG Filters (Rasterized)
SVG filter primitives PDF has no operator for - blur, drop shadow, morphology, convolution, turbulence, displacement and lighting, cross-channel colour matrices, table/gamma transfer functions, arithmetic compositing - evaluated over pixels in linear light and embedded at the document's raster resolution.
SVG Filter Inputs (feImage, FillPaint, BackgroundImage)
feImage with a stand-alone image (fitted by preserveAspectRatio into its subregion) and with a reference to an element, plus the FillPaint / StrokePaint / BackgroundImage / BackgroundAlpha inputs: a filter can paint the element's own gradient, stroke a halo in its stroke colour, or blur the page and the SVG content painted behind it.
Backdrop Filter
backdrop-filter on frosted-glass panels over a gradient and text: blur, grayscale + contrast, blur + saturate, and invert + hue-rotate, each applied to what was painted behind the panel and clipped to its rounded corners.
Legacy Vendor-Prefixed CSS
A stylesheet written only with the legacy -webkit-/-moz- spellings (autoprefixer-era output): prefixed linear, radial and repeating gradients in their pre-standard syntax, box-shadow, border-radius, box-sizing, transform, flex and sticky, the -webkit-box flexbox model (box-pack, box-align) and the -webkit-box + -webkit-line-clamp text-truncation idiom - each renders exactly as its standard spelling.
Perspective and 3D Transforms
CSS perspective on a parent and perspective() in a transform: rotateX/rotateY cards foreshortened in real perspective, translateZ scaling, backface-visibility, and a perspective card with opacity - warped from a bitmap of the element at the raster resolution.
3D Transforms on SVG Elements
The 3D transform functions on SVG elements: rotateX/rotateY, translateZ and perspective() in a transform, a container's perspective and perspective-origin, backface-visibility, transform-style: preserve-3d with intersecting planes, a group carrying its children, and a filtered element warped with its filter.
3D Rendering Contexts (preserve-3d)
transform-style: preserve-3d: a cube, a carousel, flip cards with hidden back faces and intersecting planes, each depth-tested per pixel in one shared 3D space, with the parent's perspective reaching every nested plane - against the same planes flattened.
mix-blend-mode
mix-blend-mode composites overlapping content via a real PDF blend mode (ExtGState /BM) - normal, multiply, screen, and difference shown over overlapping circles.
CSS Animations: Start, Midpoint and End
One page animated with CSS, rendered at three points by PdfGenerateConfig.AnimationProgress: page 1 at 0 (the start of every animation), page 2 at 0.5 (half way through each animation's own run) and page 3 at 1 (the end). The two logos cross-fade (without the option they are drawn on top of each other), and a bar, a color, a rotating tile with a growing shadow, a stepped box, a box on a linear() spring curve, a border that mixes toward currentcolor, a gradient whose stops mix with currentcolor, an oklch() color mixed in Oklab and a box whose two transform lists differ in their functions (mixed through matrix decomposition) move between the states. With animation-direction: alternate the first cycle still runs forward, so the end is the 100% keyframe.
filter: drop-shadow()
CSS filter: drop-shadow() approximated with box-shadow's own vector blur technique, keyed off the filtered element's own rectangle - not a true alpha silhouette.
SVG Filter: feBlend & feColorMatrix
Native SVG <filter> primitives - feBlend (a real PDF blend mode) and feColorMatrix (a channel-independent matrix via PDF's /TR transfer function) - never rasterized.
SVG Filter: Multi-Primitive Graph
A real SVG <filter> primitive graph (feFlood, feComposite, feOffset, feMerge) building a drop shadow from named, non-adjacently-referenced results - the general filter graph evaluator, not a simple linear chain.
Typography & Text
Unicode Line Breaking
Where a line may end follows the Unicode line breaking algorithm (UAX #14): kana and ideographs break between characters, word-break:keep-all keeps them together, break-all also breaks Latin letters, and hyphens, slashes, numbers and punctuation get the algorithm's rules.
line-break and Language
The breaks CSS Text 3 allows for line-break: normal and loose only in Chinese and Japanese text follow the lang attribute: the wave dash and centred punctuation may start a line, and a suffix or prefix of East Asian width may be split from its number, while English text keeps them together.
Thai, Lao, Khmer and Burmese Line Breaking
Scripts written without spaces wrap at the words a dictionary finds and never inside a syllable: Thai, Lao and Khmer paragraphs in real Noto Sans glyphs at three widths each (Khmer also shaped with real coeng/subjoined-consonant stacking), and Burmese as blocks in the line breaking test font, where the word boundaries are visible.
overflow-wrap
CSS Text emergency wrapping with overflow-wrap:anywhere, overflow-wrap:break-word, the legacy word-wrap alias, and their distinct min-content sizing behavior.
Hyphenation — English (en-US)
Automatic hyphenation (hyphens: auto) splitting long words at real, language-appropriate break points in a narrow justified column.
Hyphenation — German (de-DE, reformed orthography default)
Automatic hyphenation (hyphens: auto) splitting long words at real, language-appropriate break points in a narrow justified column.
Hyphenation — French (fr)
Automatic hyphenation (hyphens: auto) splitting long words at real, language-appropriate break points in a narrow justified column.
Hyphenation — Russian (ru, Cyrillic script)
Automatic hyphenation (hyphens: auto) splitting long words at real, language-appropriate break points in a narrow justified column.
Hyphenation Control Properties
CSS Text 4's hyphenate-character, hyphenate-limit-chars, hyphenate-limit-zone and hyphenate-limit-lines shown side by side against default hyphens:auto behavior: a custom hyphen glyph, wider before/after character minimums moving where a word breaks, a wide limit-zone accepting a larger ragged gap at a line's end rather than hyphenating its last word, and a limit-lines of 1 stopping two hyphenated lines in a row (issue #713).
hyphenate-limit-last
CSS Text 4's hyphenate-limit-last preventing a hyphen from ending the last line before a page break: the default none lets it hyphenate right up to the boundary, always moves the whole word onto the following page instead.
Vertical Align
vertical-align behaviors for inline content, from baseline and middle to explicit offsets, including its length and percentage forms.
line-height: normal
line-height: normal resolved from each font's own ascent/descent/line-gap metrics, matching browser behavior, rather than a flat 1.2× font-size.
Declared line-height
A declared line-height sets the line box height in both directions - including shorter than the font, where the glyphs overflow - plus the block's strut on every line.
Baseline alignment & leading
Every inline box on a line shares one baseline - images, inline-blocks and markers included - with a declared line-height's leading split half above the text and half below.
text-decoration-thickness
text-decoration-thickness (CSS Text Decoration 4): auto, from-font, and explicit length/percentage underline thickness.
text-decoration-style
text-decoration-style (CSS Text Decoration 3 §2.2): solid, dotted and dashed as pen patterns, double as two strokes — the accounting rule under a grand total — and wavy as a stroked curve.
Decoration Skipping
text-decoration-skip-ink (CSS Text Decoration 4) breaking underlines around descenders, and CSS Text Decoration 3's rule that atomic inlines are not decorated.
Decorated Inline-Block
A decorated inline-block (an <a>, say) is underlined only under its own text, per CSS Text Decoration 3 §2.4: an icon-only link has no line, and a wide box is underlined only as far as its text.
tab-size
tab-size (CSS Text 4): controlling how far a preserved tab character indents inside white-space:pre content.
text-indent
text-indent's plain, hanging, and each-line forms (CSS Text 3), including their combination and interaction with text-align: center.
Justification & text-align-last
text-align: justify leaves every line that ends a paragraph ragged - the block's last line and the last line before a <br> - and text-align-last (auto, justify, center, right) says how those lines are aligned instead. text-align is a real shorthand (CSS Text 3 §6.1) over text-align-all and text-align-last: justify-all forces both to justify, and match-parent resolves a logical start/end against the parent's own direction rather than the element's own.
writing-mode (Vertical Text)
Real vertical-rl/vertical-lr line flow: columns stacking along the block axis, text running top-to-bottom within each column, real per-character text-orientation (upright CJK next to rotated Latin), writing-mode-aware Flexbox and Table layout (including captions, thead/tfoot, collapsed borders, vertical-align and rowspan row-axis sizing), block-level/orthogonal-flow content inside a vertical box, direction: rtl block children anchoring to the physical bottom edge, real CSS2.1 margin collapse (sibling-to-sibling and box-own-edge) between block-axis-stacked children, and text-align, Unicode Bidi Algorithm reordering, hyphenation, position: absolute/fixed, and float column wrap-around all working inside vertical line flow.
Floats and clear in vertical text
float and clear in a vertical writing mode: left and right are line-relative (top and bottom), floats slide along the inline axis and text wraps around them.
text-overflow: ellipsis
Per-line-box truncation with a trailing ellipsis wherever content overflows an overflow:hidden container's content edge - Tailwind's truncate idiom for the common single nowrap line, a wrapping paragraph whose one unbreakable line overflows, and both horizontal directions plus vertical-rl/vertical-lr writing modes, each finding the correct end edge (right/left/bottom/top) for its own writing-mode/direction combination.
line-clamp
line-clamp (CSS Overflow 4): a layout-time cutoff limiting a block to a fixed number of visible lines, with a generated ellipsis on the last one whenever content is actually truncated - the block's own height shrinks to fit only the visible lines, and content past the limit is never laid out at all.
Font Resolution
CSS font selection compliance: nearest-weight matching across a six-weight family, faux-bold/italic synthesis, oblique angles, font-stretch face selection, and generic family resolution.
@font-face unicode-range
Per-character font matching: a monospaced webfont declared only for the digit range (U+0030-0039) supplies the digits, while letters in the same text run fall back to serif - each character resolved to the family whose unicode-range (or glyph coverage) covers it.
Last-Resort System Font Fallback
The final step of the CSS Fonts 4 matching algorithm: when no font in the declared font-family stack covers a character, PeachPDF searches every OTHER font registered with the document - here a Noto Sans Arabic subset registered but never referenced in any font-family - instead of drawing a missing-glyph box.
Emoji (astral codepoints)
Supplementary-plane glyph rendering and grapheme-aware wrapping: adjacent emoji resolve through a bundled Noto Emoji subset and wrap as complete clusters; the separate Color Fonts showcase covers COLR/CPAL.
Color Fonts (COLR/CPAL)
COLR/CPAL color-glyph fonts — including the real COLR v1 build of Noto Color Emoji — rendered as native PDF vector content: layered palette colors, gradients, transforms, and blend-mode compositing, with an invisible embedded subset for searchable, selectable, exact-copy text.
font-variant-emoji
Choosing between the text (outline) and emoji (colour) form of a character: the four font-variant-emoji keywords, and how an explicit U+FE0E / U+FE0F variation selector overrides them, shown with a colour font and an outline font that both cover the same heart.
CSS font-palette
Selecting among a COLR/CPAL color font's palettes with the CSS font-palette property: the light/dark keywords, custom palettes via @font-palette-values (base-palette + override-colors), and palette-mix(). Rendered against a subset of Nabla, a real 7-palette COLR v1 font.
SVG text: font-palette and font-variant-alternates
SVG <text> selecting a color font's CPAL palette with font-palette / @font-palette-values and a font's stylistic sets with font-variant-alternates / @font-feature-values, exactly as HTML text does.
SVG text: CSS text properties
SVG <text> with a font-family fallback list, the font and text-decoration shorthands, decoration thickness and skip-ink, text-shadow, paint-order, dominant-baseline and baseline-shift (also on a textPath), -webkit-text-stroke, textLength and xml:space.
SVG text: auto-wrapping
SVG <text> laid out with inline-size and shape-inside: text-indent, line-height, text-align (including justify and the text-anchor fallback), hyphens, white-space: pre-line hard breaks, and wrapping inside a triangle and a circle.
Variable fonts
font-weight, font-stretch and font-variation-settings choosing locations in a variable font's design space: the glyph outlines, advances and metrics follow the axes, and each location is embedded in the PDF as a static instance. Rendered against a small synthetic variable font with weight and width axes.
Variable fonts with CFF2 outlines
A variable font with CFF2 (variable CFF) outlines at different weights, widths and font-variation-settings locations: the charstrings blend at the location, and each location is embedded in the PDF as a static CFF font. Rendered against a small synthetic font.
Variable fonts: avar 2 and vertical metrics
An avar version 2 font, whose axes move each other, beside the same design without the cross-axis mapping, and vertical text whose glyph advances follow the axes through VVAR. Rendered against small synthetic variable fonts.
Variable font ranges
@font-face weight, width and oblique ranges for a variable font: the face covers its whole range in font matching, the weight, width and slant of the text set the font's axes inside the range, font-stretch takes percentages, and nothing is faked that an axis supplies. Rendered against a small synthetic variable font with weight, width and slant axes.
Variable colour fonts
A COLR version 1 colour font whose paints vary with the font's axes: opacities, gradient geometry and colours, and transforms all follow the location, as font-weight and font-stretch move it. Rendered against a small synthetic colour font, one glyph per variable paint format.
Face matching order
CSS Fonts 4 face matching: a family's faces are narrowed by width, then style, then weight, so a condensed italic request gets the condensed face; the requested oblique angle chooses among faces that declare oblique ranges; and font-weight takes fractions such as 350.5.
SVG-in-OpenType glyphs
Colour glyphs drawn from a font's SVG table: the SVG document of each glyph is rendered as vector content, its palette variables follow font-palette, and context-fill and context-stroke follow the text and the <use> they are inside, also inside a filtered (rasterized) element; artwork that lies outside the em box is drawn, not clipped. Rendered against a small synthetic font.
GSUB Ligatures
Real GSUB liga/clig ligature substitution (not a synthesized effect): font-variant-ligatures actually turns a font's ligatures on and off, for both ordinary text and gradient-filled SVG text.
Font Variant: Caps, Numerals & Position
font-variant-caps prefers a font's real GSUB smcp/c2sc/titl substitution, falling back to a synthesized approximation only where the standard allows it; font-variant-numeric activates a font's real oldstyle/tabular/slashed-zero GSUB features the same way, and font-variant-position uses real sups/subs glyphs where a font has them and synthesizes them from its OS/2 metrics where it doesn't.
font-variant-alternates & @font-feature-values
Named aliases for a font's numbered stylistic-set GSUB features: @font-feature-values maps a readable name to a feature index per font family, and font-variant-alternates's styleset()/character-variant()/swash()/ornaments()/annotation()/stylistic() functions select them by name. Rendered against a subset of Recursive, a real font with genuine ss01/ss02 stylistic-set data.
Bidirectional Text (dir, bdo, bdi)
A real Unicode Bidi Algorithm (UAX #9): the dir global attribute (incl. auto-detection), bdo/bdi, and CSS direction/unicode-bidi, with per-character reordering, digit/Latin run embedding, and bracket mirroring in real Hebrew text.
Arabic-Family Complex-Script Joining
Positional initial/medial/final/isolated GSUB joining forms resolved from each character's own Unicode Joining_Type, a font's rlig lam-alef ligature, and GPOS cursive attachment (curs) for a calligraphic font whose joining relies on it.
Devanagari Universal Shaping Engine (USE)
Indic_Syllabic_Category/Indic_Positional_Category-driven syllable classification, GSUB conjunct (cjct)/reph (rphf) formation, and the resulting glyph reorder (repha repositioning, pre-base matra movement) - ported from HarfBuzz's own Universal Shaping Engine.
USE: Bengali, Gujarati & Tamil
Universal Shaping Engine syllable reordering extended to three more Brahmic scripts - pre-base matra movement, conjunct (cjct)/reph (rphf) formation, and Bengali's own two additional USE categories (Consonant Placeholder, Syllable Modifier) no Devanagari codepoint reaches.
text-underline-offset & text-underline-position
text-underline-offset moves an underline further from (or closer to) the text it decorates; text-underline-position chooses auto/from-font/under as the position that offset is measured from. Both were previously unimplemented and silently dropped at parse time.
Vertical Writing Mode: text-decoration
Under a true vertical writing mode (vertical-rl/vertical-lr), a text-decoration line now runs along the column's own extent on the correct physical side of the glyphs, instead of being drawn as a short horizontal stroke across its top. Also covers text-decoration-skip-ink now applying to a rotated run and text-underline-position: left/right pinning the underline to a literal physical edge, switching a same-line overline to the opposite edge when they would otherwise collide.
Vertical Writing Mode: background-clip: text
background-clip: text now clips to the real glyph-outline union under a true vertical writing mode (vertical-rl/vertical-lr), for both a rotated (sideways) run and an upright run - including one whose font carries real vhea/vmtx vertical metrics - instead of falling back to a plain border-box fill.
Standards & Accessibility
Tagged PDF (PDF/UA)
Accessible, tagged PDF output: a logical structure tree with headings, lists, tables, alt text, links, and tag-type overrides.
PDF/A Conformance
Archival PDF/A output: an embedded sRGB ICC output intent, XMP metadata with pdfaid:part/conformance, and (at the accessible "A" level shown here) a tagged structure tree.
PDF/A-3 Attachments
Embedded files in a PDF/A-3 document, added through PdfGenerateConfig.Attachments: a CSV holding the report's data and a text note, each with its own MIME type and AFRelationship, indexed in both /AF and /Names /EmbeddedFiles.
ZUGFeRD / Factur-X Invoice
A hybrid e-invoice: a readable invoice laid out with the declarative API, plus the same invoice as EN 16931 Cross Industry Invoice XML - generated by the open-source ZUGFeRD-csharp library and embedded by PdfGenerateConfig.FacturX in a PDF/A-3 file, with the Factur-X XMP metadata and extension schema.
ZUGFeRD XRechnung Invoice
The same hybrid e-invoice in the German XRECHNUNG profile, for an invoice to a public body: the XML is embedded as xrechnung.xml and the buyer reference (Leitweg-ID) is carried both in the XML and on the page.
CMYK Colors
CSS device-cmyk() colors, carried through natively as real DeviceCMYK PDF operators (including gradients and color-mix() between two CMYK colors), coexisting on the same page as ordinary RGB colors.
PDF/X-1a Conformance
Print-production PDF/X-1a output: a caller-supplied CMYK ICC output intent, CMYK-only content, and the achromatic-RGB TrueBlack conversion that keeps un-set default text colors working under the CMYK-only restriction.
PDF Bookmarks (Outline)
Automatic PDF outline generation from headings, with full CSS control via bookmark-level/bookmark-label/bookmark-state and -peachpdf-bookmark-target.
PDF/A-1 with Flattened Transparency
A PDF/A-1b document that uses rgba backgrounds, opacity, a blurred shadow, mix-blend-mode and translucent text - all forbidden by PDF/A-1 - generated with TransparencyPolicy.Flatten, which renders each affected region as an opaque bitmap.
Real-World Documents
Repeating Table Headers
A 60-row sales ledger spanning three pages - the table header repeats automatically on every page, framed by @page margin-box running headers and page counters.
Modern Invoice
A one-page, full-bleed invoice in a dark green palette: custom properties, oklch gradient interpolation, gradient-border cards, zero-padded line numbers via counter(line, decimal-leading-zero), a transform stamp, and an inline SVG logo.
Charts & Data Viz
Charts.css
The Charts.css framework (MIT) rendering column, bar, area, line, and pie charts — plus a multi-series example and the documented customizations (extruded 3D bars via stacked box-shadows, a skewY tilt, and shadowed bars with inset+outset box-shadow) — purely from CSS. The full official stylesheet is embedded, exercising @property, aspect-ratio, clip-path, box-shadow, logical properties, and conic/linear gradients together.
Images & Replaced Content
object-fit & object-position
The CSS object-fit (fill/contain/cover/none/scale-down) and object-position properties applied to a replaced <img>: the same 2:1 image sized/cropped/positioned inside a fixed square box, with corner markers making each fit and crop obvious.
The embed element
<embed> as a void replaced element: an image or SVG src is drawn at the size given by width/height, a transform applies to it, and an embed with no drawable resource still reserves its box. The text after each embed stays in the paragraph.
image-rendering
The CSS image-rendering property (auto, smooth, high-quality, crisp-edges, pixelated) on a small pixel-art image enlarged sixteen times: blended pixels versus hard-edged ones, inherited down the tree and applied to a repeating background as well as an img.
srcset, sizes & <picture>
Responsive image markup resolved for a fixed page: srcset with x and w descriptors, sizes, and <picture>/<source> selected by media and type, each cell showing which candidate was chosen.
CMYK JPEG Images
A CMYK JPEG embedded via byte-for-byte pass-through (DeviceCMYK, with a Decode array undoing Adobe's inverted-CMYK convention) instead of being converted to RGB - preserving the original print separations exactly rather than destroying them with a naive, color-management-free conversion.
CMYK TIFF Images
A CMYK TIFF decoded natively and embedded as a raw FlateDecode DeviceCMYK stream - TIFF has no DCTDecode-equivalent PDF pass-through filter, so this is a genuinely new encode path rather than a byte-for-byte copy, preserving the source's CMYK separations without ever touching RGB.
PNG Lossless Pass-through
An opaque PNG (no real per-pixel alpha, not interlaced) embeds byte-for-byte via /FlateDecode pass-through - the PNG's own compressed IDAT data, unchanged, with an /Indexed color space for a palette source or a color-key /Mask array for tRNS chroma-key transparency - instead of being decoded and re-encoded as a lossy JPEG at quality 75.
Lossless WebP & AVIF Embedding
A WebP or AVIF source that was itself encoded losslessly (VP8L, or AV1's lossless coding path) is detected via PeachImage's ImageInfo.IsLosslessEncoding and embedded as a raw /FlateDecode stream under ImageCompression.Auto/Lossless, instead of always being re-encoded as lossy JPEG the way every earlier PeachPDF version did regardless of the source's own encoding.
JPEG XL Images
JPEG XL (decode only, via PeachImage 0.5.0): lossy and lossless, alpha, 16-bit samples, animation (first frame), ICC profiles, and files made by recompressing a JPEG, which are turned back into the original JPEG and then embedded under the usual JPEG rules (a CMYK or ICC-tagged one byte for byte).
image-orientation
image-orientation: from-image honors the image's own Exif orientation (a photo taken with the phone held sideways renders upright), none ignores it, and an angle with an optional flip replaces it. The orientation is applied as a placement transform, so JPEG, PNG and CMYK pass-through embedding stays byte for byte.
GIF Lossless Pass-through
A GIF that isn't interlaced, whose LZW minimum code size is exactly 8, and whose frame covers the full logical canvas embeds the same LZW codes its own encoder produced as /LZWDecode with an /Indexed color space - re-packed from GIF's bit order into PDF's, instead of being decoded and re-encoded.
PNG Alpha-Channel /SMask Split
A PNG with a real per-pixel alpha channel (color type 4/6, or a palette source with a genuine partial-alpha tRNS entry) embeds as a color /FlateDecode XObject plus a child /SMask, both split out of the source's own interleaved IDAT data, instead of a full pixel decode and a raw alpha mask.
ICC Color Profile Preservation
A PNG, WebP, or AVIF source's embedded ICC color profile is now extracted and embedded as an /ICCBased color space (/N + /Alternate + the raw profile bytes) instead of being silently dropped in favor of a bare /DeviceRGB or /DeviceGray - preserving the source's actual color intent for wide-gamut or non-sRGB-tagged images.
Color
Modern CSS Colors (oklch, color-mix)
A wide-gamut palette authored in oklch() with oklab()/lab()/lch()/hsl()/hwb() companions, plus color-mix() opacity modifiers (including hex operands of either form) and blends composited over a checkerboard — the CSS Color 4/5 function set modern utility frameworks emit, resolved to real PDF colors.
Selectors & Cascade
@layer Cascade Layers
CSS cascade layers: an @layer order declaration makes a later layer's low-specificity rule win over an earlier layer's high-specificity (#id) rule, and an unlayered rule beat every layer; for !important the layer order reverses (earlier layer wins), and revert-layer reveals a lower layer — the layering model modern utility frameworks rely on.
CSS Nesting
CSS Nesting: a card styled entirely by rules nested inside `.card` — the `&` nesting selector (`&.accent`), an implicit-descendant nested selector (`.body`), a child combinator (`> .tag`), and a two-level-deep nested combinator (`& + .tag`), resolved against the parent exactly like `:is(.card)`.
Unmatchable Selectors
Selectors PeachPDF recognizes but can never match — `:host`, `:host()`, `::placeholder`, and vendor extensions like `::-webkit-file-upload-button` — no longer invalidate the selector list they share with a real selector. Every token, colour and measure here arrives through such a list, including a Tailwind-v4-shaped `:root, :host` design-token block.
Document-Tree Pseudo-Classes
`:empty`, `:any-link` and `:scope` — the three pseudo-classes that depend only on the document tree, so a static renderer can evaluate them. The design tokens here come from a `:scope` block, the link styling from `:any-link`, and the table's flagged gaps plus the collapsed callout from `:empty` (which counts white space as no content, and ignores generated `::before`/`::after` boxes entirely).
Responsive Design
Responsive @media (wide page)
A mobile-first stylesheet rendered on a wide (A4 landscape) page: the `@media (min-width: 60rem)` breakpoint matches the page-box width, so the grid becomes three columns and the badge flips to "desktop".
Responsive @media (narrow page)
The identical stylesheet rendered on a narrow (A4 portrait) page: the breakpoint does not match, so the grid stays a single column and the badge reads "mobile" — proof the width feature actually gates.
Dark Mode (prefers-color-scheme)
The same page rendered with `PdfGenerateConfig.PreferredColorScheme = PdfColorScheme.Dark`, so the `@media (prefers-color-scheme: dark)` rules apply — the dark surface and light text render, a utility framework's `dark:` variants included.
Responsive @container (size queries)
Three `container-type: inline-size` containers of different declared widths on one page, all using the identical `.card` component. The `@container card-shelf (min-width: 400px)` rule applies independently per container - the 500px one flips to a horizontal layout while the 220px and 320px ones stay stacked, proving the breakpoint reads each container's own resolved width rather than the page's.
Viewport units (vw/vh/vmin/vmax)
Bars and boxes sized entirely from `vw`/`vmin`/`vmax` against a fixed A4 page - proving the page box is a real, working viewport numerator. Also includes a `cqw` box with no ancestor `container-type`, which now falls back to the small-viewport unit instead of collapsing to a zero-width box, and a `ch`-sized box (the `0.5em` approximation).
Interactivity
Math
Document Building
Overlay and Underlay PDF Files
IDocumentBuilder.UnderlayFile/OverlayFile: pages of an existing PDF (here a letterhead with a band and a frame) are drawn under or over the document's own pages, paired with target pages by a range such as "1-z", and cycled with RepeatSourcePages.
Declarative Document-Building API
PdfGenerator.CreateDocument: pages, a padded/bordered/shadowed card, a table with a repeating header, a dashed divider, a bulleted list, a line-clamped paragraph with a custom ellipsis, auto-detected per-span text direction, hand-authored and ScottPlot-generated standalone SVG, a dynamically-generated raster chart sized to its own container, and a repeating page-numbered footer, built directly in C# with no HTML/CSS strings - layered entirely on PeachPDF's own flexbox, table, list, line-clamp, bidi-detection, SVG, and running-header/footer machinery.
Sectioned Page Numbers
BeginPageNumberOfSection/EndPageNumberOfSection mark a chapter's own page range; PageNumberWithinSection/TotalPagesWithinSection then resolve "page 2 of 5" scoped to just that chapter, shown here alongside the document-wide CurrentPageNumber/TotalPages for comparison - unsectioned front matter and an appendix bracket the chapter to make the difference visible.
Stylesheet, Class/Id, and HTML Fragments
IDocumentBuilder.Stylesheet attaches a document-level stylesheet so IContainer.Class/Id/Tag can target declaratively-built containers with real CSS selectors (including compound classes like "line-item highlight"), a base @page rule's margin merges with the page's own Header, and IContainer.Html(...) splices a real parsed HTML fragment into the tree with a <slot> filled in from C#.