MDX Notes
How to build tables in MDX — basic syntax, alignment tricks, real-world examples, and when tables are actually the right choice.
Tables are for structured data. Rows and columns. MDX uses standard Markdown table syntax, and because it's MDX, you can also drop in React components when you need sorting, filtering, or responsive behavior.
Let's start simple.
Basic Table Syntax
Pipes (|) separate columns. Hyphens (-) separate the header from the body:
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1 | Cell 2 | Cell 3 |
| Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 || Header 1 | Header 2 | Header 3 |
| Cell 1 | Cell 2 | Cell 3 |
|---|---|---|
| Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 |
Minimal Syntax
You don't technically need the outer pipes or aligned spacing:
Header 1 | Header 2 | Header 3
--- | --- | ---
Cell 1 | Cell 2 | Cell 3
Cell 4 | Cell 5 | Cell 6But honestly, the full syntax is way easier to read in source. Most formatters will auto-align columns anyway, so just use pipes everywhere.
Column Alignment
You control alignment with colons (:) in the separator row:
| Left Aligned | Center Aligned | Right Aligned |
|:-------------|:--------------:|--------------:|
| Left | Center | Right |
| Text | Text | Text |
| Here | Here | Here |Here's the rule:
:---or---→ Left aligned (this is the default):---:→ Center aligned---:→ Right aligned
A Real Example: Component Props
This is how you'd document props for a component — types centered, defaults centered, descriptions left-aligned:
| Property | Type | Default | Description |
|:---------|:----:|:-------:|:------------|
| name | string | — | Component display name |
| size | number | `16` | Size in pixels |
| disabled | boolean | `false` | Whether the component is disabled |
| onClick | function | — | Click event handler |Numbers Should Be Right-Aligned
When you're showing money, counts, or any numeric data — right-align it. That's how spreadsheets work, and it's easier to scan:
| Product | Q1 Sales | Q2 Sales | Q3 Sales |
|:---------------|----------:|----------:|----------:|
| Widget Pro | $12,450 | $15,230 | $18,900 |
| Gadget Plus | $8,300 | $9,100 | $11,200 |
| Tool Master | $22,100 | $24,500 | $27,800 |
| **Total** | **$42,850** | **$48,830** | **$57,900** |Formatting Within Tables
You can use bold, italic, strikethrough, inline code, links, and emoji inside cells:
API Endpoints Table
This comes up constantly in real docs:
| Method | Endpoint | Response |
|:-------|:---------|:---------|
| `GET` | `/api/users` | Array of users |
| `POST` | `/api/users` | Created user |
| `PUT` | `/api/users/:id` | Updated user |
| `DELETE` | `/api/users/:id` | Success message |Complex Tables
Tables with Long Content
Sometimes cells have a lot of text. That's fine — let them wrap:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `apiKey` | `string` | Your unique API key obtained from the developer dashboard. Required for all authenticated requests. |
| `timeout` | `number` | Maximum time in milliseconds to wait for a response before throwing a timeout error. Defaults to 30000. |
| `retries` | `number` | Number of retry attempts for failed requests. Uses exponential backoff between retries. Defaults to 3. |Multi-Line Cells
Markdown tables don't support actual line breaks in cells. But you can fake it with <br/>:
| Command | Description |
|:--------|:------------|
| `build` | Compiles the project<br/>Outputs to `./dist` folder<br/>Runs type checking |
| `dev` | Starts development server<br/>Enables hot module reload<br/>Opens browser automatically |
| `test` | Runs test suite<br/>Generates coverage report |Wide Tables
Got a table with tons of columns? Wrap it so it scrolls on small screens:
<div style={{ overflowX: 'auto' }}>
| Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | Col 6 | Col 7 | Col 8 |
|-------|-------|-------|-------|-------|-------|-------|-------|
| Data | Data | Data | Data | Data | Data | Data | Data |
| Data | Data | Data | Data | Data | Data | Data | Data |
</div>Responsive Tables
Scrollable Table Wrapper
For anything beyond 4-5 columns, you probably want a wrapper component:
import { ResponsiveTable } from '../components/ResponsiveTable'
<ResponsiveTable>
| Browser | Version | Support | Release Date | Engine |
|:--------|:--------|:--------|:-------------|:-------|
| Chrome | 120+ | Full | 2023-12-05 | Blink |
| Firefox | 121+ | Full | 2023-12-19 | Gecko |
| Safari | 17.2+ | Partial | 2023-12-11 | WebKit |
| Edge | 120+ | Full | 2023-12-07 | Blink |
</ResponsiveTable>// components/ResponsiveTable.jsx
export function ResponsiveTable({ children }) {
return (
<div className="responsive-table-wrapper" role="region" aria-label="Scrollable table" tabIndex={0}>
{children}
</div>
)
}Card Layout on Mobile
This is a nice pattern — table on desktop, cards on phones:
Table Components
Full HTML Table (When Markdown Can't Do It)
Need merged cells? Markdown tables can't handle rowSpan or colSpan. Use HTML:
<table>
<thead>
<tr>
<th rowSpan={2}>Name</th>
<th colSpan={2}>Scores</th>
</tr>
<tr>
<th>Math</th>
<th>Science</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>95</td>
<td>88</td>
</tr>
<tr>
<td>Bob</td>
<td>82</td>
<td>91</td>
</tr>
</tbody>
</table>Comparison Table Component
Pricing pages, feature matrices — you've seen these everywhere:
Data Table with Props
Pass data as props and let the component handle rendering:
Sortable Tables
Markdown tables are static. But in MDX, you can make them clickable and sortable:
How to Build One
Here's a basic implementation. Nothing fancy — just useState and .sort():
When to Use Tables (And When Not To)
Tables are great for:
- Comparing items across the same attributes
- Numeric data, specs, pricing
- Config options with types and defaults
- API endpoint docs
- Feature comparison matrices
Use a list instead when:
{/* ❌ BAD — Simple data forced into a table */}
| Requirement |
|-------------|
| Node.js 18+ |
| npm 9+ |
| Git 2.0+ |
{/* ✅ GOOD — A simple list is more appropriate */}
**Requirements:**
- Node.js 18+
- npm 9+
- Git 2.0+If you've got a single column, it's not really a table. It's a list.
Use definition lists instead when:
{/* ❌ BAD — Key-value pairs in a table */}
| Term | Definition |
|------|------------|
| API | Application Programming Interface |
| SDK | Software Development Kit |
{/* ✅ GOOD — Definition list is more semantic */}
<dl>
<dt>API</dt>
<dd>Application Programming Interface</dd>
<dt>SDK</dt>
<dd>Software Development Kit</dd>
</dl>Just write prose when:
You have 2-3 items with short descriptions. A sentence is clearer than a table with two rows.
Best Practices
- Always include headers — A table without headers is just a grid of confusion.
- Keep it under 6-7 columns — Too wide? Split into multiple tables.
- Right-align numbers, left-align text — This isn't a style choice, it's readability.
- Add a caption or heading — Tell people what they're looking at.
- Think about mobile — Wide tables need scroll wrappers.
- Keep cells short — Long paragraphs don't belong in table cells.
Common Mistakes
Inconsistent Column Counts
{/* ❌ BAD — Rows have different numbers of cells */}
| A | B | C |
|---|---|---|
| 1 | 2 |
| 4 | 5 | 6 | 7 |
{/* ✅ GOOD — Consistent column count */}
| A | B | C |
|---|---|---|
| 1 | 2 | — |
| 4 | 5 | 6 |Missing Separator Row
{/* ❌ BAD — No separator between header and body */}
| Header 1 | Header 2 |
| Cell 1 | Cell 2 |
{/* ✅ GOOD — Separator row required */}
| Header 1 | Header 2 |
|----------|----------|
| Cell 1 | Cell 2 |Pipe Characters in Cell Content
{/* ❌ BAD — Unescaped pipe breaks the table */}
| Command | Example |
|---------|---------|
| OR | a | b |
{/* ✅ GOOD — Escape the pipe */}
| Command | Example |
|---------|---------|
| OR | a \| b |Cramming Too Much Into One Table
{/* ❌ BAD — Too much data crammed into a table */}
{/* Consider breaking into multiple smaller tables or using a component */}
{/* ✅ GOOD — Split complex tables */}
{/* Table 1: Basic properties */}
{/* Table 2: Advanced properties */}
{/* Table 3: Event handlers */}Quick Reference
| Feature | Syntax | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Basic table | `\ | H \ | H \ | + \ | ---\ | ---\ | + \ | C \ | C \ | ` |
| Left align | :--- | |||||||||
| Center align | :---: | |||||||||
| Right align | ---: | |||||||||
| Escape pipe | `\ | ` | ||||||||
| Multi-line cell | <br/> | |||||||||
| Spanning cells | HTML colSpan/rowSpan |
That's tables. Use them when you have real structured data to show. Don't force everything into a grid just because you can.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Tables in MDX.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this MDX Tutorial topic.
Search Terms
mdx-tutorial, mdx tutorial, mdx, tutorial, basics, tables, tables in mdx
Related MDX Tutorial Topics