Joy DOM

Migrating from HTML

Adapt an HTML+CSS page to the Joy DOM subset.

Joy DOM is HTML-shaped but smaller. If you already have an HTML page you want to render natively across platforms, the migration is mostly subtraction.

What to keep

  • Block structure. div, span, p, h1h6, and img map directly. Every other tag becomes a custom node.
  • Class names. The selector model is the same - type, class, id.
  • Flexbox. Joy DOM is flexbox-first; layouts that work in flex translate cleanly.
  • Media-query thinking. Joy DOM breakpoints are media-query-like; same patterns apply.

What to translate

HTML/CSSJoy DOM
Tag soup (section, article)div with a meaningful className. Custom nodes if you need a distinct render path.
display: block (the default)Explicit display: "flex". There is no default in Joy DOM - see §4.4.
display: gridUse nested flex containers. Grid is not supported yet.
position: fixedNot supported. Use absolute positioning relative to a containing block.
CSS variablesNot supported. Repeat values, or generate the JSON.
Pseudo-classes (:hover)Not supported. Use custom components to attach interaction.
Media queries (@media)Breakpoints. See §6.
calc()Not supported. Compute values when you generate the JSON.
transformNot supported.
rgba() for transparencyopacity plus a hex color. See §5.7.2.

What to drop

  • All scripting tags. Joy DOM has no scripting - register custom components for behavior.
  • Inline event handlers. Same - custom components.
  • <style> blocks. Styles live in the document's style field.
  • Layout via floats or positioning hacks. Use flex.

Worked example

A typical HTML card:

<div class="card">
  <h1 class="title">Hello</h1>
  <p class="body">Static paragraph.</p>
</div>

Translated:

{
  "version": 1,
  "style": {
    ".card": {
      "display": "flex",
      "flexDirection": "column",
      "gap": {
        "value": 8,
        "unit": "px"
      },
      "padding": {
        "value": 16,
        "unit": "px"
      }
    },
    ".title": {
      "display": "flex",
      "fontSize": {
        "value": 24,
        "unit": "px"
      },
      "fontWeight": "bold"
    },
    ".body": {
      "display": "flex"
    }
  },
  "breakpoints": [],
  "layout": {
    "type": "div",
    "props": {
      "className": ["card"]
    },
    "children": [
      {
        "type": "h1",
        "props": {
          "className": ["title"]
        },
        "children": ["Hello"]
      },
      {
        "type": "p",
        "props": {
          "className": ["body"]
        },
        "children": ["Static paragraph."]
      }
    ]
  }
}

The biggest gotcha is always display: "flex" - HTML doesn't make you set it on block elements. Joy DOM does. See §4.4.

Tooling

An automated HTML → Joy DOM converter is not shipped today. For now, port pages by hand; the structure tends to translate cleanly and the exercise surfaces which parts of the page relied on non-portable CSS.

Where next

On this page