HTML Table Sorting With JavaScript
Making a cool HTML table that can be sorted is a great way to make your website more fun for users. With JavaScript, you can add a sorting feature that lets people click on the headers to organize the table in different ways.
Demo HTML Table Sorting
When you click on a header in the table, the rows will be sorted based on the content of that column in ascending order. Clicking on it again will switch to descending order. included icons indicating sort direction
User Name | Age | Country |
---|---|---|
Joan | 30 | USA |
Sonia | 25 | India |
Maria Garcia | 28 | Spain |
Bella | 35 | Japan |
Table Sorting Function With Sort Direction Icons
An existing HTML table allows users a sorting option. Insert the following JavaScript code into your web page.
Below is the full code for sorting tables using HTML, CSS, and JavaScript. Feel free to copy and paste this code directly onto your webpage without requiring any external library code. You can even make live edits by clicking on the edit button provided
const tableSort = (tableId) => {
const table = document.getElementById(tableId);
if (!table) {
console.error(`Table with ID "${tableId}" not found`);
return;
}
const thead = table.querySelector("thead");
const tbody = table.querySelector("tbody");
if (!thead || !tbody) {
console.error("Table must have <thead> and <tbody>");
return;
}
const headers = thead.querySelectorAll("th");
if (headers.length === 0) {
console.error("No table headers found");
return;
}
// Initialize sorting direction for each column
const sortDirections = Array(headers.length).fill("asc");
const getCellValue = (row, column) => {
const cell = row.children[column];
// Handle cases where cell is not found
if (!cell) return '';
const cellValue = cell.textContent.trim();
return isNaN(cellValue) ? cellValue : parseFloat(cellValue);
};
const sortTableByColumn = (column, direction) => {
const rows = Array.from(tbody.querySelectorAll("tr"));
rows.sort((a, b) => {
const cellA = getCellValue(a, column);
const cellB = getCellValue(b, column);
const order = direction === "asc" ? 1 : -1;
if (typeof cellA === 'number' && typeof cellB === 'number') {
return order * (cellA - cellB);
} else {
return order * cellA.toString().localeCompare(cellB);
}
});
rows.forEach(row => tbody.appendChild(row));
};
const handleHeaderClick = (index) => {
sortTableByColumn(index, sortDirections[index]);
sortDirections[index] = sortDirections[index] === "asc" ? "desc" : "asc";
updateHeaderClasses();
};
const updateHeaderClasses = () => {
headers.forEach((header, index) => {
header.classList.remove("sort-asc", "sort-desc");
header.classList.add(sortDirections[index] === "asc" ? "sort-asc" : "sort-desc");
});
};
// Attach click event listeners to each header cell
headers.forEach((header, index) => {
header.addEventListener("click", () => handleHeaderClick(index));
});
};
<table class="my-table" id="sortable-table">
<thead>
<tr>
<th>User Name</th>
<th>Age</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr>
<td>Joan</td>
<td>30</td>
<td>USA</td>
</tr>
<tr>
<td>Sonia</td>
<td>25</td>
<td>India</td>
</tr>
<tr>
<td>Maria Garcia</td>
<td>28</td>
<td>Spain</td>
</tr>
</tbody>
</table>
.my-table {
border-collapse: collapse;
width: 100%;
font-family: Arial, Helvetica, sans-serif;
}
.my-table tr {
background-color: #ffffff;
color: #000;
}
.my-table th {
padding: 10px 10px;
border: solid 1px #ccc;
text-align: center;
font-size: 12px;
font-weight: bold;
cursor: pointer;
user-select: none;
}
.my-table td {
border: solid 1px #ccc;
font-size: 13px;
padding: 10px 10px;
text-align: center;
}
.my-table thead>tr {
background-color: #e9e9e9;
}
.my-table>tbody>tr:hover {
background-color: #faffe3;
}
.my-table th::after {
content: "";
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIHZpZXdCb3g9IjAgMCAzMjAgNTEyIiAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTM3LjQgNDEuNGMxMi41LTEyLjUgMzIuOC0xMi41IDQ1LjMgMGwxMjggMTI4YzkuMiA5LjIgMTEuOSAyMi45IDYuOSAzNC45cy0xNi42IDE5LjgtMjkuNiAxOS44SDMyYy0xMi45IDAtMjQuNi03LjgtMjkuNi0xOS44cy0yLjItMjUuNyA2LjktMzQuOWwxMjgtMTI4em0wIDQyOS4zbC0xMjgtMTI4Yy05LjItOS4yLTExLjktMjIuOS02LjktMzQuOXMxNi42LTE5LjggMjkuNi0xOS44SDI4OGMxMi45IDAgMjQuNiA3LjggMjkuNiAxOS44czIuMiAyNS43LTYuOSAzNC45bC0xMjggMTI4Yy0xMi41IDEyLjUtMzIuOCAxMi41LTQ1LjMgMHoiLz48L3N2Zz4=);
background-repeat: no-repeat;
width: 10px;
height: 10px;
display: inline-block;
margin-left: 5px;
}
.my-table th.sort-asc::after {
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIHZpZXdCb3g9IjAgMCAzMjAgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xODIuNiA0NzAuNmMtMTIuNSAxMi41LTMyLjggMTIuNS00NS4zIDBsLTEyOC0xMjhjLTkuMi05LjItMTEuOS0yMi45LTYuOS0zNC45czE2LjYtMTkuOCAyOS42LTE5LjhIMjg4YzEyLjkgMCAyNC42IDcuOCAyOS42IDE5LjhzMi4yIDI1LjctNi45IDM0LjlsLTEyOCAxMjh6Ii8+PC9zdmc+);
}
.my-table th.sort-desc::after {
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJjdXJyZW50Q29sb3IiIHZpZXdCb3g9IjAgMCAzMjAgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xODIuNiA0MS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMGwtMTI4IDEyOGMtOS4yIDkuMi0xMS45IDIyLjktNi45IDM0LjlzMTYuNiAxOS44IDI5LjYgMTkuOEgyODhjMTIuOSAwIDI0LjYtNy44IDI5LjYtMTkuOHMyLjItMjUuNy02LjktMzQuOWwtMTI4LTEyOHoiLz48L3N2Zz4=);
}
Usage
// Initialize table sorting once the document is fully loaded
document.addEventListener('DOMContentLoaded', () => {
tableSort("sortable-table");
});
Try it yourself edit and preview live
Edit Code