Simple and powerful JavaScript table with all features enabled by default - no configuration needed!
npm install vanillajs-excelike-table> The simplest Excel-like table for JavaScript
> Zero configuration needed - all features work out of the box! ✨
- 🎯 Zero Configuration: Just pass data and columns - everything works!
- ⚡ All Features Enabled: Filtering, sorting, pagination, column pinning - all included by default
- 🚀 Modern ESM: Works with Vite, Webpack, Next.js, and all modern tools
- 📦 Lightweight Package: Pure vanilla JavaScript (~100KB minified)
- 💾 Auto-Save Settings: User preferences saved automatically
- 🎨 Excel-like UX: Familiar interface for end users
---
``bash`
npm install vanillajs-excelike-table
Step 1: Install the package (see above)
Step 2: Create your HTML file:
`html`
Step 3: Create src/main.js:
`javascript
import ExceLikeTable from 'vanillajs-excelike-table';
import 'vanillajs-excelike-table/dist/excelike-table.css';
const table = new ExceLikeTable('#my-table', {
data: [
{ id: 1, name: 'John Doe', age: 30, city: 'New York' },
{ id: 2, name: 'Jane Smith', age: 25, city: 'Los Angeles' },
{ id: 3, name: 'Bob Johnson', age: 35, city: 'Chicago' }
],
columns: [
{ key: 'name', title: 'Name', dataIndex: 'name' },
{ key: 'age', title: 'Age', dataIndex: 'age' },
{ key: 'city', title: 'City', dataIndex: 'city' }
]
});
`
Step 4: Run your dev server:
`bash`
npm run dev # For Viteor
npm start # For Webpack/other bundlers
That's it! ✅ You now have:
- ✓ Sortable columns (click headers)
- ✓ Filterable data (click filter icons)
- ✓ Pagination (10 items per page)
- ✓ Resizable columns (drag edges)
- ✓ Pinnable columns (column settings menu)
- ✓ Auto-saved user preferences
---
Copy and paste this complete HTML file - it works immediately!
`html
`
Just open this HTML file in your browser - no npm, no build step needed!
---
`javascript
const ExceLikeTable = require('vanillajs-excelike-table');
// CSS must be loaded separately in your HTML
const table = new ExceLikeTable('#container', {
data: myData,
columns: myColumns
});
`
`typescript
import ExceLikeTable, { ExceLikeTableOptions, ExceLikeTableColumn } from 'vanillajs-excelike-table';
import 'vanillajs-excelike-table/dist/excelike-table.css';
const options: ExceLikeTableOptions = {
data: myData,
columns: myColumns
};
const table = new ExceLikeTable('#container', options);
`
---
Use ColumnHelpers for common column types with pre-configured features:
`javascript
import ExceLikeTable, { ColumnHelpers } from 'vanillajs-excelike-table';
import 'vanillajs-excelike-table/dist/excelike-table.css';
const table = new ExceLikeTable('#container', {
data: employees,
columns: [
ColumnHelpers.text('name', 'Employee Name'),
ColumnHelpers.number('salary', 'Salary', { currency: '$' }),
ColumnHelpers.date('joinDate', 'Join Date'),
ColumnHelpers.status('status', 'Status', {
'Active': '#52c41a',
'On Leave': '#faad14',
'Terminated': '#ff4d4f'
})
]
});
`
| Helper | Usage | Features |
|--------|-------|----------|
| text() | ColumnHelpers.text('key', 'Title') | Basic text column |number()
| | ColumnHelpers.number('price', 'Price', { currency: '¥' }) | Formatted numbers with currency |date()
| | ColumnHelpers.date('date', 'Date') | Auto-formatted dates with hierarchy filter |status()
| | ColumnHelpers.status('status', 'Status', colors) | Colored status badges |actions()
| | ColumnHelpers.actions('Actions', buttons) | Action buttons |
---
`javascript`
new ExceLikeTable(container, options)
#### Parameters
container string | HTMLElement
CSS selector or DOM element where table will be rendered
options Object
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| data | Array | [] | Your data array |columns
| | Array | [] | Column definitions |rowKey
| | string | 'id' | Unique row identifier |pagination
| | Object\|false | {pageSize: 10, showSizeChanger: true} | Pagination config or false to disable |bordered
| | boolean | true | Show table borders |size
| | 'small'\|'middle'\|'large' | 'middle' | Table size |tableId
| | string | 'excelike-table' | Unique ID for settings storage |persistSettings
| | boolean | true | Auto-save user preferences |
---
All features are enabled by default for each column!
`javascript${value}
{
key: 'columnKey', // Required: Unique identifier
title: 'Column Title', // Required: Display name
dataIndex: 'dataKey', // Required: Property name in data
width: 150, // Optional: Column width (default: 150)
sortable: true, // Optional: Enable sorting (default: true)
filterable: true, // Optional: Enable filtering (default: true)
filterType: 'text', // Optional: 'text' | 'date-hierarchy' | 'range'
render: (value, record) => , // Optional: Custom renderer`
hidden: false // Optional: Hide column (default: false)
}
---
`javascript
// Update table data
table.setData(newData);
// Get current filters
const filters = table.getFilters();
// Set filters programmatically
table.setFilters({ name: ['John'], age: [30] });
// Clear all filters
table.clearFilters();
// Clean up and destroy table
table.destroy();
`
---
`javascript
import ExceLikeTable, { ColumnHelpers } from 'vanillajs-excelike-table';
import 'vanillajs-excelike-table/dist/excelike-table.css';
const employees = [
{ id: 1, name: 'Alice', department: 'Engineering', salary: 120000, joinDate: '2020-03-15', status: 'Active' },
{ id: 2, name: 'Bob', department: 'Marketing', salary: 85000, joinDate: '2019-07-22', status: 'Active' },
{ id: 3, name: 'Carol', department: 'Sales', salary: 95000, joinDate: '2021-01-10', status: 'On Leave' }
];
const table = new ExceLikeTable('#employee-table', {
data: employees,
columns: [
ColumnHelpers.text('name', 'Employee Name'),
ColumnHelpers.text('department', 'Department'),
ColumnHelpers.number('salary', 'Salary', { currency: '$' }),
ColumnHelpers.date('joinDate', 'Join Date'),
ColumnHelpers.status('status', 'Status', {
'Active': '#52c41a',
'On Leave': '#faad14',
'Terminated': '#ff4d4f'
}),
ColumnHelpers.actions('Actions', [
{ key: 'edit', label: 'Edit' },
{ key: 'delete', label: 'Delete' }
])
]
});
`
`javascript
const salesData = [
{ date: '2024-01-15', product: 'Widget A', quantity: 120, revenue: 2400, profit: 15 },
{ date: '2024-01-16', product: 'Widget B', quantity: 85, revenue: 3400, profit: 22 },
{ date: '2024-01-17', product: 'Widget C', quantity: 200, revenue: 5000, profit: -5 }
];
const table = new ExceLikeTable('#sales-table', {
data: salesData,
columns: [
ColumnHelpers.date('date', 'Date'),
ColumnHelpers.text('product', 'Product'),
ColumnHelpers.number('quantity', 'Qty'),
ColumnHelpers.number('revenue', 'Revenue', { currency: '¥' }),
{
key: 'profit',
title: 'Profit %',
dataIndex: 'profit',
render: (value) => {
const color = value >= 0 ? '#52c41a' : '#ff4d4f';
return ${value}%;`
}
}
],
pagination: { pageSize: 20 }
});
`javascript`
// Simplest possible usage
const table = new ExceLikeTable('#container', {
data: myData,
columns: [
{ key: 'col1', title: 'Column 1', dataIndex: 'col1' },
{ key: 'col2', title: 'Column 2', dataIndex: 'col2' }
]
});
// Everything just works! ✨
---
All features are enabled by default. You can disable them if needed:
`javascript
const table = new ExceLikeTable('#container', {
data: myData,
columns: myColumns,
pagination: false, // Disable pagination
persistSettings: false // Disable auto-save
});
// Or disable per-column:
columns: [
{
key: 'id',
title: 'ID',
dataIndex: 'id',
sortable: false, // Disable sorting for this column
filterable: false // Disable filtering for this column
}
]
`
`javascriptShowing ${range[0]}-${range[1]} of ${total}
const table = new ExceLikeTable('#container', {
data: myData,
columns: myColumns,
pagination: {
pageSize: 25,
showSizeChanger: true,
showTotal: (total, range) => `
}
});
`css
/ Override default styles /
.excelike-table-wrapper {
--table-border-color: #e0e0e0;
--table-header-bg: #fafafa;
--table-row-hover: #f5f5f5;
}
/ Customize specific elements /
.table-header {
background: linear-gradient(to bottom, #f9f9f9, #ececec);
font-weight: 600;
}
.table-cell {
padding: 12px 16px;
}
``
---
---
Works in all modern browsers and environments:
| Environment | Support |
|-------------|---------|
| Chrome/Edge | ✅ Latest |
| Firefox | ✅ Latest |
| Safari | ✅ Latest |
| Node.js | ✅ 14+ |
| Vite | ✅ Yes |
| Webpack | ✅ Yes |
| Next.js | ✅ Yes |
| React/Vue/Angular | ✅ Yes (framework-agnostic) |
---
Contributions are welcome! Please feel free to submit pull requests.
---
MIT License - feel free to use this library in your projects!
---
For questions, issues, or feature requests, please visit the GitHub repository.
---
Made with ❤️ for developers who love simplicity