Instant and dynamic HTML table creation with JavaScript

Reading Time: 4 minutes 🕑

Last updated: February 10, 2022.

Do you find hard-coding HTML tables tedious? The good news is you can spare yourself this effort by creating tables dynamically using JavaScript.

To start using the table generator function, copy and paste the code below into your project and call the function according to the usage notes.

Build notes that may be helpful to you in creating your own table generator function or customizing the one provided here are contained in notes alongside the code.

Using the JavaScript table generator function

Usage notes

Using tableCreate

tableCreate(rows, cols, thead, tfoot)

  1. rows: table rows (numeric)
  2. cols: table columns (numeric)
  3. thead: head title (string) or column titles (array)
  4. tfoot: foot title (string)

The return value of the function is the table. So it can be rendered to the DOM like this:

    <! --- Some DOM content --->
    <div id="table"></div>
     <! --- More DOM content --->
    document.getElementById('table').innerHTML = tableCreate(rows, cols, thead, tfoot)

Output examples

Example 1: Simple table

A simple table with a heading and five rows of data:

const data = ["United States","China","India","Russia","Germany"];

tableCreate(5,1, "Five large countries", "By JavaScript");

Example 2: Meal plan

A more complex table with multiple rows and columns as well as column titles.

The cells in the first column of the table have the class attribute col-left and so can be separately styled in CSS:

// Define data input
const data = ["Monday", "Cereal", "Steamed rice", "Baked Potatoes",
              "Tuesday", "Bagel", "Spaghetti bolognese", "Pasta salad",
              "Wednesday", "Oatmeal", "Pasta", "Burger",
              "Thursday", "Cereal", "Fish and chips", "Fried Rice",
              "Friday", "Fried breakfast", "Sandwiches", "Lasange"

// Define headings
const headings = ['', 'Breakfast', 'Lunch', 'Dinner']

/* Call tableCreate */
tableCreate(5,4,data,headings,'Created by JavaScript');

The code

Table generator function:

/* Defining the tableCreate function */
function tableCreate(rows, cols, data, thead, tfoot) {
  // 1) Create table and body elements
  let table = document.createElement('table')
  let tableBody = document.createElement('tbody')

  // 2) Optional header
  let headContent = document.createElement('thead')
  let tr = document.createElement('tr')

  // 2.1) Sets default behavior: Single cell header
  if (thead && Array.isArray(thead) == false) {
    let td = document.createElement('td')
    td.innerHTML = thead // Set header text to argument input
    td.setAttribute('colspan', cols) // Span header for as many cols as table

    headContent.append(tr) // append head row to thead element
    thead = headContent // Make this final value of thead
  // 2.2) If "split" is third argument: Creates a multi-cell header
  if (Array.isArray(thead)) {
    let i
    for (i = 0; i < cols; i++) {
      let td = document.createElement('td') = 'thead' + i
      td.innerHTML = thead[i]
      tr.append(td) // append multiple td to head row
    headContent.append(tr) // append head row to thead element
    thead = headContent // Make this final value of thead

  // 3) Optional footer (text is user input string)
  if (tfoot) {
    footElement = document.createElement('tfoot')
    tr = document.createElement('tr')
    td = document.createElement('td')
    td.innerHTML = tfoot // Set text to fourth argument input
    td.setAttribute('colspan', cols)
    tr.append(td) // Append single cell to row
    footElement.append(tr) // Append row to tfoot element
    tfoot = footElement // Make this final value of tfoot

  // 4) Create table body rows and cell with loops
  let i
  for (i = 0; i < rows; i++) {
    // Loop to create row
    let tr = document.createElement('tr')

    let id = i * cols // Nested loop to append cells to rows (first loop id = 0*5; second loop id = 1*5, etc)
    for (j = 0; j < cols; j++) {
      let td = document.createElement('td')
      id++ // increase id by 1 (first loop is 0+1 = 1)
      if (id == i * cols + 1) {
      td.innerHTML = id // print id in col cell
      td.setAttribute('id', 'cell' + id) // set id of element to id
      tr.append(td) // append col cell to table row
      // Repeats until j < column numbers entered by user

      if (data) {
        td.innerHTML = data[id - 1]


  // 5) Append head, body and footer
  if (thead) {
  if (tfoot) {

  // Show table in console

  // 6) Return a value for the function
  return table

CSS styling

/* import custom Open Sans font */
@import url('');
body {
    background: linear-gradient(#e66465, #9198e5);
    background-repeat: no-repeat;
    background-position: top left;
    height: 100vh;
    margin: 0px;
#table {
    display: flex;
    justify-content: center;
    margin-top: 3rem;
table {
    font-family: 'Open Sans', sans-serif;
    border-collapse: collapse;
    color: black;
thead {
    background-color: lightblue;
    font-weight: bold;
    border-bottom: 2px solid white;
th, td {
    padding: 0.5rem;
    padding-left: 3rem;
    padding-right: 3rem;
    text-align: center;
tbody tr td {
    padding: 0.5rem;
    padding-left: 0.8rem;
    padding-right: 0.8rem;
/* Even row styling */
tbody tr:nth-child(even) {
    background-color: #f2f2f2;
/* Odd row styling */
tbody tr:nth-child(odd) {
    background-color: white;
/* Left column styling */
.col-left {
    background-color: lightblue;
    color: black;
    font-weight: 400;
    border-top: 2px solid white;
    border-bottom: 2px solid white;
tfoot {
    background-color: rgb(206, 231, 240);
    font-size: 0.7rem;
    padding: 0.1rem;
    border-top: 2px solid white;
tfoot tr td {
    padding: 0.2rem;
    text-align: right;