openpencil/packages/docs/reference/dom-css-mapping.md
Danila Poyarkov 9bc353587f
refactor!: generate Tailwind JSX through dom-css (#763)
* refactor!: generate Tailwind JSX through dom-css

Core kept its own SceneGraph → Tailwind mapper next to the one dom-css
uses for Tailwind HTML, and the two drifted: HTML export turned grid
frames into flex columns and dropped rotation, inner shadows, blur, and
flex grow, while Tailwind JSX had them.

Tailwind JSX is now printed by dom-css from the same CSS projection as
HTML export, with esrap building the JSX and string literals carrying
text or attributes that JSX would otherwise reinterpret. The projection
gains grid layout and placement, rotation, every shadow, layer and
background blur, flex grow, right-to-left direction, and sections, and
writes opaque colors as hex so Tailwind can match its palette.

BREAKING CHANGE: `sceneNodeToJSX` and `selectionToJSX` in
`@open-pencil/core` no longer accept a format, and `JSXFormat` and
`JSXExportOptions` are removed. Use `sceneNodesToTailwindJSX` from
`@open-pencil/dom-css` or `@open-pencil/dom-css/browser`.

* fix(dom-css): keep backslashes and line breaks in Tailwind JSX attributes

JSX attribute strings keep backslashes literally, but the printer
escapes backslashes and line breaks in string literals, so a layer
named `a\b` came back as `a\\b`. Such values are now written as
expression containers, like values containing quotes or `&`.
2026-09-26 10:50:28 +04:00

5.2 KiB

DOM/CSS mapping reference

OpenPencil maps browser-computed DOM/CSS styles into SceneGraph fields through @open-pencil/dom-css. Browser adapters should use native DOM/CSSOM and getComputedStyle() as the source of truth. Headless conversion is an approximation for tests and CLI usage.

Layout

CSS SceneGraph Notes
display: flex / inline-flex layoutMode flex-direction: row maps to horizontal; column maps to vertical.
justify-content primaryAxisAlign Supports start, center, end/flex-end, and space-between.
align-items counterAxisAlign Supports start, center, end/flex-end, stretch, and baseline.
align-self layoutAlignSelf Supports start, center, end/flex-end, stretch, and baseline.
flex-wrap: wrap layoutWrap: WRAP Counter-axis spacing is preserved when gaps are available.
gap, row-gap, column-gap itemSpacing, counterAxisSpacing Axis-aware: row and column gaps swap meaning for column flex direction.
padding-* paddingTop/Right/Bottom/Left Browser-computed physical values are preferred.
position: absolute/fixed, left, top layoutPositioning, x, y Right/bottom constraints are not mapped yet.
overflow: hidden/clip clipsContent Other overflow values are ignored.
width, height, min/max sizes node size constraints Browser-computed pixel values are preferred.
aspect-ratio fallback width/height sizing Used when one axis is available and the other is auto/missing.

Paint, stroke, and effects

CSS SceneGraph Notes
background-color solid fill Transparent values are ignored.
border-color, border-*-color stroke color First available border color is used.
border-width, border-*-width stroke weight / independent stroke weights Side-specific widths set independent stroke weights.
border-style: dashed/dotted dashPattern Unsupported border styles fall back to solid.
border-radius, border-*-radius corner radii Independent corners are preserved when sides differ.
opacity node opacity Numeric computed value.
box-shadow drop shadow First simple outer shadow only; complex shadow lists require maintained parser or browser-computed support before mapping.
<img src="data:..."> image fill Data URL images are stored in the graph image map.
<img src="https://..."> preserved source URL metadata External URL fetching is not performed; the URL is retained for HTML round-trip.
object-fit: contain/cover image FIT / FILL scale mode scale-down maps to FIT; other object-fit values are not mapped yet.

Text

CSS SceneGraph Notes
color text fill Uses core color parsing.
font-family fontFamily Uses first family token.
font-size fontSize Pixel/rem-ish numeric values.
font-weight fontWeight Numeric values.
font-style: italic italic Other styles ignored.
line-height lineHeight Numeric computed values.
letter-spacing letterSpacing Numeric computed values.
text-align horizontal text alignment Supports center, right, justified; defaults left.
text-decoration-line underline / strikethrough Decoration style/thickness are not mapped yet.
text-transform textCase Uppercase, lowercase, and capitalize map to SceneGraph text case.
white-space: nowrap maxLines = 1 Other white-space values are not mapped yet.
text-shadow drop shadow effect Simple shadows only.

Export

HTML export, Tailwind HTML, and Tailwind JSX (sceneNodesToTailwindJSX) share one SceneGraph → CSS projection; Tailwind classes are derived from that CSS.

SceneGraph CSS Notes
auto layout display: flex, flex-direction, gaps, padding Row direction is the default and is not written.
grid layout display: grid, grid-template-*, gaps Equal 1fr tracks use repeat(N, minmax(0, 1fr)).
grid child position grid-column, grid-row, *-start Spans are written before starts.
layoutGrow in auto layout flex-grow: 1
rotation transform: rotate() Rotates around the element center.
drop and inner shadows box-shadow Every visible shadow, in order; inner shadows use inset.
layer / background blur filter / backdrop-filter: blur()
right-to-left layout or text direction: rtl
section <section>
colors hex, or rgba() when translucent Hex lets Tailwind match its palette.

Browser-oracle but not mapped yet

These values are collected or covered by browser oracle tests but do not yet have a stable SceneGraph mapping:

  • complex gradients
  • CSS filters
  • multi-shadow lists
  • media-query-specific provenance
  • pseudo-elements

Headless limitations

The headless runtime uses maintained parsers for HTML (parse5) and stylesheets/inline declarations (@acemir/cssom), but still has limited approximations for selector matching, shorthand expansion, calc(), and simple shadows. Do not expand those with ad hoc parsers; prefer browser getComputedStyle() oracle coverage or maintained parser dependencies for new CSS behavior.