Creating a dynamic HTML table with JavaScript

This tutorial will teach you how to create a dynamic HTML table through the use of Javascript and Document Object Model (DOM) manipulation. The number of table rows and cell content will vary depending on your data.

In this tutorial, I will be creating a scoreboard for a Javascript video game and the data will be coming from a fetch request. The source of the data for your application may be different, but the logic should still apply. This tutorial will include screenshots for the code, website rendering, and the full HTML at each step in the tutorial.

The copy-paste-friendly code is at the end. 🔥

The data for this HTML table comes from an SQLite database table. The number of rows will vary depending on the number of records in the scores table.

This is an example of the data we will be working with.This is an example of the data we will be working with.

HTML Table Tags:

An HTML table consists of one

element and one or more , and elements for additional styling options.

Tag Definitions:


, and elements.

This HTML table will also include the optional

tag defines an HTML table.


tag defines a row in an HTML table.


tag is used to group header content in an HTML table.


tag is used to group the body content in an HTML table.

We will be creating all the tags that are defined above through document method *document.createElement(tagName)* and we will append them to a

tag in our html file.

Most of the ‘classNames’ that you will see in the code are there for styling purposes and are completely optional.

The CSS styling will not be discussed, but it will be available for you to reference and test on your own.

The Tutorial:


that will contain our table is the following:

<div class='scoreboard'></div>

Steps to create the table:

  • Find the ‘scoreboard’ div with the document method *document.querySelector(selectors).*

  • Create an array of strings that holds the header values for the data that you are interested in displaying. I believe these are more representative of the data I am going to display and it allowed me to include units in brackets. (This is an optional step since you can use the object keys as the headers)

    let tableHeaders = [“Global Ranking”, “Username”, “Score”, “Time Alive [seconds]”, “Accuracy [%]”]

  • Creating the

tag defines a header cell in an HTML table.


tag defines a standard data cell in an HTML table.



  • Creating and appending the

  • element to the table. This contains the first element with all 5 of the strings in the ‘tableHeaders’ variable displayed above as the values inside the respective element to the table. This will allow us to append the tags that correspond to each score record in our scores table later.

  • Appending the

  • cell elements.

  • Creating and appending the

  • onto the ‘scoreboard’

    The function that achieves the steps outlined above.The function that achieves the steps outlined above.

    The rendering of the table (at this point).The rendering of the table (at this point).

    HTML for the ‘Scoreboard’ div and the dynamic HTML Table (at this point).HTML for the ‘Scoreboard’ div and the dynamic HTML Table (at this point).

    • Find the HTML table we created above with the document method *document.querySelector(selectors).*

    • Create all of the table body rows that represent each high score. These will be

    tags that will hold a
    tag for each one of the columns in your table. The following function will create a new row when given a score object.

    Example of the singleScore object that is being passed into the next function:

    singleScore = {
        "id": 6,
        "score": 115,
        "time_alive": 70.659,
        "accuracy": 17.1,
        "user_id": 1,
        "user": {
            "username": "daniel"

    The function that achieves the steps above.The function that achieves the steps above.

    Rendering of the full table.Rendering of the full table.

    Complete HTML for the ‘Scoreboard’ div and the dynamic HTML Table.Complete HTML for the ‘Scoreboard’ div and the dynamic HTML Table.

    Lastly, I mentioned that this example table relied on a fetch to receive its data. Here is the code for the fetch that supplies all the individual scores to the ‘appendScores’ function:

    I hope you have found this tutorial helpful. If you have any questions, feel free to ask them below.

    Here is a short video of the application that I created this specific table for!

    All of the code in the snippets:

    const scoreDiv = document.querySelector("div.scoreboard") // Find the scoreboard div in our html
    let tableHeaders = ["Global Ranking", "Username", "Score", "Time Alive [seconds]", "Accuracy [%]"]
    const createScoreboardTable = () => {
    while (scoreDiv.firstChild) scoreDiv.removeChild(scoreDiv.firstChild) // Remove all children from scoreboard div (if any)
    let scoreboardTable = document.createElement('table') // Create the table itself
    scoreboardTable.className = 'scoreboardTable'
    let scoreboardTableHead = document.createElement('thead') // Creates the table header group element
    scoreboardTableHead.className = 'scoreboardTableHead'
    let scoreboardTableHeaderRow = document.createElement('tr') // Creates the row that will contain the headers
    scoreboardTableHeaderRow.className = 'scoreboardTableHeaderRow'
    // Will iterate over all the strings in the tableHeader array and will append the header cells to the table header row
    tableHeaders.forEach(header => {
    let scoreHeader = document.createElement('th') // Creates the current header cell during a specific iteration
    scoreHeader.innerText = header
    scoreboardTableHeaderRow.append(scoreHeader) // Appends the current header cell to the header row
    scoreboardTableHead.append(scoreboardTableHeaderRow) // Appends the header row to the table header group element
    let scoreboardTableBody = document.createElement('tbody') // Creates the table body group element
    scoreboardTableBody.className = "scoreboardTable-Body"
    scoreboardTable.append(scoreboardTableBody) // Appends the table body group element to the table
    scoreDiv.append(scoreboardTable) // Appends the table to the scoreboard div
    // The function below will accept a single score and its index to create the global ranking
    const appendScores = (singleScore, singleScoreIndex) => {
    const scoreboardTable = document.querySelector('.scoreboardTable') // Find the table we created
    let scoreboardTableBodyRow = document.createElement('tr') // Create the current table row
    scoreboardTableBodyRow.className = 'scoreboardTableBodyRow'
    // Lines 72-85 create the 5 column cells that will be appended to the current table row
    let scoreRanking = document.createElement('td')
    scoreRanking.innerText = singleScoreIndex
    let usernameData = document.createElement('td')
    usernameData.innerText = singleScore.user.username
    let scoreData = document.createElement('td')
    scoreData.innerText = singleScore.score
    let timeData = document.createElement('td')
    timeData.innerText = singleScore.time_alive
    let accuracyData = document.createElement('td')
    accuracyData.innerText = singleScore.accuracy
    scoreboardTableBodyRow.append(scoreRanking, usernameData, scoreData, timeData, accuracyData) // Append all 5 cells to the table row
    scoreboardTable.append(scoreboardTableBodyRow) // Append the current row to the scoreboard table body
    const getScores = () => {
    fetch('http://localhost:3000/scores') // Fetch for all scores. The response is an array of objects that is sorted in decreasing order
    .then(res => res.json())
    .then(scores => {
    createScoreboardTable() // Clears scoreboard div if it has any children nodes, creates & appends the table
    // Iterates through all the objects in the scores array and appends each one to the table body
    for (const score of scores) {
    let scoreIndex = scores.indexOf(score) + 1 // Index of score in score array for global ranking (these are already sorted in the back-end)
    appendScores(score, scoreIndex) // Creates and appends each row to the table body

    All the CSS styling for the table in this tutorial:

    .scoreboardTable {
    padding: 0;
    margin: auto;
    border-collapse: collapse;
    width: 80%;
    text-align: center;
    color: whitesmoke;
    .scoreboardTableHeaderRow {
    color: darkorange;
    font-weight: bold;
    height: 50px;
    .scoreboardTableBodyRow:nth-child(odd){background-color: rgba(128, 128, 128, 0.050);}
    #latestUserScore {
    background-color: crimson;
    background-color: darkorange;
    .scoreboardTable tr td {
    height: 25px;

    Continue Learning