How to Create a Sortable HTML Table with JavaScript

1. Placing Content With HTML

The <table> tag is the semantic HTML tag used for displaying data on a webpage. We’ll be placing our <table> tag within a table-container div which will allow us include some responsive styling in CSS.

Our table will contain the table header, thead and table content, tbody tags. In our table header, we’ll include buttons in each th cell which will be used to handle the sorting functionality. The cells for table content will added in with JavaScript using the data from our JSON response.

2. Making a Responsive Table with CSS

One of the more common problems of working with HTML tables is a lack of responsiveness. The table might have a cell overlap problem or go beyond the boundaries of the full page.

We can get rid of these issues by placing the table in a table-container that’s the width of the full page with an overflow scroll property. That way, the table is always only as wide as the full page and there’s no need to shrink the cells thanks to the scrollable overflow. We’ll also include min-width properties on our table cells to avoid text wrapping.

table flowing beyond the boundaries of the pagetable flowing beyond the boundaries of the pagetable flowing beyond the boundaries of the page
Table overflowing beyond the viewport without becoming squashed

This is the CSS needed to make our table scrollable:

We can then add the rest of our styling:

3. Placing JSON Data in an HTML Table

For this example, we’ll be working with a mock parsed JSON response. This is what our data looks like:

We’ll be placing the data within our <tbody id="table-content"> tag so we’ll target that element in JavaScript;

The row content will be based on each object within our response.pokedata. Let’s define a function for creating a new row based on the object data:

In this function, we use the Object.keys() method to get the object keys as an array. This is what the returned value looks like:

Object.keys(obj) (9) ['name', 'type', 'hp', 'attack', 'defense', 'spAttack', 'spDefense', 'speed', 'total']Object.keys(obj) (9) ['name', 'type', 'hp', 'attack', 'defense', 'spAttack', 'spDefense', 'speed', 'total']Object.keys(obj) (9) ['name', 'type', 'hp', 'attack', 'defense', 'spAttack', 'spDefense', 'speed', 'total']
Object.keys() returns an array containing the object keys

Once we’ve gotten the array of the object keys, we loop through each key using the .map() method. The map method carries out the function we’ve passed into it on each item in the array.

In this map function, we’re creating a new cell for each item in the array and setting the cell innerHTML as the corresponding object key value. 

Mapping through the object using the keys arrayMapping through the object using the keys arrayMapping through the object using the keys array
Mapping through the object using the keys array

Finally, we append the cell we’ve created to the row defined at the beginning of the function using the .appendChild() method.

Now that we have our row creating function, we’ll define a function to loop through the response.pokedata array and append each new row to our tableContent element.

We’ll pass our getTableContent function into an event listener so the content is added to the table once the page loads.

4. Sorting Data With JavaScript

Now that we have created our table, let’s add the sorting functionality. In our HTML, we included buttons in the header cells which had the object keys as their id. Let’s target those buttons now:

We want to handle sorting the data according to which button is clicked and also include a feature that toggles the sorting direction (ascending or descending) when the button is clicked.

We can use the .sort() method to handle sorting the data in our response.pokedata array. The sort method takes in a function comparing two different params and sorts them according to the function response:





compareFunction(a, b) return value sort order
> 0 sort a after b
< 0 sort a before b
=== 0 keep original order of a and b

Source: MDN

Another thing to note about the sort method is that it mutates the original array that it operates on. This means it changes the value of our original array.

Array mutation when using .sort()

We can avoid mutating our original array by using the spread syntax […]

Avoiding array mutation by using the spread syntax

Now we can create our sorting function. This is what the logic for our sorting function will look like:

  1. Clear the content in the tableContent element
  2. Sort the data according to the selected param and direction
  3. Append the sorted data to our tableContent using the getTableContent function

Our sort function takes three parameters:

  • data: the array to be sorted
  • param: the value being used to sort the array
  • direction: sort the array in either ascending or descending order. The default paramater value is set to “asc”.

We clear the content in our tableContent element by setting the innerHTML to a blank string. We then use the .sort() method and direction parameter to determine how the data should be sorted. We reverse the compare function in order to sort in descending order. Using the compare function this way lets us sort the data regardless of the type value (string, integer, float etc)

Finally, we pass the sortedData as the new value in our table content.

Now we’ll pass our sort function into a click event listener for our table buttons and also handle toggling the sort direction. 

In this function, we handle the toggling by setting a data-dir attribute on our buttons to determine the sorting direction. We’ll also update our CSS to display an icon next to the button depending on the sorting direction:

We don’t want to have the icons show up on all previously clicked buttons so we’ll define a resetButtons function that removes the data-dir attribute on any button that’s not the button clicked.

We’ll pass that function into our button event listener to reset the previous buttons whenever a new button is clicked

Conclusion

And with that, we’re done! We’ve created a sortable table using only vanilla JavaScript!