Sortable Markdown Tables: GitHub, GitLab, MkDocs and R Markdown
By MarkdownTables.com editorial teamUpdated
On this page
Can a Markdown table be sortable?
A Markdown pipe table describes rows and columns and nothing else. The Markdown table syntax has no flag for “sortable”, so a clickable header can only come from the place where the table is displayed: a feature of the renderer, or JavaScript on the page. That is why the answer differs by platform.
| Library | Stars | Released |
| :-------- | ----: | :------- |
| Alpha | 420 | 2021 |
| Bravo | 1310 | 2019 |
| Charlie | 85 | 2024 |
| Delta | 960 | 2022 || Library | Stars | Released |
|---|---|---|
| Alpha | 420 | 2021 |
| Bravo | 1310 | 2019 |
| Charlie | 85 | 2024 |
| Delta | 960 | 2022 |
On GitHub the headers can’t be clicked. To put the rows in order there, sort the source (below).
Open in editor : A table in source orderYou have two broad choices: make the displayed table sortable on a platform that can do it, or sort the rows in the Markdown before you publish. The second works everywhere, including Reddit and chat tools.
Every way to get a sortable table, by platform
| Where | Method | Setup |
|---|---|---|
| GitHub README, issues, wikis | Sort the source rows | Use the table sorter or a spreadsheet |
| GitLab | Sortable tables, json:table with sortable fields | Built in |
| MkDocs Material | tablesort script | extra_javascript plus a short JS file |
| Docusaurus, Hugo, Jekyll, custom sites | A JavaScript sort library or your own script | Load a script, run it on table elements |
| R Markdown, Quarto (HTML) | DT::datatable(), reactable::reactable() | Install the package |
| Jupyter | itables.show(df) or pandas sorting | Install itables |
| Obsidian | Dataview SORT, Bases, Advanced Tables | Plugin or core plugin setup |
| Anywhere with a spreadsheet | Sort the data, then convert to Markdown | CSV to Markdown table |
GitHub: no sorting, so sort the source
GitHub renders Markdown tables as static HTML and removes scripts, so a README table can't be sorted by the reader. A table you want in a specific order has to be in that order in the file. Sort by the column that readers care about, say stars, newest first, or alphabetical, and note the order in the sentence above the table.
| Library | Stars | Released |
| :-------- | ----: | :------- |
| Bravo | 1310 | 2019 |
| Delta | 960 | 2022 |
| Alpha | 420 | 2021 |
| Charlie | 85 | 2024 || Library | Stars | Released |
|---|---|---|
| Bravo | 1310 | 2019 |
| Delta | 960 | 2022 |
| Alpha | 420 | 2021 |
| Charlie | 85 | 2024 |
The Markdown table sorter does this in the browser: paste the table, click a column header in the grid (once for ascending, twice for descending), and copy the Markdown. It detects numeric columns, so 2 sorts before 10, and the header and delimiter rows stay in place. For a script in CI or a local workflow, sorting the body rows from the shell also works:
# Keep the header and delimiter rows, sort the data rows by column 2, descending
(head -n 2 table.md; tail -n +3 table.md | sort -t '|' -k3,3nr) > sorted.mdThis works only on tables whose cells contain no pipes. Cells containing \| split in the wrong place, and values such as 1,310 don't sort numerically with sort -n. Use the tool for tables with that kind of data. See the GitHub README tables guide for more on what renders there.
GitLab: sortable tables and json:table
GitLab renders sortable tables, and its json:table code block builds one from JSON. Mark each field that should sort with sortable: true; a top-level filter adds a search box. The GitLab Flavored Markdown docs list the full set of options, which can change between versions.
```json:table
{
"fields": [
{ "key": "library", "label": "Library", "sortable": true },
{ "key": "stars", "label": "Stars", "sortable": true },
{ "key": "released", "label": "Released", "sortable": true }
],
"items": [
{ "library": "Alpha", "stars": 420, "released": 2021 },
{ "library": "Bravo", "stars": 1310, "released": 2019 },
{ "library": "Charlie", "stars": 85, "released": 2024 }
],
"filter": true
}
```The data lives in JSON rather than pipes, so it is harder to diff and doesn't render on GitHub, where it shows as a code block. For a table that must read well in both places, keep a normal pipe table and sort it in the source. See the GitLab Markdown tables guide.
MkDocs Material: the tablesort recipe
Material for MkDocs documents a recipe that uses the tablesort library. Load the script, then initialize it on every table inside the article. The document$ subscription re-runs the code when instant navigation swaps the page, so sorting keeps working after the first click through the site.
# mkdocs.yml
extra_javascript:
- https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js
- javascripts/tablesort.js// docs/javascripts/tablesort.js
document$.subscribe(function () {
var tables = document.querySelectorAll("article table:not([class])")
tables.forEach(function (table) {
new Tablesort(table)
})
})The selector skips tables that have a class, so tables made by other components are left alone. For numbers and dates, add tablesort's number and date extensions; the core library compares text, as its README explains.
Docusaurus, Hugo, Jekyll and other sites
Docusaurus, Hugo, Jekyll and plain HTML pages have no built-in sorting. Two routes work on any of them. Add a library such as tablesort, DataTables or List.js and point it at your tables:
<script src="https://cdn.jsdelivr.net/npm/tablesort@5.3.0/dist/tablesort.min.js"></script>
<script>
document.querySelectorAll('table').forEach(function (table) {
new Tablesort(table);
});
</script>Or write a short script yourself. This version sorts text and numbers in the clicked column, and toggles between ascending and descending:
document.querySelectorAll('table').forEach(function (table) {
var body = table.tBodies[0];
table.querySelectorAll('th').forEach(function (th, col) {
th.style.cursor = 'pointer';
th.addEventListener('click', function () {
var dir = th.dataset.dir === 'asc' ? -1 : 1;
th.dataset.dir = dir === 1 ? 'asc' : 'desc';
var text = function (row) { return row.cells[col].textContent.trim(); };
Array.from(body.rows)
.sort(function (a, b) {
return dir * text(a).localeCompare(text(b), undefined, { numeric: true });
})
.forEach(function (row) { body.appendChild(row); });
});
});
});Headers made clickable with a plain click handler can't be reached with the keyboard. For a public site, use a library that handles keyboard focus and ARIA sort state, or wrap each header's text in a button. Hugo drops raw HTML, including inline <script>, unless markup.goldmark.renderer.unsafe is on, so load scripts from the theme's templates instead. Docusaurus needs the script in scripts in its config or a React component.
R Markdown, Quarto and Jupyter
R Markdown and Quarto can emit interactive tables when the output is HTML. DT::datatable() and reactable::reactable() sort by clicking a header. knitr::kable() writes a regular Markdown table, which is static.
```{r}
library(DT)
datatable(mtcars) # sortable, searchable, paged (HTML output)
```
```{r}
library(reactable)
reactable(mtcars) # sortable by default (HTML output)
```
```{r}
knitr::kable(head(mtcars)) # static Markdown table: not sortable
```Both packages need JavaScript, so they don't work in PDF or Word output, where a static kable() table is the right choice. In Jupyter, Markdown-cell tables are static. Show a DataFrame with itables to get click-to-sort, or sort with pandas and export Markdown:
import pandas as pd
from itables import show
df = pd.read_csv("libraries.csv")
show(df) # interactive table with click-to-sort headers
df.sort_values("stars", ascending=False).to_markdown("sorted.md", index=False)Obsidian: Dataview, Bases and sorting the source
Obsidian renders pipe tables as static HTML. For sorted output, query your notes with the Dataview plugin and put the order in the query; Bases, the core plugin for database-style views, lets you set sorting in the view. The Advanced Tables community plugin sorts the rows of a Markdown table in the editor, which changes the source. See Obsidian and Notion tables.
```dataview
TABLE stars, released
FROM "Libraries"
SORT stars DESC
```Sortable tables by platform
| Platform | Click to sort | Workaround |
|---|---|---|
| GitHub (GFM)Rendered tables are static, and scripts are removed from Markdown. | No | Yes: Sort the source rows |
GitLab (GLFM)Renders sortable tables. json:table blocks set sortable per field. Check GitLab’s docs for which views and versions apply. | Yes: json:table fields | Not applicable |
| ObsidianPlain Markdown tables are static. Dataview and Bases sort by query or view settings. | No | Yes: Dataview, Bases, Advanced Tables |
| VS Code previewStatic HTML table. | No | Yes: Sort the source |
| JupyterMarkdown-cell tables are static. Code output can be interactive. | No | Yes: itables, pandas |
R Markdown / Quarto (HTML)DT::datatable() and reactable::reactable() sort in the browser. knitr::kable() output is static. | Yes: DT, reactable | Not applicable |
| PandocTables are static. HTML output needs your own JavaScript. | No | Partly: JS in HTML output |
MkDocs MaterialThe theme documents a tablesort recipe. | Yes: tablesort recipe | Not applicable |
| Docusaurus / Hugo / JekyllNo built-in sorting. Load a JavaScript library or write a small script. | Partly: Add JS | Yes: Sort the source |
| Reddit, Slack, DiscordNo scripting and no sortable table element. | No | Yes: Sort the source |
✅ supported · ⚠️ partly or with a workaround · ❌ not supported · Last verified October 2026
“Sort the source” means reordering the Markdown rows before publishing. It works everywhere but only changes the order for everyone.
Common mistakes (broken vs. fixed)
Numbers sorted as text
| Library | Stars |
| :------ | ----: |
| Alpha | 100 |
| Bravo | 20 |
| Charlie | 3 || Library | Stars |
|---|---|
| Alpha | 100 |
| Bravo | 20 |
| Charlie | 3 |
A text sort puts 100, 20, 3 in that order. Use a numeric sort (the sorter tool, localeCompare with numeric: true, or tablesort’s number extension).
A script in a README
| Library | Stars |
| ------- | ----: |
| Alpha | 420 |
<script src="https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js"></script>
<script>new Tablesort(document.querySelector('table'))</script>GitHub strips <script>, so the table stays unsorted and the tags don't appear. Use scripts only on sites you publish yourself.
Sorting a table with merged cells
Script-based sorters move whole rows. A table with rowspan or colspan breaks, because the spanned cell belongs to several rows. Keep sortable tables flat; the nested tables page shows flat alternatives to grouped layouts.
Formatted values
Cells like $1,200, 2 MB or 12 Jan sort in surprising ways. Either keep the column in a sortable format (numbers without units, ISO dates such as 2026-10-11) and put the unit in the header, or use a library that reads a separate sort key.
When to use a database table or spreadsheet
- The table is data readers will filter and sort. Publish it as a page with
DataTables,reactableoritables, and link to it from the README. - The data lives in a spreadsheet. Share the sheet or a CSV file, and keep a sorted Markdown snapshot with the CSV to Markdown table converter.
- The table is a short reference. Sort it once by the most useful column and add a sentence that says how it is ordered.
- The table is long. Hide it in a collapsible section or split it into smaller tables.
Frequently asked questions
Can you make a Markdown table sortable?
Not in the Markdown itself: pipe tables are static data. Sorting comes from the renderer or from JavaScript added to the page. GitLab and MkDocs Material (with a recipe) offer click-to-sort, GitHub does not, and you can always sort the rows in the source.
Is there a sortable table in GitHub Markdown?
No. GitHub renders tables as static HTML and removes scripts, so headers can’t be clicked to sort. Sort the rows before you commit, with the Markdown table sorter or a spreadsheet, or link to a published page that has a sortable table.
Does GitLab support sortable Markdown tables?
Yes: GitLab renders sortable tables, and json:table code blocks define fields with "sortable": true for click-to-sort headers. Check the GitLab Flavored Markdown docs for the options in your version and where they render.
How do I make a sortable table in MkDocs?
Follow the Material for MkDocs recipe: add the tablesort script and a small tablesort.js to extra_javascript in mkdocs.yml, then call new Tablesort(table) on each table. Include tables as plain Markdown; no per-table setup is needed.
How do I make a sortable table in R Markdown?
Use DT::datatable(df) or reactable::reactable(df) in a code chunk with HTML output; both sort by clicking a column header. knitr::kable() produces a plain Markdown table, which is static, and neither package works in PDF or Word output.
Can Obsidian sort a Markdown table?
Plain Markdown tables in Obsidian aren’t sortable in the rendered view. The Dataview plugin sorts with a SORT clause in the query, Bases is built for sortable database views, and the Advanced Tables plugin can sort the rows of a Markdown table in the source.
How do I sort a Markdown table by column?
Paste it into the Markdown table sorter, click a column header, and copy the result. You can also sort the data in a spreadsheet and convert it back with the CSV to Markdown table tool. Keep the header and delimiter rows in place.