Limitations
Changed in 1.22.0: Text and fonts, CSS.
PdfPecker is built for fast conversion of HTML templates you control, not for rendering arbitrary web pages. These are the known gaps; most are scope choices for speed and size, and they are the first candidates for future work. Anything not listed in What is supported should be assumed missing; CSS support marks every CSS property one by one. The PDF feature checklist marks every PDF feature as supported, partly supported or missing.
By design
- No JavaScript. Scripts are never run, so content must be in the HTML before conversion (render it server-side first).
- No network access:
http:/https:stylesheets and images are not downloaded. Supply them through yourResourceResolver, as files underBaseDirectory, or asdata:URIs. <canvas>,<iframe>,<video>and<audio>are not drawn,<object>and<embed>show only pictures, and file, range, colour and image inputs are not drawn. Form fields have no JavaScript (no calculations, formats or submit actions), and a field inside a transformed box, a running header or footer, or aposition: fixedbox is drawn but not fillable.
Text and fonts Changed in 1.22.0
- Without registered fonts or
EmbedStandardFonts, text uses the standard PDF fonts, so characters are limited to the Windows-1252 set (Western European languages) plus what the built-in fallback fonts add: Central European, Greek and Cyrillic letters and common symbols. They have no CJK or other scripts, and no emoji: register fonts for those. - Complex-script shaping covers Arabic and Hebrew (and other scripts written with Arabic letters, such as Persian and Urdu), nine Indic scripts, Thai and Lao. Khmer, Myanmar, Sinhala, Tibetan, Mongolian, Javanese, Adlam and Syriac are not shaped, so their vowel signs and conjuncts come out wrong. Thai and Lao text breaks only at spaces, since there is no dictionary for word breaks.
- Vertical text is drawn as turned horizontal text: Chinese and Japanese characters
are turned rather than upright (
text-orientationandtext-combine-uprightare not supported), tables and images inside vertical text are turned with it (Chrome keeps images upright and lays tables out vertically), and a verticalhtmlorbodyis laid out horizontally.viandvbstay the page width and height in vertical boxes (Chrome swaps them), andinitial-lettermakes no drop cap in a vertical box. - CJK punctuation trimming does not use the vertical
vhalfeature, and thetext-spacingshorthand is not read.hanging-punctuationis not supported. - In Latin and other simple scripts, shaping is limited to kerning, standard ligatures and features that swap one
glyph for another (see OpenType features) and fractions; contextual alternates
(
calt) and ordinals are not applied, andsmall-capsis synthesized from scaled capitals when the font has no small capitals of its own.font-variant-alternatesandfont-paletteare not supported, so colour fonts use their default palette. - Solid underlines, overlines and line-throughs are a little thinner than Chrome's (about 1.5 px for 20 px text where
Chrome draws 2 px), and a solid overline sits about a pixel lower; dashed, dotted, double and wavy lines match Chrome.
text-decorationon SVG text is always a solid line in the text's fill, and is not drawn ontextPathtext. - Automatic hyphenation (
hyphens: auto) has built-in patterns for English, Danish, German, Dutch, Norwegian, Swedish, Spanish, French, Italian, Portuguese and Polish; other languages need their patterns inPdfOptions.Hyphenation. - SVG
<text>uses only the first value of position lists; in a text chunk with right-to-left text,dxon itstspans is ignored.
CSS Changed in 1.22.0
- Container queries: no
scroll-state()queries,style()works only on custom properties, and style containment (counter scoping) and thecontainproperty are not implemented. A document with container queries takes about two to four times as long to lay out, and queries that keep changing the layout stop after six passes. In running headers and footers,@pagemargin boxes and SVG images, thecqunits fall back to viewport units. - Footnotes:
@footnoteinside@page :first,:leftor:rightis ignored,footnote-policy: blockacts likeline, andfootnote-display: compactis always inline. A note split across pages does not carry its background or border onto the next page, and margins between block notes do not collapse. - When
@page :first,:leftor:rightgive pages different widths, floats, inline-blocks, flex, grid and multi-column containers, and boxes with transforms or filters keep the width of the page they start on (Chrome re-sizes floats, inline-blocks and multi-column per page). A named page's:firstis the document's first page, as in Chrome, not the first page of the named run. - Selectors: a rule with an unsupported selector is skipped. A complex selector may have at most 64 compound parts and
16 levels of nesting, and
:has()cannot contain:has(). - Blurred text shadows are drawn as images at 144 dpi (down to 72 dpi for wide blurs, with the blur capped at about
200px), so shadowing long body text adds to the file size; the shadow of an underline is painted under the glyphs
rather than between them and their own underline.
filter: blur()anddrop-shadow()draw the box as an image; its text stays selectable, and the colour filters keep everything as vectors. text-overflowapplies only at the end of the line, as in the spec and Chrome.- Background images on the
@pagebox are positioned in the page box, as CSS Paged Media 3 says; Chrome sizes that area like the root element, soright,bottomand percentage positions can land elsewhere than in Chrome. inline-size,block-sizeand theirmin-andmax-forms always mean width and height, also in vertical writing modes; the logical margins, paddings, insets and borders do followwriting-mode.- Percentage heights still count as
autoin a flexed item of a container that has only amin-height, against a table row's height on its own, and in footnotes and running headers and footers. When pages differ in size, a box resolves its percentage height against the page it starts on and keeps that height if it breaks onto a page of another height (Chrome recomputes it there). background-attachment: fixedplaces images against the paper, as Chrome prints them, but gradients still move with their box.- Not supported:
contain,content-visibility,cross-fade(),element(),paint(),env(),anchor(),attr()outsidecontent,::selectionand:nth-col(). In@pagemargins and media queries,ex,chand the other font units use the initial 16 px font. - 3D transforms are drawn flat, since a PDF page has only flat transforms: a box with
a perspective stays a rectangle or parallelogram where Chrome draws a trapezoid, only the parent's
perspectivecounts, and nestedpreserve-3dscenes, such as a cube, do not come out the way a screen shows them. backdrop-filterdraws what is behind the box as a 144 dpi image, up to 64 per document. A mask with more than 16 layers is ignored, andmask-clip: no-clip,stroke-boxandview-boxact asborder-box.- Float shapes: an SVG image in
shape-outsidefalls back to the margin box, and image and path shapes are measured at 1 px per CSS pixel, up to 4 million pixels and ashape-marginof 1,024 px (beyond that the float keeps its rectangle). text-wrap: balanceandprettydo not apply beside floats, with::first-line, or on pages of different widths.display: contents: a link to theidof such an element finds no place on the page when its children are blocks, and in a tagged PDF the wrapper's own tag (a list or link around blocks) is left out; its children are tagged.- Gradient stops that fade to transparent are mixed in unpremultiplied colours, so the middle of such a gradient is a little greyer than in Chrome.
- A document without a doctype reads lengths without a unit as pixels and takes Chrome's quirks-mode line heights, but is otherwise laid out in standards mode; Chrome's quirks mode also, among other things, ignores the first paragraph's top margin in the body.
Backgrounds and transparency
- Inset box shadows of inline elements (
<span>) are not drawn.box-decoration-breakapplies to inline elements, not to blocks split across pages or columns. - Inline boxes nested more than 16 deep are not decorated, and one layout paints at most 50,000 inline box fragments with a shared budget for their layers, shadows and outlines; past it, fragments show only their background colour.
- A translucent box shadow without blur is blended onto white rather than truly see-through. Blurs are drawn as bands, so very wide blurs may show faint steps when zoomed in.
Layout
- Subgrid: percentage gaps, margins and padding on a subgrid resolve against the parent
grid's width rather than the subgrid's area; subgrid items are not baseline-aligned with the parent's items; and only
the horizontal
writing-modeis supported. - Multi-column:
column-span: allworks only on direct children of the multi-column box, and multi-column boxes nested more than two levels deep keep their children whole instead of splitting them. Footnotes inside columns are placed at their call and do not reserve space at the bottom of the column, orphans and widows are not applied to lines beside floats, and content that overflows a fixed-height multi-column box withoverflow: hiddenis clipped from view but stays in the PDF's text. - Overflow: a positioned child with a
z-indexinside a clipping box stays stacked within that box. - Collapsed table borders on
colandcolgroupare not drawn; borders on cells, rows, row groups and the table are. - A table row with a cell that spans rows moves to the next page whole rather than breaking inside, as other rows do.
Images and SVG
- No AVIF images: decoding them needs an AV1 video decoder, which is not planned. Convert them to WebP, PNG or JPEG.
- SVG filters are applied in pixels at 144 dpi, so filtered shapes become an image (text keeps an invisible, selectable copy).
- A missing image with alt text shows the text without Chrome's small broken-image icon, and a missing image without alt text or a size has no box rather than Chrome's 16 px icon box.
- An SVG
symbolis not clipped to its viewport, and itspreserveAspectRatiois always the default (xMidYMid meet). - A
foreignObjectinside an SVG group with a clip, mask or filter is drawn over the drawing without those effects, and auseelement's ownfillandstrokereach the content it draws only throughcontext-fillandcontext-stroke.
Reading and changing existing PDFs
- Text extraction reads columns that sit side by side across, line by line, rather than one
column after the other, and it does not use the structure tree of a tagged PDF to find the reading order. Text drawn
only as outlines or images is not extracted; there is no OCR. Indic vowel signs drawn before their consonant come
out in that visual order unless the PDF carries
/ActualText. - PDF to HTML in its visual mode keeps the PDF's layout: the page is an image and the text an invisible layer over it, so text zooms as an image does, and what text extraction cannot read (outlines, scans) cannot be selected either. The structured mode reads an untagged PDF's structure from its layout, so unusual layouts, floats and charts can come out as plain paragraphs, and text of cards side by side in one row can run together.
- Form filling does not shape text, so values in Arabic, Hebrew, Devanagari and other scripts that need shaping are stored but not drawn correctly. XFA forms are not filled: their XFA data is removed and the AcroForm fields are filled instead. Field JavaScript (calculations, formats) is not run.
- Signature verification checks the changes made after a
certification signature against its level, but not field locks
(FieldMDP), so after an approval signature it counts the updates but cannot tell an allowed form fill from a changed
page. Revocation is checked only when
RevocationModeasks the platform to, not from the OCSP responses and CRLs stored in the PDF.
Markdown and the PDF renderer
- Markdown: no math. Definition list terms are one line each (no several terms for one definition), and
~does not start a definition. A footnote's text cannot hold another page-bottom footnote: a reference inside a footnote links to its note, and a note that only other notes reference is listed after the text. PdfRenderer(PDF to image): no predefined CJK CMaps or non-embedded CJK fonts, and ICC profiles are not applied (ICC-based colours use their device equivalents). WebP output is lossless only (no lossy VP8), and JPEG output is baseline only (no progressive or arithmetic coding).