How to convert an excel spreadsheet to a responsive tailwind html table
- Step 1Put your data on the first sheet with headers in row 1 — The tool reads sheet index 0 only and uses row 1 as the column headers (which become
<th>cells). If your real data lives on a second tab, copy it to the first sheet before exporting, or save that tab as its own file. - Step 2Drop the .xlsx or .csv onto the tool above — Both Excel workbooks and CSV files are accepted. Parsing runs in your browser with SheetJS — nothing uploads. Cells are read as formatted display text (the value you see in the cell), so a date shown as
15/03/2026exports as that string, not a serial number. - Step 3Pick a style — Choose
striped(default — zebra rows),bordered(full grid lines),compact(text-xs, tighter padding for dense tables), orminimal(no borders, just spacing). The style controls the class strings on<table>,<th>, and<td>— see the cookbook for the exact classes each one emits. - Step 4Toggle dark mode if your site has a dark theme — Dark mode is off by default. Turning it on appends
dark:bg-gray-800 dark:text-gray-100to the wrapper<div>, every<th>, and every<tr>— it does not adddark:classes to<td>or to the<table>element itself. - Step 5Copy the snippet or download table.html — The generated HTML appears in the preview. Copy it to the clipboard or download it as
table.html. There is no UI field for editing the class strings — adjust them in your editor after pasting. - Step 6Paste into a project that already has Tailwind — The snippet uses Tailwind utility classes but ships no CDN tag. Paste it into a page or component where Tailwind is already built, and make sure the file is covered by your Tailwind
contentglobs so the classes survive the production purge.
The two options the tool actually exposes
These are the only controls in the UI. There is no CDN toggle, no sticky-header option, and no in-UI class editor — anything beyond these two is edited by hand after export.
| Option | Type | Values | Default | What it changes |
|---|---|---|---|---|
style | enum | striped, bordered, compact, minimal | striped | Swaps the class strings applied to <table>, <th>, and <td>, and whether <tr> gets a zebra class |
darkMode | boolean | on / off | off | When on, appends dark:bg-gray-800 dark:text-gray-100 to the wrapper <div>, every <th>, and every <tr> |
Exact classes emitted per style
The literal Tailwind class strings the generator writes for each style. The <tr> zebra class only exists for striped.
| Style | table class | th class | td class | tr zebra |
|---|---|---|---|---|
striped | w-full text-sm text-left text-gray-700 border-collapse | px-4 py-3 bg-gray-100 font-semibold ... uppercase tracking-wide text-xs border-b | px-4 py-3 border-b | even:bg-gray-50 |
bordered | w-full text-sm ... border border-gray-300 border-collapse | px-3 py-2 bg-gray-50 font-semibold border border-gray-300 | px-3 py-2 border border-gray-200 | (none) |
compact | w-full text-xs text-left text-gray-600 border-collapse | px-2 py-1 bg-gray-50 font-medium border-b | px-2 py-1 border-b | (none) |
minimal | w-full text-sm text-left text-gray-700 | px-4 py-2 font-semibold text-gray-800 | px-4 py-2 | (none) |
Row limits by plan
Tailwind Table Export is a Pro-tier feature. Limits are per the excel tool family. The tool emits one <tr> per data row with no truncation, so very large tables produce very large snippets.
| Plan | Max file size | Max rows | Files at once |
|---|---|---|---|
| Free | Not available (Pro required) | — | — |
| Pro | 50 MB | 100,000 | 5 |
| Pro-media | 200 MB | 500,000 | 20 |
| Developer | 500 MB | Unlimited | Unlimited |
Cookbook
Real before/after snippets showing what each style and toggle produces. The <pre> blocks below are the literal tool output (whitespace simplified for readability).
Default striped table from a 3-column sheet
The default style. Note the wrapper overflow-x-auto div, the uppercase <th> styling, and the even:bg-gray-50 zebra class on every <tr>.
Input (first sheet, row 1 = headers):
Name | Role | Team
Sue | Engineer | Core
Jon | Designer | Web
Output (style: striped):
<div class="overflow-x-auto">
<table class="w-full text-sm text-left text-gray-700 border-collapse">
<thead><tr>
<th class="px-4 py-3 bg-gray-100 font-semibold ... text-xs border-b">Name</th>
...
</tr></thead>
<tbody>
<tr class="even:bg-gray-50">
<td class="px-4 py-3 border-b">Sue</td> ...
</tr>
</tbody>
</table>
</div>Dark-mode bordered table
Bordered style with dark mode on. The dark: classes land on the wrapper, each <th>, and each <tr> — not on <td> and not on <table>. There is no zebra class because zebra only exists for striped.
Config: style = bordered, darkMode = on
<div class="overflow-x-auto dark:bg-gray-800 dark:text-gray-100">
<table class="w-full text-sm ... border border-gray-300 border-collapse">
<thead><tr>
<th class="px-3 py-2 bg-gray-50 font-semibold border border-gray-300 dark:bg-gray-800 dark:text-gray-100">Name</th>
</tr></thead>
<tbody>
<tr class="dark:bg-gray-800 dark:text-gray-100">
<td class="px-3 py-2 border border-gray-200">Sue</td>
</tr>
</tbody>
</table>
</div>Cell text containing angle brackets is escaped
Spreadsheet content that looks like HTML is escaped, so it renders as text instead of injecting markup. The four escaped characters are &, <, >, and ". The single quote is left as-is.
Input cell value: <b>bold</b> & "quoted" Output <td>: <td class="px-4 py-3 border-b"><b>bold</b> & "quoted"</td> Renders on the page as the literal text: <b>bold</b> & "quoted"
Empty cells become empty <td>, not dropped columns
Blank cells are read as empty strings, so the column structure stays intact and every row keeps the same number of cells as the header row.
Input: Name | Email | Phone Sue | sue@example.com | Jon | | 555-0100 Output tbody rows (compact): <tr><td>Sue</td><td>sue@example.com</td><td></td></tr> <tr><td>Jon</td><td></td><td>555-0100</td></tr>
Minimal style for a borderless reference list
Minimal drops all border classes and the bg-gray header fill — just padding and a bold header. Good for sitting a table inside a card that already has its own border.
Config: style = minimal
<div class="overflow-x-auto">
<table class="w-full text-sm text-left text-gray-700">
<thead><tr>
<th class="px-4 py-2 font-semibold text-gray-800">Term</th>
<th class="px-4 py-2 font-semibold text-gray-800">Definition</th>
</tr></thead>
<tbody>
<tr class="">
<td class="px-4 py-2">SSG</td>
<td class="px-4 py-2">Static Site Generation</td>
</tr>
</tbody>
</table>
</div>Edge cases and what actually happens
Workbook with multiple sheets
First sheet onlyThe tool reads sheet index 0 and ignores every other tab. If your data lives on the second or third sheet, move it to the first sheet (or save it as its own file) before exporting. There is no sheet-picker in this tool's UI.
Row 1 is a title banner, not headers
By designRow 1 is always treated as the header row, so a merged title cell or a 'Generated on...' banner in row 1 becomes your <th> labels and the real headers become a data row. Delete leading banner rows in the spreadsheet first so the genuine header row is row 1.
Two columns share the same header name
PreservedSheetJS auto-suffixes duplicates, so headers Name, Name become <th>Name</th> and <th>Name_1</th>. No error is raised — but the suffixed label appears verbatim in the output, so rename the duplicate column in the spreadsheet if you want clean headers.
A header cell is blank
PreservedAn empty header cell produces an empty <th></th>. The column is kept (its data cells still render) but the heading is blank. Fill in the header in the spreadsheet to get a labelled column.
Some rows have more cells than the header row
By designHeaders are derived from the first data row's keys. Cells in later rows that fall under a column not present in the first row are not given their own <td> — keep your sheet rectangular (every row the same width as the header row) for predictable output.
Expecting a full HTML page or a Tailwind CDN tag
Snippet onlyThe output is a <div>+<table> snippet with no <!DOCTYPE>, no <head>, and no <script src="...tailwindcss...">. It assumes Tailwind is already set up in your project. To prototype standalone, wrap the snippet in your own HTML page and add the Tailwind Play CDN yourself.
Classes get purged in production and the table looks unstyled
Config issueIf the file holding the pasted snippet is not covered by your Tailwind content globs, the build strips the classes and the table renders with no styling. Add the file path to your Tailwind content array and rebuild.
Free tier upload
402 Pro requiredTailwind Table Export is a Pro-tier feature; the tool refuses to run on the Free tier. Upgrade to Pro (50 MB / 100,000 rows) or higher to use it.
Huge sheet produces a multi-megabyte snippet
Slow renderEvery data row becomes a <tr> with no truncation, so a 100,000-row sheet generates a 100,000-row table. The HTML is valid but the browser will be slow to render it. For large datasets, paginate or virtualise on the page rather than dumping the whole table inline.
Frequently asked questions
Does it include Tailwind's CDN script or a <link> tag?
No. The output is the table markup only — a <div class="overflow-x-auto"> wrapping a <table> with Tailwind utility classes. There is no <!DOCTYPE>, no <head>, and no CDN <script> or <link>. It assumes Tailwind is already configured in your project. To prototype standalone, add the Tailwind Play CDN to your own HTML page and paste the snippet inside it.
How many rows can it handle?
Pro processes up to 100,000 rows (50 MB), Pro-media up to 500,000 (200 MB), and Developer is unlimited (500 MB). The tool emits one <tr> per row with no truncation, so very large tables produce very large snippets that are slow to render in the browser — paginate for thousands of rows.
Can I customise the class strings in the UI?
Not directly. The UI exposes only two controls: style (striped/bordered/compact/minimal) and darkMode (on/off). To change padding, colours, or add classes, copy or download the HTML and edit the class attributes in your editor.
Which sheet does it use?
Only the first sheet (index 0). Other tabs are ignored, and there is no sheet picker. Move the data you want onto the first sheet, or save that tab as its own file, before exporting.
What becomes the table header?
Row 1 of the first sheet. Each cell in row 1 becomes a <th>. If row 1 holds a banner or title instead of real headers, that banner becomes your headings — delete leading non-header rows first.
Does dark mode style every element?
It appends dark:bg-gray-800 dark:text-gray-100 to the wrapper <div>, every <th>, and every <tr>. It does not add dark: classes to <td> or to the <table> element. If you need dark styling on cells specifically, add it by hand after export.
Is the output safe against HTML injection from cell content?
Yes. The generator escapes &, <, >, and " in every cell and header, so spreadsheet text like <script> renders as visible text rather than executing. The single quote (') is left unescaped, which is fine inside double-quoted HTML attributes and text nodes.
Does it preserve number and date formatting?
Cells are read as their formatted display text, so a date shown as 15/03/2026 exports as that string and a percentage shown as 42% exports as 42%. It does not export raw serial numbers. If you need raw values or standardised dates, normalise the sheet first (for example with the Excel date standardizer).
Can it accept a CSV instead of an .xlsx?
Yes. Both .xlsx and .csv are accepted. A CSV's first row is treated as headers exactly like an Excel sheet's first row.
Does my data get uploaded anywhere?
No. Parsing and HTML generation run entirely in your browser via SheetJS. The file is never sent to a server, which is why it is safe for customer lists and internal data.
Can I get a JSON, SQL, or Python version of the same data instead of HTML?
Yes — different tools in the same family handle those. For a Python dict/DataFrame use the Excel to Python generator; for an SVG chart use the Excel SVG dataviz tool. For SQL or Markdown, this family routes to the JSON tools (JSON to SQL, JSON to Markdown).
What filename does the download use?
The download is named table.html and contains the snippet exactly as shown in the preview. You can rename it after downloading.
Privacy first
Every JAD Excel tool runs entirely in your browser using SheetJS and ExcelJS. Your spreadsheets, formulas, and data never leave your device — verified by zero outbound network requests during processing.