TanStack

Marko Example: Dynamic

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Dynamic Virtualisation — @tanstack/marko-virtual</title>
    <style>
      * { box-sizing: border-box; margin: 0; padding: 0; }
      body { font-family: system-ui, sans-serif; padding: 24px; }
      h1 { font-size: 24px; margin-bottom: 8px; }
      p { color: #555; margin-bottom: 16px; font-size: 14px; line-height: 1.5; }
      .scroll-container { height: 400px; overflow-y: auto; border: 1px solid #e5e7eb; border-radius: 6px; }
      .item { padding: 10px 12px; font-size: 14px; border-bottom: 1px solid #f3f4f6; box-sizing: border-box; line-height: 1.5; }
      .item-even { background: #f9fafb; }
      .item-odd  { background: #ffffff; }
    </style>
  </head>
  <body>
    <h1>Dynamic Virtualisation</h1>
    <p>Item sizes are unknown at render time. Each rendered item is measured via measureElement.</p>

    <const/items = Array.from({ length: 1000 }, (_, idx) => ({
      id: idx,
      text: "Item " + idx + " — " + "lorem ipsum dolor sit amet ".repeat(1 + (idx % 5)),
    }))/>

    <div/scrollEl class="scroll-container">
      <virtualizer/v
        count=items.length
        estimateSize=() => 80
        getScrollElement=() => scrollEl()
      />
      <div style=`height: ${v.totalSize}px; width: 100%; position: relative`>
        <for|item| of=v.virtualItems>
          <div/itemEl
            data-index=item.index
            class=item.index % 2 === 0 ? "item item-even" : "item item-odd"
            style=`position: absolute; top: 0; left: 0; width: 100%; transform: translateY(${item.start}px)`
          >
            <script() {
              const _key = item.key
              const node = itemEl()
              if (node && v.measureElement) v.measureElement(node)
            }/>
            <strong>${items[item.index]!.id}.</strong> ${items[item.index]!.text}
          </div>
        </for>
      </div>
    </div>
  </body>
</html>