Lattice Grid Buy a licence

demo D115

Density in htmx

compact through spacious, with the row height following the token

density: 'comfortable'

This grid switches row density from compact to spacious, with the row height following a single token. It lets a reader trade detail for how many rows fit on screen, the setting most people reach for first, from one control.

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">

<div id="controls" style="display: flex; gap: 8px; margin-bottom: 10px"></div>
<!-- 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="density-table" data-lattice-grid>
  <thead>
    <tr>
      <th data-field="service">Service</th>
      <th data-field="team">Team</th>
      <th data-field="owner">Owner</th>
      <th data-field="region">Region</th>
      <th data-field="active">Active</th>
      <th data-field="deprecated">Deprecated</th>
      <th data-field="version">Version</th>
    </tr>
  </thead>
  <tbody>
    <tr data-id="1"><td>svc-00001</td><td>Search</td><td>k.yilmaz</td><td>Malmö</td><td>false</td><td>false</td><td>1.2.10</td></tr>
    <tr data-id="2"><td>svc-00002</td><td>Mobile</td><td>m.svensson</td><td>Leeds</td><td>true</td><td>false</td><td>2.3.6</td></tr>
    <tr data-id="3"><td>svc-00003</td><td>Identity</td><td>j.okafor</td><td>Zürich</td><td>true</td><td>false</td><td>1.11.1</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('density-table'), {
    selection: 'multiple',
    // The starting spacing. Four are built in: compact, standard, comfortable
    // and spacious.
    density: 'standard',
    columns: [
      { field: 'service', title: 'Service', layout: { pin: 'start', width: 140 } },
      { field: 'team', title: 'Team', filter: { type: 'set' } },
      { field: 'owner', title: 'Owner', filter: { type: 'set' } },
      { field: 'tier', title: 'Tier', cell: { decoration: 'pill', variant: { map: { gold: 'warning', silver: 'neutral', bronze: 'info' } } } },
      { field: 'state', title: 'State', cell: { decoration: 'dot', variant: { map: { healthy: 'success', degraded: 'warning', failing: 'danger', unknown: 'neutral' } } } },
      { field: 'region', title: 'Region', filter: { type: 'set' } },
      { field: 'active', title: 'Active', type: 'boolean' },
      { field: 'deprecated', title: 'Deprecated', type: 'boolean' },
      { field: 'version', title: 'Version', layout: { width: 100 } },
    ],
  });

  // Switch the spacing live on the one grid. grid.set('density', ...) is the
  // same runtime setter behind every option.
  const controls = document.getElementById('controls');
  for (const value of ['compact', 'standard', 'comfortable', 'spacious']) {
    const button = document.createElement('button');
    button.type = 'button';
    button.textContent = value;
    button.onclick = () => grid.set('density', value);
    controls.append(button);
  }
</script>

Setting row density with a single token

Density is the control most JavaScript data grid users touch before anything else, because it decides how many rows fit on screen without a scrollbar. Lattice Grid exposes it as one setting, density: 'comfortable', with compact and spacious as the other named steps, rather than as CSS a team has to author and maintain against the grid’s own layout. Row height, cell padding and the size of icon-only controls all read from the same density token, so a change to it is consistent across every column type and renderer instead of a patchwork of overrides that drift out of sync after a redesign. A developer reaches for compact when a screen holds a trading blotter or an admin table that benefits from more rows per scroll, and for spacious when the audience is scanning rather than transacting, or when a touch target needs more room to hit reliably. Because the row height is derived rather than hard-coded, switching density at runtime does not require a rebuild of the grid’s DOM or a manual recalculation of scroll offsets: the grid recomputes row heights and keeps the current scroll position and selection intact. This keeps density compatible with theming and with saved views, so a user’s preferred setting persists the same way a colour theme does.

How do I change row height in Lattice Grid?

Set the density option to 'compact', 'comfortable' or 'spacious' when configuring the grid, or call the equivalent runtime method to switch it after the grid exists. Row height, cell padding and control sizing all follow the token, so there is no need to set an explicit pixel height unless a row’s content requires it.