Documentation
Column Width
Set each column's width to "auto", a fixed size, or "1fr". Optionally fill the container with autoExpandColumns.
Content-fit ("auto")
Use width: "auto" to size from the header and sampled cell content. Cap growth with maxWidth when you want truncation.
{accessor: "email",label: "Email",width: "auto",maxWidth: 300,}
{accessor: "email",label: "Email",width: "auto",maxWidth: 300,}
{accessor: "email",label: "Email",width: "auto",maxWidth: 300,}
{accessor: "email",label: "Email",width: "auto",maxWidth: 300,}
{accessor: "email",label: "Email",width: "auto",maxWidth: 300,}
{accessor: "email",label: "Email",width: "auto",maxWidth: 300,}
Fixed width
Pass a number for a pixel width. Best for IDs, dates, and other short columns.
{ accessor: "id", label: "ID", width: 60 }
{ accessor: "id", label: "ID", width: 60 }
{ accessor: "id", label: "ID", width: 60 }
{ accessor: "id", label: "ID", width: 60 }
{ accessor: "id", label: "ID", width: 60 }
{ accessor: "id", label: "ID", width: 60 }
Flexible width ("1fr")
Use width: "1fr" so the column shares leftover space with other flexible columns. Pair with minWidthso it doesn't get too narrow.
{accessor: "name",label: "Name",width: "1fr",minWidth: 120,}
{accessor: "name",label: "Name",width: "1fr",minWidth: 120,}
{accessor: "name",label: "Name",width: "1fr",minWidth: 120,}
{accessor: "name",label: "Name",width: "1fr",minWidth: 120,}
{accessor: "name",label: "Name",width: "1fr",minWidth: 120,}
{accessor: "name",label: "Name",width: "1fr",minWidth: 120,}
Fill the container
Set autoExpandColumns to scale all column widths proportionally so the table fills its container with no horizontal scroll. Prefer falseon small screens (< 768px).
<SimpleTable columns={columns} rows={rows} height="400px" autoExpandColumns={true} />
<SimpleTable:columns="columns":rows="rows"height="400px":auto-expand-columns="true"/>
<simple-table[columns]="columns"[rows]="rows"height="400px"[autoExpandColumns]="true"></simple-table>
<SimpleTable {columns} {rows} height="400px" autoExpandColumns={true} />
<SimpleTable columns={columns} rows={rows} height="400px" autoExpandColumns={true} />
new SimpleTableVanilla(container, {columns,rows,height: "400px",autoExpandColumns: true,});
Example
Fixed, flexible, and auto columns together. On wider viewports the demo enables autoExpandColumns.
1import { useState, useEffect } from "react";2import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";3import { columnWidthConfig } from "./column-width.demo-data";4import "@simple-table/react/styles.css";56const ColumnWidthDemo = ({7 height = "400px",8 theme,9}: {10 height?: string | number;11 theme?: Theme;12}) => {13 const [isMobile, setIsMobile] = useState(false);1415 useEffect(() => {16 const check = () => setIsMobile(window.innerWidth < 768);17 check();18 window.addEventListener("resize", check);19 return () => window.removeEventListener("resize", check);20 }, []);2122 return (23 <SimpleTable24 autoExpandColumns={!isMobile}25 columnResizing26 columns={columnWidthConfig.headers}27 height={height}28 rows={columnWidthConfig.rows}29 theme={theme}30 />31 );32};3334export default ColumnWidthDemo;
1<template>2 <SimpleTable3 :auto-expand-columns="!isMobile"4 :column-resizing="true"5 :columns="columnWidthConfig.headers"6 :height="height"7 :rows="columnWidthConfig.rows"8 :theme="theme"9 />10</template>1112<script setup lang="ts">13import { ref, onMounted, onUnmounted } from "vue";14import {SimpleTable} from "@simple-table/vue";import type { Theme } from "@simple-table/vue";15import { columnWidthConfig } from "./column-width.demo-data";16import "@simple-table/vue/styles.css";1718withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {19 height: "400px",20});2122const isMobile = ref(false);2324function checkMobile() {25 isMobile.value = window.innerWidth < 768;26}2728onMounted(() => {29 checkMobile();30 window.addEventListener("resize", checkMobile);31});3233onUnmounted(() => {34 window.removeEventListener("resize", checkMobile);35});36</script>
1import { Component, Input, OnInit, OnDestroy } from "@angular/core";2import {SimpleTableComponent} from "@simple-table/angular";import type { AngularColumnDef, Row, Theme } from "@simple-table/angular";3import { columnWidthConfig } from "./column-width.demo-data";4import "@simple-table/angular/styles.css";56@Component({7 selector: "column-width-demo",8 standalone: true,9 imports: [SimpleTableComponent],10 template: `11 <simple-table12 [autoExpandColumns]="!isMobile"13 [columnResizing]="true"14 [rows]="rows"15 [columns]="headers"16 [height]="height"17 [theme]="theme"18 ></simple-table>19 `,20})21export class ColumnWidthDemoComponent implements OnInit, OnDestroy {22 @Input() height: string | number = "400px";23 @Input() theme?: Theme;2425 readonly rows: Row[] = columnWidthConfig.rows;26 readonly headers: AngularColumnDef[] = columnWidthConfig.headers;27 isMobile = false;2829 private checkMobile = () => { this.isMobile = window.innerWidth < 768; };3031 ngOnInit() {32 this.checkMobile();33 window.addEventListener("resize", this.checkMobile);34 }3536 ngOnDestroy() {37 window.removeEventListener("resize", this.checkMobile);38 }39}404142// column-width.demo-data.ts43// Self-contained demo table setup for this example.44import type { AngularColumnDef } from "@simple-table/angular";454647export const columnWidthHeaders: AngularColumnDef[] = [48 { accessor: "id", label: "ID", width: 60, type: "number" },49 { accessor: "name", label: "Name", width: "1fr", minWidth: 120, type: "string" },50 { accessor: "email", label: "Email", width: "1fr", minWidth: 180, type: "string" },51 { accessor: "age", label: "Age", width: 80, type: "number" },52 { accessor: "department", label: "Department", width: "auto", minWidth: 100, type: "string" },53 { accessor: "salary", label: "Salary", width: 120, align: "right", type: "number" },54];5556export const columnWidthData = [57 { id: 1, name: "Alexandra Reeves", email: "alex.reeves@techstartup.io", age: 32, department: "AI Research", salary: "$145,000" },58 { id: 2, name: "Zephyr Kim", email: "zephyr.kim@techstartup.io", age: 28, department: "Product Design", salary: "$125,000" },59 { id: 3, name: "Phoenix Okafor", email: "phoenix.okafor@techstartup.io", age: 35, department: "Platform Engineering", salary: "$160,000" },60 { id: 4, name: "Luna Tanaka", email: "luna.tanaka@techstartup.io", age: 29, department: "DevOps & Infrastructure", salary: "$138,000" },61 { id: 5, name: "River Stone", email: "river.stone@techstartup.io", age: 31, department: "Growth Engineering", salary: "$142,000" },62 { id: 6, name: "Sage Morrison", email: "sage.morrison@techstartup.io", age: 27, department: "Customer Success", salary: "$95,000" },63 { id: 7, name: "Atlas Chen", email: "atlas.chen@techstartup.io", age: 33, department: "Security & Compliance", salary: "$155,000" },64 { id: 8, name: "Nova Patel", email: "nova.patel@techstartup.io", age: 30, department: "Data Science", salary: "$148,000" },65 { id: 9, name: "Isabella Patel", email: "isabella.patel@techstartup.io", age: 29, department: "Marketing", salary: "$130,000" },66 { id: 10, name: "Leo Patel", email: "leo.patel@techstartup.io", age: 30, department: "Sales", salary: "$125,000" },67 { id: 11, name: "Oliver Patel", email: "oliver.patel@techstartup.io", age: 31, department: "HR", salary: "$115,000" },68 { id: 12, name: "Sophia Patel", email: "sophia.patel@techstartup.io", age: 28, department: "Finance", salary: "$120,000" },69 { id: 13, name: "William Patel", email: "william.patel@techstartup.io", age: 32, department: "Marketing", salary: "$135,000" },70];7172export const columnWidthConfig = {73 headers: columnWidthHeaders,74 rows: columnWidthData,75 tableProps: { columnResizing: true },76} as const;77
1<script lang="ts">2 import {SimpleTable} from "@simple-table/svelte"; import type { Theme } from "@simple-table/svelte";3 import { columnWidthConfig } from "./column-width.demo-data";4 import "@simple-table/svelte/styles.css";56 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();7 let isMobile = $state(false);89 function checkMobile() {10 isMobile = window.innerWidth < 768;11 }1213 $effect(() => {14 checkMobile();15 window.addEventListener("resize", checkMobile);16 return () => window.removeEventListener("resize", checkMobile);17 });18</script>1920<SimpleTable21 autoExpandColumns={!isMobile}22 columnResizing={true}23 columns={columnWidthConfig.headers}24 rows={columnWidthConfig.rows}25 {height}26 {theme}27/>
1import { createSignal, onMount, onCleanup } from "solid-js";2import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";3import { columnWidthConfig } from "./column-width.demo-data";4import "@simple-table/solid/styles.css";56export default function ColumnWidthDemo(props: { height?: string | number; theme?: Theme }) {7 const [isMobile, setIsMobile] = createSignal(false);89 const check = () => setIsMobile(window.innerWidth < 768);1011 onMount(() => {12 check();13 window.addEventListener("resize", check);14 });1516 onCleanup(() => {17 window.removeEventListener("resize", check);18 });1920 return (21 <SimpleTable22 autoExpandColumns={!isMobile()}23 columnResizing24 columns={columnWidthConfig.headers}25 height={props.height ?? "400px"}26 rows={columnWidthConfig.rows}27 theme={props.theme}28 />29 );30}
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { columnWidthConfig } from "./column-width.demo-data";4import "simple-table-core/styles.css";56export function renderColumnWidthDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme },9): SimpleTableVanilla {10 const isMobile = window.innerWidth < 768;1112 const table = new SimpleTableVanilla(container, {13 columns: columnWidthConfig.headers,14 rows: columnWidthConfig.rows,15 height: options?.height ?? "400px",16 theme: options?.theme,17 autoExpandColumns: !isMobile,18 columnResizing: true,19 });2021 const check = () => {22 const mobile = window.innerWidth < 768;23 table.update({ autoExpandColumns: !mobile });24 };25 window.addEventListener("resize", check);2627 return table;28}293031// column-width.demo-data.ts32// Self-contained demo table setup for this example.33import type { ColumnDef } from "simple-table-core";343536export const columnWidthHeaders: ColumnDef[] = [37 { accessor: "id", label: "ID", width: 60, type: "number" },38 { accessor: "name", label: "Name", width: "1fr", minWidth: 120, type: "string" },39 { accessor: "email", label: "Email", width: "1fr", minWidth: 180, type: "string" },40 { accessor: "age", label: "Age", width: 80, type: "number" },41 { accessor: "department", label: "Department", width: "auto", minWidth: 100, type: "string" },42 { accessor: "salary", label: "Salary", width: 120, align: "right", type: "number" },43];4445export const columnWidthData = [46 { id: 1, name: "Alexandra Reeves", email: "alex.reeves@techstartup.io", age: 32, department: "AI Research", salary: "$145,000" },47 { id: 2, name: "Zephyr Kim", email: "zephyr.kim@techstartup.io", age: 28, department: "Product Design", salary: "$125,000" },48 { id: 3, name: "Phoenix Okafor", email: "phoenix.okafor@techstartup.io", age: 35, department: "Platform Engineering", salary: "$160,000" },49 { id: 4, name: "Luna Tanaka", email: "luna.tanaka@techstartup.io", age: 29, department: "DevOps & Infrastructure", salary: "$138,000" },50 { id: 5, name: "River Stone", email: "river.stone@techstartup.io", age: 31, department: "Growth Engineering", salary: "$142,000" },51 { id: 6, name: "Sage Morrison", email: "sage.morrison@techstartup.io", age: 27, department: "Customer Success", salary: "$95,000" },52 { id: 7, name: "Atlas Chen", email: "atlas.chen@techstartup.io", age: 33, department: "Security & Compliance", salary: "$155,000" },53 { id: 8, name: "Nova Patel", email: "nova.patel@techstartup.io", age: 30, department: "Data Science", salary: "$148,000" },54 { id: 9, name: "Isabella Patel", email: "isabella.patel@techstartup.io", age: 29, department: "Marketing", salary: "$130,000" },55 { id: 10, name: "Leo Patel", email: "leo.patel@techstartup.io", age: 30, department: "Sales", salary: "$125,000" },56 { id: 11, name: "Oliver Patel", email: "oliver.patel@techstartup.io", age: 31, department: "HR", salary: "$115,000" },57 { id: 12, name: "Sophia Patel", email: "sophia.patel@techstartup.io", age: 28, department: "Finance", salary: "$120,000" },58 { id: 13, name: "William Patel", email: "william.patel@techstartup.io", age: 32, department: "Marketing", salary: "$135,000" },59];6061export const columnWidthConfig = {62 headers: columnWidthHeaders,63 rows: columnWidthData,64 tableProps: { columnResizing: true },65} as const;66
How "1fr" splits space
Fixed columns take their pixels first. Remaining width is split equally among 1fr columns. In a 1000px table with fixed 100px + 150px and two 1fr columns, each flexible column gets 375px.
autoExpandColumns trade-offs
Column width values are the scale base. minWidth /maxWidth are not enforced while scaling.
Props
Column Width Properties
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
ColumnDef.width | Required | Column width: a pixel number, '1fr' to share leftover space, or 'auto' to fit content (clamped by minWidth/maxWidth). | |
ColumnDef.minWidthnumber | Optional | Minimum width for '1fr' and 'auto' columns. Not enforced during autoExpandColumns scaling. | |
ColumnDef.maxWidthnumber | Optional | Maximum width. With width: 'auto', content past the cap truncates. Ignored when autoExpandColumns is enabled. | |
autoExpandColumns | Optional | Scale all column widths proportionally to fill the container. Recommended off on mobile (< 768px). |