pm4ai

Minimal DOM

Fewest DOM nodes with React and Tailwind

Same UI, fewest DOM nodes — every element earns its place. If deleting it breaks nothing (semantics, layout, behavior, required styling), it must not exist.

MUST

  • Keep a node ONLY if it provides one of: semantics/a11y (ul/li, button, label, form, nav, section, ARIA, focus); a layout constraint (own containing block / positioning / clip / scroll / stacking — relative, overflow-*, sticky, z-*, min-w-0); behavior (measurement ref, observer, portal, event boundary, virtualization); or component API (can’t pass props/classes to the real root after trying as/asChild/forwarding). Why: every node is render + memory cost.
  • Spacing via parent gap-* (flex/grid) or space-x/y-*. Why: no wrapper for gaps.
  • Separators via parent divide-y/divide-x. Why: no separator elements.
  • Alignment via flex/grid on the existing parent. Why: no alignment wrapper.
  • Visual (padding/bg/border/shadow/radius) on the element that owns the box. Why: no decoration wrapper.
  • Group JSX with <>...</> fragment, not <div>. Why: zero DOM cost.
  • Style mapped components by passing className to the item; uniform direct children via *: or [&>tag]:. Why: props first, selectors second — no repeat-class wrapper.

NEVER

  • Add a wrapper a gap/space/divide/className/[&>...]: could replace. Cost: dead node, render + read budget.

Examples

Good (selector pushdown)Bad (repeated classes)
<div className='divide-y [&>p]:px-3 [&>p]:py-2'><div className='divide-y'> with px-3 py-2 on each <p>

Pitfall

  • Selector tools: *: direct children · [&>li]:py-2 targeted · [&_a]:underline descendant (sparingly) · group/peer on existing nodes → group-hover:*/peer-focus:* · data-[state=open]:*/aria-expanded:*/disabled:* · first:/last:/odd:/even:/only: structural.
  • Review each node: can I delete it → delete; can gap/space/divide replace it → do it; can I pass className → do it; can [&>...]: remove repetition → do it.

On this page