HTML and CSS support
PdfPecker lays out HTML and CSS the way Chrome prints it. Anything not listed here should be assumed missing; the known gaps are listed under Limitations.
HTML
The common document elements: headings, paragraphs, div/section-style blocks, span, a (external links
and #id links inside the document), b/strong, i/em, u, s, sub, sup, small, big, mark, code,
pre, blockquote, hr, br, ul/ol/li (nested, with start and value), dl, table (with thead,
tbody, tfoot, caption, colspan, rowspan, col width), img, inline <svg>, and legacy attributes such as align,
valign, bgcolor, width, height, border, cellpadding, cellspacing and <font>. The dir attribute
(ltr, rtl and auto), <bdi> and <bdo> set the text direction. The parser is forgiving
about unclosed and misnested tags, the way browsers are.
Markdown is converted to this HTML first; see Markdown.
CSS
<style> blocks, <link rel="stylesheet">, inline style attributes, @media (media queries level 4:
print, width/height and orientation of the page area, ranges such as (400px <= width <= 800px), and, or,
not), @supports (property tests, selector(), and/or/not), @layer cascade layers, CSS nesting (&),
@property (initial values and inheritance of registered custom properties) and @page (see
Paged media). Selectors: type, .class, #id, *, attribute selectors ([a], =, ~=, |=,
^=, $=, *=, with i/s flags), descendant, >, +, ~, :first-child, :last-child, :only-child,
:nth-child() and :nth-last-child() (incl. of S), :first-of-type, :last-of-type, :only-of-type,
:nth-of-type(), :nth-last-of-type(), :not(), :is(), :where() and :has() (all with selector lists; :is()
and :where() skip entries they do not understand), :root, :link, :empty, :lang(), form states (:checked,
:disabled, :enabled, :required, :optional, :read-only, :placeholder-shown and the like), ::before,
::after and ::marker, with specificity and !important handled as in browsers.
CSS properties
| Area | Properties |
|---|---|
| Box model | display (block, inline, inline-block, flex, inline-flex, grid, inline-grid, list-item, table parts, none), margin, padding (also the logical margin-inline/-block and padding-inline/-block properties and their -start/-end longhands), border (solid, dashed, dotted, double), border-radius (incl. elliptical / radii and percentages; rounds backgrounds, borders, shadows and images), box-shadow (outer shadows; a blur is drawn as fading bands), overflow (hidden, clip, auto and scroll clip to the padding box, following its rounded corners, also in table cells; overflow-x/overflow-y), outline and outline-offset (all border styles; follows rounded corners), width, height, min-/max-width, min-height, box-sizing, aspect-ratio (incl. auto <ratio>), object-fit and object-position on images |
| Text | color, font, font-family, font-size, font-weight, font-style, line-height, text-align (incl. justify, start and end), direction, unicode-bidi, text-decoration, text-transform, text-indent, letter-spacing, word-spacing, white-space, overflow-wrap/word-wrap, word-break (break-all), vertical-align, text-shadow (several shadows; a blur is drawn as faint copies of the text), text-overflow: ellipsis (on a box that clips its overflow), text-decoration-style (solid, double, dotted, dashed, wavy), text-decoration-color, text-decoration-thickness, text-underline-offset, text-align-last, tab-size, font-variant: small-caps (synthesized from capitals when the font has none), line-clamp and -webkit-line-clamp (with an ellipsis), `hyphens: manual |
| Backgrounds | background-color, background-image and background with url() images (PNG, JPEG, GIF, WebP, and SVG files drawn as vectors), linear-gradient(), radial-gradient(), conic-gradient() (pie charts and colour wheels, drawn as smooth PDF shadings) and their repeating- forms (several layers allowed); background-repeat (incl. space, round), background-position (incl. edge offsets like right 10px bottom 5px), background-size (cover, contain, lengths), background-origin, background-clip. Repeated images are written once as PDF tiling patterns. url() in a linked stylesheet is relative to the stylesheet and follows the same file access rules as <img>. As in Chrome's print output, the background of <html>, or else of <body>, fills every page area (images and gradients too, positioned against the root box and continuing from page to page); @page { background: <colour> } also colours the page margins. opacity on SVG |
| Flexbox | flex-direction, flex-wrap, flex-flow, flex, flex-grow/-shrink/-basis, order, justify-content, align-items, align-self, align-content, gap, margin: auto |
| Grid | grid-auto-flow: dense packing, grid-template-columns/-rows (lengths, %, fr, auto, min-content, max-content, minmax(), fit-content(), repeat() incl. auto-fill/auto-fit), grid-auto-rows/-columns, grid-auto-flow, grid-template-areas, grid-template, named lines ([name]), grid-column/-row (line numbers, names and span), grid-area (incl. area names), gap, justify-items/-self, align-items/-self, justify-content, align-content, place-* |
| Columns | column-count, column-width, columns, column-gap, column-rule (all border styles), column-span: all |
| Variables | custom properties (--name: value) and var(--name, fallback), anywhere including shorthands |
| Math functions | calc(), min(), max(), clamp(), round(), mod(), rem(), abs(), sign(), sin(), cos(), tan(), asin(), acos(), atan(), atan2(), pow(), sqrt(), hypot(), log() and exp() for lengths, numbers and angles, nested in any combination and mixing units (calc(100% - 2em), min(100%, 600px), clamp(1rem, 2.5vw, 2rem)), with var() inside them. Percentages resolve against the property's own reference (the containing block's width for width and margins, the parent's font size for font-size), so they work in widths, heights, margins, padding, flex bases, grid tracks, gaps, positions, translations, font sizes and borders |
| Positioning | float and clear; position (relative, absolute, fixed; sticky is drawn as relative) with top, right, bottom and left; z-index |
| Transparency | opacity (a block is painted as one PDF transparency group; an inline <span> fades its text and background), translucent colours everywhere (rgba(), hsla(), #rrggbbaa, transparent), gradients that fade to transparent (as a soft mask). PDF/A-2 and 3 allow all of this |
| Transforms | transform (translate(), translateX()/Y(), scale(), scaleX()/Y(), rotate(), skew(), skewX()/Y(), matrix()), transform-origin, and the individual translate, rotate and scale properties |
| Generated content | ::before, ::after and ::marker with content (strings, attr(), counter(), counters(), open-quote/close-quote, and for paged media target-counter(), target-text(), leader(), string() and content()), counter-reset, counter-increment, counter-set, string-set |
| SVG | fill, stroke, stroke-width, fill-opacity, stroke-opacity, fill-rule, stroke-linecap, stroke-linejoin, stroke-miterlimit, clip-path, clip-rule, mask, mask-type, filter, marker, marker-start/-mid/-end, flood-color, flood-opacity, color-interpolation-filters, text-anchor, dominant-baseline (as CSS or presentation attributes) |
| Lists | list-style-type (disc, circle, square, decimal, decimal-leading-zero, alpha, roman, none, or a string such as '— '), list-style, ::marker (content, colour, font) |
| Tables | border-collapse (each shared border drawn once, the wider one winning), border-spacing, cell vertical-align, automatic column widths, table-layout: fixed, a table height shared out over the rows |
| Paging | page-break-before/after/inside, break-before/after/inside (always, page, avoid), orphans, widows, @page size, margins and background, @page :first/:left/:right, the sixteen page-margin boxes (@top-center and the like), named pages (page), string-set (see Paged media) |
Units and colours
Units: px, pt, em, rem, %, mm, cm, in, pc, ex, ch, vw, vh, vmin, vmax (the viewport is
the page's content area, minus any running header and footer, in whole pixels as in Chrome). Colours: names, #rgb, #rrggbb,
#rrggbbaa, rgb(), rgba(), hsl(), hsla() (comma or space syntax), hwb(), lab(), lch(), oklab(),
oklch(), color() (sRGB, Display P3 and the other predefined spaces, mapped to sRGB), color-mix(),
light-dark() (the light value) and currentColor.
Pagination
Lines, images and table rows are never cut in half at a page boundary; table header rows repeat on
every page a table spans; backgrounds and borders continue across pages. Flex lines and grid rows move to the next
page as a whole when they don't fit. A paragraph that splits leaves at least orphans lines (default 2) at the bottom
of a page and carries at least widows lines (default 2) to the next. Headings keep with the content that follows
them (break-after: avoid in the default styles), and break-before/break-after: avoid does the same for any block.
break-inside: avoid keeps a block or a whole table on one page when it fits.
Links and bookmarks
<a href> becomes a clickable link, whether inline or a block (a card wrapped in a link),
and stays clickable on both pages when a page break splits it. External URLs open in the viewer's browser and #id
links jump to the element. Headings h1-h6 become the PDF's bookmarks, nested by level; set
PdfOptions.Bookmarks = false to leave them out.
SVG
Inline <svg> and SVG files (in <img> and as url() backgrounds, including data:image/svg+xml URIs) with path (all commands, arcs included), rect (incl. rounded), circle, ellipse, line,
polyline, polygon, text and tspan (x, y, dx, dy, text-anchor, dominant-baseline, direction,
registered fonts and right-to-left text),
g, use, nested svg, viewBox, preserveAspectRatio and transform, drawn as vector paths. linearGradient and
radialGradient (both units, gradientTransform, spreadMethod, href inheritance) become PDF shadings, and
pattern fills and strokes (both units, viewBox, patternTransform, href inheritance) become PDF tiling patterns.
clipPath clips the elements that reference it, and mask (luminance or alpha, both units) becomes a PDF soft mask.
marker draws arrowheads and dots at the vertices of paths, lines, polylines and polygons (orient incl. auto and
auto-start-reverse, markerUnits, viewBox, refX/refY, clipped to the marker unless overflow="visible").
filter is applied in pixels, at 144 dpi, and drawn as an image: feGaussianBlur, feOffset, feDropShadow,
feFlood, feMerge, feComposite (all operators), feBlend (separable modes), feColorMatrix,
feComponentTransfer and feMorphology, in linearRGB or sRGB. As in browsers, an SVG file is styled only by its own <style>
elements and attributes, not by the page's CSS, and loads nothing else.
Images
JPEG (embedded as-is, RGB, grayscale and CMYK), PNG (all colour types and bit depths, transparency,
interlacing), GIF (transparency, interlacing) and WebP (lossy, lossless and with alpha), from files, data: URIs or
your ResourceResolver. Animated GIF and WebP files show their first frame. SVG files are drawn as vectors (see SVG
above). Opaque PNGs are passed through without re-encoding. Images wider than the page are scaled down to fit.