Documentation
Table Height
Control vertical overflow with height or maxHeight. Most apps should set one of them.
Fixed height
Use a fixed height when the table should always occupy the same vertical space. The header stays visible while rows scroll.
<SimpleTable columns={columns} rows={rows} height="400px" />
<SimpleTable:columns="columns":rows="rows"height="400px"/>
<simple-table[columns]="columns"[rows]="rows"height="400px"></simple-table>
<SimpleTable {columns} {rows} height="400px" />
<SimpleTable columns={columns} rows={rows} height="400px" />
new SimpleTableVanilla(container, {columns,rows,height: "400px",});
Adaptive height (maxHeight)
Prefer maxHeight when row count varies — the table stays compact with few rows and grows up to the cap.
<SimpleTable columns={columns} rows={rows} maxHeight="600px" />
<SimpleTable:columns="columns":rows="rows"max-height="600px"/>
<simple-table[columns]="columns"[rows]="rows"maxHeight="600px"></simple-table>
<SimpleTable {columns} {rows} maxHeight="600px" />
<SimpleTable columns={columns} rows={rows} maxHeight="600px" />
new SimpleTableVanilla(container, {columns,rows,maxHeight: "600px",});
Viewport or parent size
Use vh/vw or % when the table should track the viewport or a parent with a defined height.
<SimpleTable columns={columns} rows={rows} height="50vh" />
<SimpleTable:columns="columns":rows="rows"height="50vh"/>
<simple-table[columns]="columns"[rows]="rows"height="50vh"></simple-table>
<SimpleTable {columns} {rows} height="50vh" />
<SimpleTable columns={columns} rows={rows} height="50vh" />
new SimpleTableVanilla(container, {columns,rows,height: "50vh",});
External / window scroll
Omit height and maxHeight, then set scrollParent so the page (or a custom container) drives virtualization. The header pins to that scroll viewport. More detail on Infinite Scroll.
<SimpleTable columns={columns} rows={rows} scrollParent="window" />
<SimpleTable:columns="columns":rows="rows"scroll-parent="window"/>
<simple-table[columns]="columns"[rows]="rows"scrollParent="window"></simple-table>
<SimpleTable {columns} {rows} scrollParent="window" />
<SimpleTable columns={columns} rows={rows} scrollParent="window" />
new SimpleTableVanilla(container, {columns,rows,scrollParent: "window",});
Example
Try different fixed heights below. Use Code or StackBlitz for the full example.
400px1import { useState } from "react";2import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";3import { tableHeightConfig } from "./table-height.demo-data";4import "@simple-table/react/styles.css";56const heights = ["200px", "300px", "400px"] as const;78const TableHeightDemo = ({9 height: _height,10 theme,11}: {12 height?: string | number;13 theme?: Theme;14}) => {15 const [selectedHeight, setSelectedHeight] = useState<string>("400px");1617 return (18 <div>19 <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>20 {heights.map((h) => (21 <button22 key={h}23 onClick={() => setSelectedHeight(h)}24 style={{25 padding: "6px 12px",26 borderRadius: 4,27 border: "1px solid #ccc",28 background: selectedHeight === h ? "#3b82f6" : "#f3f4f6",29 color: selectedHeight === h ? "#fff" : "#374151",30 cursor: "pointer",31 fontSize: 14,32 fontWeight: 500,33 }}34 >35 {h}36 </button>37 ))}38 </div>39 <SimpleTable40 columns={tableHeightConfig.headers}41 rows={tableHeightConfig.rows}42 height={selectedHeight}43 theme={theme}44 />45 </div>46 );47};4849export default TableHeightDemo;
1<template>2 <div>3 <div style="display: flex; gap: 8px; margin-bottom: 12px">4 <button5 v-for="h in heights"6 :key="h"7 @click="selectedHeight = h"8 :style="{9 padding: '6px 12px',10 borderRadius: '4px',11 border: '1px solid #ccc',12 background: selectedHeight === h ? '#3b82f6' : '#f3f4f6',13 color: selectedHeight === h ? '#fff' : '#374151',14 cursor: 'pointer',15 fontSize: '14px',16 fontWeight: '500',17 }"18 >19 {{ h }}20 </button>21 </div>22 <SimpleTable23 :columns="tableHeightConfig.headers"24 :rows="tableHeightConfig.rows"25 :height="selectedHeight"26 :theme="theme"27 />28 </div>29</template>3031<script setup lang="ts">32import { ref } from "vue";33import {SimpleTable} from "@simple-table/vue";import type { Theme } from "@simple-table/vue";34import { tableHeightConfig } from "./table-height.demo-data";35import "@simple-table/vue/styles.css";3637withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {38 height: "400px",39});4041const heights = ["200px", "300px", "400px"];42const selectedHeight = ref("400px");43</script>
1import { Component, Input } from "@angular/core";2import {SimpleTableComponent} from "@simple-table/angular";import type { AngularColumnDef, Row, Theme } from "@simple-table/angular";3import { tableHeightConfig } from "./table-height.demo-data";4import "@simple-table/angular/styles.css";56@Component({7 selector: "table-height-demo",8 standalone: true,9 imports: [SimpleTableComponent],10 template: `11 <div>12 <div style="display: flex; gap: 8px; margin-bottom: 12px">13 @for (h of heights; track h) {14 <button15 (click)="selectedHeight = h"16 [style.padding]="'6px 12px'"17 [style.borderRadius]="'4px'"18 [style.border]="'1px solid #ccc'"19 [style.background]="selectedHeight === h ? '#3b82f6' : '#f3f4f6'"20 [style.color]="selectedHeight === h ? '#fff' : '#374151'"21 [style.cursor]="'pointer'"22 [style.fontSize]="'14px'"23 [style.fontWeight]="'500'"24 >25 {{ h }}26 </button>27 }28 </div>29 <simple-table30 [rows]="rows"31 [columns]="headers"32 [height]="selectedHeight"33 [theme]="theme"34 ></simple-table>35 </div>36 `,37})38export class TableHeightDemoComponent {39 @Input() height: string | number = "400px";40 @Input() theme?: Theme;4142 readonly rows: Row[] = tableHeightConfig.rows;43 readonly headers: AngularColumnDef[] = tableHeightConfig.headers;44 readonly heights = ["200px", "300px", "400px"];45 selectedHeight = "400px";46}474849// table-height.demo-data.ts50// Self-contained demo table setup for this example.51import type { AngularColumnDef } from "@simple-table/angular";525354export const tableHeightHeaders: AngularColumnDef[] = [55 { accessor: "id", label: "ID", width: 80, type: "number" },56 { accessor: "name", label: "Name", minWidth: 150, width: "1fr", type: "string" },57 { accessor: "email", label: "Email", minWidth: 200, width: "1fr", type: "string" },58 { accessor: "role", label: "Role", minWidth: 150, width: "1fr", type: "string" },59 { accessor: "department", label: "Department", minWidth: 150, width: "1fr", type: "string" },60 { accessor: "status", label: "Status", width: 120, type: "string" },61];6263export const tableHeightData = [64 { id: 1, name: "Alice Chen", email: "alice@example.com", role: "Senior Engineer", department: "Engineering", status: "Active" },65 { id: 2, name: "Bob Martinez", email: "bob@example.com", role: "Product Manager", department: "Product", status: "Active" },66 { id: 3, name: "Carol Williams", email: "carol@example.com", role: "Designer", department: "Design", status: "Active" },67 { id: 4, name: "David Kim", email: "david@example.com", role: "Data Analyst", department: "Analytics", status: "Active" },68 { id: 5, name: "Eva Patel", email: "eva@example.com", role: "DevOps Engineer", department: "Engineering", status: "On Leave" },69 { id: 6, name: "Frank Johnson", email: "frank@example.com", role: "QA Lead", department: "Engineering", status: "Active" },70 { id: 7, name: "Grace Lee", email: "grace@example.com", role: "UX Researcher", department: "Design", status: "Active" },71 { id: 8, name: "Henry Brown", email: "henry@example.com", role: "Backend Developer", department: "Engineering", status: "Active" },72 { id: 9, name: "Iris Davis", email: "iris@example.com", role: "Frontend Developer", department: "Engineering", status: "Active" },73 { id: 10, name: "Jack Wilson", email: "jack@example.com", role: "Technical Writer", department: "Documentation", status: "Active" },74 { id: 11, name: "Kate Thompson", email: "kate@example.com", role: "Security Engineer", department: "Engineering", status: "Active" },75 { id: 12, name: "Leo Garcia", email: "leo@example.com", role: "ML Engineer", department: "AI", status: "Active" },76 { id: 13, name: "Mia Anderson", email: "mia@example.com", role: "Project Manager", department: "Operations", status: "Active" },77 { id: 14, name: "Noah Taylor", email: "noah@example.com", role: "Solutions Architect", department: "Engineering", status: "Active" },78 { id: 15, name: "Olivia Moore", email: "olivia@example.com", role: "HR Manager", department: "Human Resources", status: "Active" },79];8081export const tableHeightConfig = {82 headers: tableHeightHeaders,83 rows: tableHeightData,84} as const;85
1<script lang="ts">2 import {SimpleTable} from "@simple-table/svelte"; import type { Theme } from "@simple-table/svelte";3 import { tableHeightConfig } from "./table-height.demo-data";4 import "@simple-table/svelte/styles.css";56 let { height: _height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();7 let selectedHeight = $state("400px");8 const heights = ["200px", "300px", "400px"];9</script>1011<div>12 <div style="display: flex; gap: 8px; margin-bottom: 12px">13 {#each heights as h}14 <button15 onclick={() => selectedHeight = h}16 style="padding: 6px 12px; border-radius: 4px; border: 1px solid #ccc; background: {selectedHeight === h ? '#3b82f6' : '#f3f4f6'}; color: {selectedHeight === h ? '#fff' : '#374151'}; cursor: pointer; font-size: 14px; font-weight: 500;"17 >18 {h}19 </button>20 {/each}21 </div>22 <SimpleTable23 columns={tableHeightConfig.headers}24 rows={tableHeightConfig.rows}25 height={selectedHeight}26 {theme}27 />28</div>
1import { createSignal, For } from "solid-js";2import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";3import { tableHeightConfig } from "./table-height.demo-data";4import "@simple-table/solid/styles.css";56const heights = ["200px", "300px", "400px"];78export default function TableHeightDemo(props: { height?: string | number; theme?: Theme }) {9 const [selectedHeight, setSelectedHeight] = createSignal("400px");1011 return (12 <div>13 <div style={{ display: "flex", gap: "8px", "margin-bottom": "12px" }}>14 <For each={heights}>15 {(h) => (16 <button17 onClick={() => setSelectedHeight(h)}18 style={{19 padding: "6px 12px",20 "border-radius": "4px",21 border: "1px solid #ccc",22 background: selectedHeight() === h ? "#3b82f6" : "#f3f4f6",23 color: selectedHeight() === h ? "#fff" : "#374151",24 cursor: "pointer",25 "font-size": "14px",26 "font-weight": "500",27 }}28 >29 {h}30 </button>31 )}32 </For>33 </div>34 <SimpleTable35 columns={tableHeightConfig.headers}36 rows={tableHeightConfig.rows}37 height={selectedHeight()}38 theme={props.theme}39 />40 </div>41 );42}
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { tableHeightConfig } from "./table-height.demo-data";4import "simple-table-core/styles.css";56export function renderTableHeightDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme }9): SimpleTableVanilla {10 const wrapper = document.createElement("div");1112 const btnContainer = document.createElement("div");13 btnContainer.style.cssText = "display: flex; gap: 8px; margin-bottom: 12px";1415 const heights = ["200px", "300px", "400px"];16 let selectedHeight = "400px";1718 const tableContainer = document.createElement("div");19 wrapper.appendChild(btnContainer);20 wrapper.appendChild(tableContainer);21 container.appendChild(wrapper);2223 const table = new SimpleTableVanilla(tableContainer, {24 columns: tableHeightConfig.headers,25 rows: tableHeightConfig.rows,26 height: selectedHeight,27 theme: options?.theme,28 });2930 const buttons: HTMLButtonElement[] = [];31 for (const h of heights) {32 const btn = document.createElement("button");33 btn.textContent = h;34 btn.style.cssText = `padding: 6px 12px; border-radius: 4px; border: 1px solid #ccc; cursor: pointer; font-size: 14px; font-weight: 500;`;35 btn.addEventListener("click", () => {36 selectedHeight = h;37 table.updateConfig({ height: h });38 updateButtons();39 });40 buttons.push(btn);41 btnContainer.appendChild(btn);42 }4344 function updateButtons() {45 buttons.forEach((btn, i) => {46 const isActive = heights[i] === selectedHeight;47 btn.style.background = isActive ? "#3b82f6" : "#f3f4f6";48 btn.style.color = isActive ? "#fff" : "#374151";49 });50 }51 updateButtons();5253 return table;54}555657// table-height.demo-data.ts58// Self-contained demo table setup for this example.59import type { ColumnDef } from "simple-table-core";606162export const tableHeightHeaders: ColumnDef[] = [63 { accessor: "id", label: "ID", width: 80, type: "number" },64 { accessor: "name", label: "Name", minWidth: 150, width: "1fr", type: "string" },65 { accessor: "email", label: "Email", minWidth: 200, width: "1fr", type: "string" },66 { accessor: "role", label: "Role", minWidth: 150, width: "1fr", type: "string" },67 { accessor: "department", label: "Department", minWidth: 150, width: "1fr", type: "string" },68 { accessor: "status", label: "Status", width: 120, type: "string" },69];7071export const tableHeightData = [72 { id: 1, name: "Alice Chen", email: "alice@example.com", role: "Senior Engineer", department: "Engineering", status: "Active" },73 { id: 2, name: "Bob Martinez", email: "bob@example.com", role: "Product Manager", department: "Product", status: "Active" },74 { id: 3, name: "Carol Williams", email: "carol@example.com", role: "Designer", department: "Design", status: "Active" },75 { id: 4, name: "David Kim", email: "david@example.com", role: "Data Analyst", department: "Analytics", status: "Active" },76 { id: 5, name: "Eva Patel", email: "eva@example.com", role: "DevOps Engineer", department: "Engineering", status: "On Leave" },77 { id: 6, name: "Frank Johnson", email: "frank@example.com", role: "QA Lead", department: "Engineering", status: "Active" },78 { id: 7, name: "Grace Lee", email: "grace@example.com", role: "UX Researcher", department: "Design", status: "Active" },79 { id: 8, name: "Henry Brown", email: "henry@example.com", role: "Backend Developer", department: "Engineering", status: "Active" },80 { id: 9, name: "Iris Davis", email: "iris@example.com", role: "Frontend Developer", department: "Engineering", status: "Active" },81 { id: 10, name: "Jack Wilson", email: "jack@example.com", role: "Technical Writer", department: "Documentation", status: "Active" },82 { id: 11, name: "Kate Thompson", email: "kate@example.com", role: "Security Engineer", department: "Engineering", status: "Active" },83 { id: 12, name: "Leo Garcia", email: "leo@example.com", role: "ML Engineer", department: "AI", status: "Active" },84 { id: 13, name: "Mia Anderson", email: "mia@example.com", role: "Project Manager", department: "Operations", status: "Active" },85 { id: 14, name: "Noah Taylor", email: "noah@example.com", role: "Solutions Architect", department: "Engineering", status: "Active" },86 { id: 15, name: "Olivia Moore", email: "olivia@example.com", role: "HR Manager", department: "Human Resources", status: "Active" },87];8889export const tableHeightConfig = {90 headers: tableHeightHeaders,91 rows: tableHeightData,92} as const;93
height vs maxHeight
height always fills the space you set. maxHeight shrinks with few rows. If both are set, height is ignored.
Rarely needed: customTheme header/footer height
Only for pagination tables with custom footers that need measured layout before paint. See Custom Theme.
Props
Height Configuration
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
heightstring | number | Optional | Fixed height for the table container. The table scrolls internally with a sticky header. If both height and maxHeight are set, height is ignored. | |
maxHeightstring | number | Optional | Maximum height with adaptive sizing — the table shrinks when there are fewer rows, and grows up to this cap. Virtualization stays enabled. |