Skip to content

CSS support in PdfNetStack.Html

Since 1.1View as Markdown

What the converter reads, module by module. A property it does not know, or a value that does not match the property’s grammar, is dropped as browsers drop it, and the rest of the rule still applies.

PdfNetStack.Html implements the CSS a print template needs: the cascade, Selectors Level 4, block, inline, table, flex and grid layout, floats, positioning, paged media, web fonts, backgrounds, borders, shadows and transforms. It has no multi-column layout, no vertical writing modes and no JavaScript.

const string Css = """
:root { --accent: oklch(0.55 0.2 260); --gap: 10pt }
body { font-family: sans-serif; font-size: 9.5pt; color: #0f172a }
h1 { font-size: clamp(16pt, 4vw, 24pt); color: var(--accent); margin: 0 0 8pt }
.page { display: grid; grid-template-columns: 140pt 1fr; grid-template-areas: "side main" "foot foot";
gap: var(--gap) }
aside { grid-area: side; padding: 8pt; border-radius: 6pt;
background: radial-gradient(circle at top left, #dbeafe, #ffffff) }
main { grid-area: main }
footer { grid-area: foot; border-top: 1pt dashed #94a3b8; padding-top: 4pt; color: #64748b }
.cards { display: flex; flex-wrap: wrap; gap: var(--gap) }
.card { flex: 1 1 120pt; padding: 8pt; border: 1pt solid #cbd5e1; border-radius: 6pt;
box-shadow: 0 2pt 4pt rgb(15 23 42 / 0.15) }
.card:nth-child(2 of .card) { border: 3pt double var(--accent) }
.card :is(h3, h4) { margin: 0 0 4pt; text-transform: uppercase; letter-spacing: 0.05em }
.figure { float: right; width: 90pt; margin: 0 0 6pt 8pt; position: relative }
.badge { position: absolute; top: -6pt; right: -6pt; padding: 2pt 4pt; color: white;
background: #dc2626; border-radius: 4pt; transform: rotate(8deg) }
.note { width: calc(100% - 20pt); text-decoration: underline wavy #f59e0b }
.gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(60pt, 1fr));
grid-auto-flow: row dense; gap: 4pt; margin: 6pt 0 }
.gallery div { background: #e0e7ff; padding: 4pt; border-radius: 3pt }
.gallery .wide { grid-column: span 2; background: #c7d2fe }
.specs { display: grid; grid-template-columns: [label] max-content [value] 1fr; column-gap: 8pt }
.specs > div { grid-column: label / -1; display: grid; grid-template-columns: subgrid;
border-bottom: 0.5pt solid #cbd5e1 }
.specs b { grid-column: label }
ol.steps { counter-reset: step; list-style: none; padding: 0 }
ol.steps li { counter-increment: step; margin-bottom: 3pt }
ol.steps li::before { content: "Step " counter(step) ": "; font-weight: bold; color: var(--accent) }
li:not(:last-child) { color: #334155 }
""";

A page laid out with a grid: a sidebar with a radial gradient, three cards in a wrapping flex row, a floated figure with a rotated badge, a grid gallery with a spanning item, a subgrid table and numbered steps

FeatureSupport
Origins, specificity, order, !importantYes
Inheritance, inherit, initial, unset, revertYes
Custom properties and var() with fallbacksYes, expansion bounded
calc(), min(), max(), clamp()Yes
Lengthspx, pt, pc, cm, mm, q, in, em, rem, ex, ch, lh, vw, vh and the other viewport units, percentages
ColorsNamed colors, hex, rgb(), hsl(), hwb(), lab(), lch(), oklab(), oklch(), currentcolor, transparency
style attributeYes
Legacy attributesalign, bgcolor, width, cellpadding, cellspacing, border, font
FeatureSupport
Type, class, id, universalYes
Attributes[a], =, ~=, `
CombinatorsDescendant, >, +, ~
Logical:is(), :where(), :not() with selector lists
Structural:first-child, :last-child, :only-child, the -of-type forms, :nth-child(), :nth-last-child() with of S, :nth-of-type(), :nth-last-of-type(), :root, :empty
Other:lang(), :dir(), :link, :any-link, :checked, :disabled, :enabled, :required, :optional, :read-only, :read-write
Pseudo-elements::before, ::after, ::marker
Not supported:has(), ::first-line, ::first-letter. Interactive states such as :hover never match in print
RuleSupport
@mediaYes, as print, with the page’s width, height and orientation
@importYes, with media conditions, nesting and count bounded
@font-faceYes: TrueType, OpenType, WOFF and WOFF2, local(), weight ranges and styles
@pageYes: sizes, margins, margin boxes, :first, :left, :right, named pages. See Paged media
@supports, @keyframes, @layer and othersSkipped
ModeSupport
BlockMargin collapsing, box-sizing, min and max sizes, overflow clipping
InlineUnicode line breaking, text-align with justify, text-indent, white-space, vertical-align (every value), soft hyphens, hyphens, overflow-wrap, word-break
Floatsfloat, clear, text wrapping around floats
Positioningrelative, absolute, fixed (repeated on every page), z-index in stacking order: positioned boxes, flex and grid items with a z-index, and boxes with opacity below one or a transform start a stacking context; a negative z-index paints under the context’s content
TablesBoth border models, rowspan and colspan, fixed and automatic widths, captions, header and footer groups, header rows repeated on every page
FlexboxDirection, wrap, gap, grow, shrink and basis, justify-content, align-items, align-self, align-content, auto margins, order
Gridfr, auto, min-content, max-content, minmax(), repeat() with counts, auto-fill and auto-fit (empty tracks collapse); line names in track lists and repeat(), placement by line, name, span name and named areas with their -start and -end lines; implicit tracks on both sides; grid-auto-flow with row, column and dense; subgrid on rows, columns or both; the grid-template and grid shorthands; alignment
Otherinline-block, inline-flex, inline-grid, flow-root, display: contents, display: none, list items with markers
Not supportedMulti-column layout, vertical writing modes
FeatureSupport
Font selectionfont-family lists, font-weight, font-style, font-size keywords and lengths, the font shorthand
ShapingKerning, ligatures, Arabic joining and vowel marks, Indic scripts, Unicode normalization, matching HarfBuzz on the fonts compared in tests
Directiondirection, unicode-bidi, dir, with the Unicode bidirectional algorithm
Spacing and caseletter-spacing, word-spacing, text-transform, line-height, tab-size
Decorationtext-decoration underline, overline and line-through, in solid, double, dotted, dashed and wavy, with color and thickness; text-shadow without blur
Not supportedfont-variant-*, font-feature-settings, font-stretch, hyphenate-character, hyphenate-limit-chars, text-overflow

hyphens: auto hyphenates text in the language of the nearest lang attribute, as long as HtmlConverterOptions.Hyphenators finds patterns for it. Without that option, or without a lang, auto behaves like manual, which is what happened before and stays the default. Add the PdfNetStack.Hyphenation package for the patterns:

// In HTML: hyphens: auto, the language from the nearest lang attribute, and a way to find its patterns.
byte[] pdf = HtmlConverter.ConvertToPdf(
"""<html lang="fr"><body style="hyphens: auto; text-align: justify; width: 200px"><p>Le développement de la bibliothèque.</p></body></html>""",
new HtmlConverterOptions { Hyphenators = PdfHyphenationPatterns.ForLanguage });
File.WriteAllBytes("hyphenation-html.pdf", pdf);

hyphens: none also turns off soft hyphens. Text under white-space: nowrap or word-break: break-all is not hyphenated, and a word split across inline elements counts as one. Min-content sizes count the points, so a narrow table column can hyphenate instead of overflowing. Words are judged as written: text-transform: uppercase over lower case text hyphenates, and text written in capitals does not. That transform writes the German sharp s as SS. See Hyphenation for the languages and the words left alone.

FeatureSupport
contentStrings, attr(), counter(), counters(), quotes, url() images
Counterscounter-reset, counter-increment, counter-set, nested counters
List stylesdisc, circle, square, decimal, decimal-leading-zero, roman, alphabetic, lower-greek, arabic-indic, persian, devanagari and others; list-style-position; list-style-image
FeatureSupport
BackgroundsColors, images, linear-gradient() and radial-gradient(), several layers, background-position, size, repeat, origin and clip
BordersWidths, colors, rounded corners with elliptical radii; solid, dashed, dotted and double styles. groove, ridge, inset and outset are drawn flat
Shadows and outlinesbox-shadow with approximated blur (inset shadows are not drawn), outline with outline-offset
Effectsopacity (applied per element), visibility, 2D transform (translate, scale, rotate, skew, matrix) with transform-origin
Imagesobject-fit, object-position
Not supportedfilter, clip-path, mix-blend-mode, conic and repeating gradients, 3D transforms
FeatureSupport
Breaksbreak-before, break-after, break-inside, the legacy page-break-* properties, orphans, widows
Named pagespage on any block in the block flow; a change of page name forces a break. No effect inside flex, grid and table containers
Running contentstring-set and string(), position: running() and element(), counter(page) and counter(pages)
Bookmarksbookmark-level and bookmark-label; headings get levels by default
Not supportedtarget-counter(), leader(), footnotes
  • No JavaScript: pages must be rendered HTML, not built in the browser.
  • Images: JPEG, PNG, GIF, BMP, TIFF and WebP (the first frame of animations), and SVG without filters, masks or patterns.
  • An inline running element shows on every page rather than from where it stands.
  • font-weight and font-variation-settings do not choose a variable font instance yet; that is on the roadmap.

Questions

Does PdfNetStack.Html support flexbox and CSS grid?
Yes. Flexbox with wrap, gap, grow, shrink, alignment and order, and grid with fr tracks, minmax(), repeat() with auto-fill and auto-fit, named areas and lines, row and column auto-placement with dense packing, and subgrid.
Are @supports, @keyframes and animations supported?
No. Rules that only matter on screen, such as @keyframes and @supports, are skipped. Print layout does not need them.