Lattice Grid Buy a licence

demo D131

Auto row height in htmx

Wrapped text measured per row, and the ceiling where it degrades

autoHeight: true | 'visible'

This grid grows each row to fit wrapped text that would otherwise be clipped, measured per row. It suits a dataset with free-text fields like notes, so a long entry reads in full while short rows stay compact, with a stated ceiling where it degrades.

Building…
Loading a live grid…

This is the htmx version. A server-rendered table is upgraded in place, so the page is readable before any script runs and gains the full grid when the module loads, which suits a progressively enhanced app.

The configuration

<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">

<!-- A real, server-rendered table: readable with JavaScript off. data-field on
     each header names the column that cell becomes, and data-id on each row is
     the key the grid carries it under. -->
<table id="auto-row-height-table" data-lattice-grid>
  <thead>
    <tr>
      <th data-field="circuit">Circuit</th>
      <th data-field="raised">Raised</th>
      <th data-field="summary">Summary</th>
      <th data-field="owner">Owner</th>
    </tr>
  </thead>
  <tbody>
    <tr data-id="note-0"><td>CKT-76234</td><td>2026-01-31</td><td>Scheduled maintenance overran its window, while the customer was kept updated on the half hour, after the vendor pushed a firmware revision without notice. Root cause is confirmed and the fix is permanent.</td><td>S. Bergström</td></tr>
    <tr data-id="note-1"><td>CKT-48786</td><td>2026-02-25</td><td>Cross-connect was found patched to the wrong panel port, with the affected prefixes withdrawn until the session stabilised, while the standby route absorbed the load without customer impact, and a replacement module was dispatched to site the same evening, which the monitoring system recorded but did not escalate, so the change was rolled back and rescheduled for the next window, and the on-call engineer was paged eleven minutes later.</td><td>M. Haddad</td></tr>
    <tr data-id="note-2"><td>CKT-45840</td><td>2026-01-19</td><td>Scheduled maintenance overran its window, and the protection path carried traffic for the duration, so the change was rolled back and rescheduled for the next window, and the on-call engineer was paged eleven minutes later, so the change was rolled back and rescheduled for the next window. Monitoring thresholds have been tightened as a result.</td><td>K. Moreau</td></tr>
    <!-- the rest of the rows, rendered by your server -->
  </tbody>
</table>

<script type="module">
  import { hydrateTable } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/htmx.esm.min.js';

  // The markup carries the rows; a server-rendered table's column types are
  // declared in the config hydrateTable takes. The grid replaces the table
  // where it stood.
  const grid = hydrateTable(document.getElementById('auto-row-height-table'), {
    selection: 'multiple',
    toolPanel: {
      side: 'left',
      panels: ['columns', 'filters', 'views', 'quick'],
      actions: ['undo', 'redo', 'export', 'restore', 'maximise'],
      exportName: 'lattice-demo',
    },
    autoHeight: 'visible',
    columns: [
      { field: 'circuit', title: 'Circuit', layout: { width: 140, pin: 'start' } },
      { field: 'severity', title: 'Severity', filter: { type: 'set' }, layout: { width: 130 },
        cell: { decoration: 'pill', variant: {
          map: { critical: 'danger', major: 'warning', minor: 'info', info: 'neutral' },
        } } },
      { field: 'raised', title: 'Raised', type: 'dateString', layout: { width: 130 } },
      { field: 'summary', title: 'Summary', layout: { flex: 1, min: 320 },
        cell: { wrap: true, autoHeight: true } },
      { field: 'owner', title: 'Owner', filter: { type: 'set' }, layout: { width: 160 } },
    ],
  });
</script>

Auto row height for wrapped text in a JavaScript data grid

Auto row height lets a row grow to fit content that would otherwise be clipped, most often a text column carrying a sentence or a paragraph rather than a short label. Reach for it when a dataset mixes free-text fields, such as notes or descriptions, with the usual short values, and a fixed row height would truncate the long ones. The option is autoHeight, set to true to measure every row up front or to 'visible' to measure only rows as they enter the viewport under virtual scrolling, which keeps the initial layout pass proportional to what is on screen rather than to the full row count.

Each row’s height comes from measuring its wrapped content against the column widths in play, so a resize or a column width change that alters wrapping is followed by a re-measure. This costs more than a fixed row height, because the grid cannot assume a uniform height when it works out which rows fall in the current scroll window, and the demo shows the ceiling: past a certain row count, per-row measurement in 'visible' mode still holds up, but true mode’s up-front pass adds a measurable delay before first paint. Assistive technology reads the resulting row as one unit regardless of how many lines it wraps to, so aria-rowindex stays correct even as heights vary row to row.

Does auto row height work with virtual scrolling in a JavaScript data grid?

Yes. Setting autoHeight: 'visible' measures each row’s wrapped height only as it scrolls into view, so the grid does not pay for measuring off-screen rows. autoHeight: true measures every row up front instead, which is simpler to reason about but scales with the full row count rather than the viewport.