Learn how to create a time table generator using HTML, CSS, and JavaScript with this easy step-by-step guide. Perfect for beginners and web developers.
Table of Contents
Creating a time table generator can be a fun and practical project, especially for beginners in web development. With this project, you'll learn how to design a time table layout using HTML, style it with CSS, and add dynamic functionality using JavaScript. Whether you're a student looking to organize your study hours or a developer sharpening your coding skills, this step-by-step guide will help you create a simple yet effective time table generator.
Prerequisites:
Before diving into the project, you should have a basic understanding of:
- HTML (to structure the page)
- CSS (to style the page)
- JavaScript (to add interactivity)
You can use any code editor like Visual Studio Code, and you should be able to run your code in a web browser (Chrome, Firefox, etc.).
Source Code
Step 1 (HTML Code):
The first step is to create the basic structure for your timetable generator. Open your code editor and create an HTML file named index.html.
In this code, we have the basic HTML structure with a heading, a table element to hold the timetable, and links to external CSS and JavaScript files.
Below is an explanation of the key components of the HTML code:
HTML Structure:
<!DOCTYPE html>
: This tells the browser that the document is an HTML5 document.<html lang="en">
: Defines the root element of the HTML page and sets the language of the document to English.<head>
:<meta charset="UTF-8">
: Sets the character encoding to UTF-8, which supports a wide range of characters.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Ensures the page is responsive and scales correctly on different devices.<title>Timetable Generator</title>
: Sets the title of the page, which appears on the browser tab.<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
: Links to the Google Fonts API to use the "Roboto" font family.<link rel="stylesheet" href="styles.css">
: Links an external CSS file (styles.css
) for styling.
<body>
:- The body contains the visible content of the page.
Main Content:
<div class="container">
: A container for the form and the timetable table.<h1 class="title">Timetable Generator</h1>
: A heading for the page, titled "Timetable Generator."- Form Section (
<form id="timetable-form">
):- Users can input the details of a subject they want to add to the timetable:
- Subject Field (
<input type="text" id="subject">
): A text input for entering the subject name. - Start and End Time (
<input type="time" id="start-time">
,<input type="time" id="end-time">
): Time inputs to define the start and end times for the subject. - Days Checkboxes (
<input type="checkbox" value="Monday">
): Checkboxes for selecting the days when the subject will be scheduled. Users can choose any combination of days from Monday to Saturday.
- Subject Field (
- Button (
<button type="submit" class="btn">
): A button labeled "Add to Timetable" to submit the form and add the details to the timetable.
- Users can input the details of a subject they want to add to the timetable:
- Table Section (
<table id="timetable">
):- A table for displaying the timetable with days of the week as columns.
- The
<thead>
contains the headers (<th>
) for the time slots and the days from Monday to Saturday. - The
<tbody>
is initially empty but will be populated dynamically via JavaScript with the user’s input.
External Files:
- CSS File (
styles.css
): The file that defines the styling (not included in this code but linked for customizing the look of the form, table, etc.). - JavaScript File (
script.js
): A script (also not shown here) to handle functionality such as capturing user input, adding data to the table, and managing the timetable entries.
Step 2 (CSS Code):
Next, create a new file named styles.css. In this file, we will add some simple CSS styles to make our time table look clean and organized. Here's an explanation of the CSS code:
Global Styles
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
- The
*
selector targets all elements, resetting their defaultmargin
andpadding
to0
to ensure consistent layout. box-sizing: border-box
ensures that padding and borders are included in the element’s total width and height.
Body Styles
body {
font-family: 'Roboto', sans-serif;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
padding: 20px;
}
font-family: 'Roboto', sans-serif;
applies the Roboto font to the entire page, falling back to a sans-serif font if unavailable.background-color: #f4f4f9;
sets a light gray background.display: flex; justify-content: center; align-items: center;
centers content horizontally and vertically.height: 100vh;
makes the body fill the full height of the viewport.padding: 20px;
adds space around the content to prevent it from touching the edges.
Container Styles
.container {
max-width: 800px;
background-color: #fff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.container
is a centered box with a maximum width of 800px.background-color: #fff;
gives it a white background.padding: 30px;
adds space inside the container.border-radius: 12px;
rounds the corners.box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
adds a subtle shadow for a 3D effect.
Title Styles
.title {
font-size: 2rem;
text-align: center;
margin-bottom: 20px;
color: #333;
}
.title
applies to headings.font-size: 2rem;
makes the text large.text-align: center;
centers the title text.margin-bottom: 20px;
adds space below the title.color: #333;
sets a dark gray text color.
Form Group Styles
.form-group {
margin-bottom: 15px;
}
.form-group
applies spacing to form sections, giving them15px
margin at the bottom.
Label Styles
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 500;
color: #555;
}
.form-group label
makes labels block-level elements, ensuring they appear above input fields.margin-bottom: 5px;
adds space below the label.font-weight: 500;
makes the font slightly bold.color: #555;
sets a medium gray text color.
Input and Button Styles
input[type="text"], input[type="time"], .btn {
width: 100%;
padding: 10px;
border-radius: 6px;
border: 1px solid #ddd;
font-size: 1rem;
}
- Targets text, time inputs, and buttons.
width: 100%;
makes them stretch to fill the width of their container.padding: 10px;
adds space inside the elements.border-radius: 6px;
rounds the corners slightly.border: 1px solid #ddd;
adds a light border.font-size: 1rem;
ensures consistent text size.
Checkbox Styles
input[type="checkbox"] {
margin-right: 10px;
}
- Adds
10px
space to the right of checkboxes, separating them from labels.
Checkbox Group Styles
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.checkbox-group
makes checkboxes appear next to each other (flex
).gap: 10px;
adds space between checkboxes.
Button Styles
.btn {
background-color: #4CAF50;
color: #fff;
border: none;
cursor: pointer;
font-weight: 500;
margin-top: 10px;
}
.btn:hover {
background-color: #45a049;
}
.btn
applies to buttons.background-color: #4CAF50;
gives the button a green background.color: #fff;
sets white text.border: none;
removes the default border.cursor: pointer;
changes the mouse cursor to a pointer on hover.font-weight: 500;
makes the button text bold.margin-top: 10px;
adds space above the button.hover
state changes the background to a darker green when hovered.
Timetable Styles
.timetable {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.timetable th, .timetable td {
padding: 12px;
text-align: center;
border: 1px solid #ddd;
}
.timetable th {
background-color: #4CAF50;
color: white;
font-weight: 500;
}
.timetable tr:nth-child(even) {
background-color: #f2f2f2;
}
.timetable tr:hover {
background-color: #ddd;
}
.timetable
styles tables.border-collapse: collapse;
removes space between table cells.th
(header) andtd
(data) cells have padding for spacing, center-aligned text, and light borders.th
cells have a green background with white text.- Even rows alternate with a light gray background for readability.
- Rows change color on hover for interactivity.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
background-color: #fff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.title {
font-size: 2rem;
text-align: center;
margin-bottom: 20px;
color: #333;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 500;
color: #555;
}
input[type="text"], input[type="time"], .btn {
width: 100%;
padding: 10px;
border-radius: 6px;
border: 1px solid #ddd;
font-size: 1rem;
}
input[type="checkbox"] {
margin-right: 10px;
}
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.btn {
background-color: #4CAF50;
color: #fff;
border: none;
cursor: pointer;
font-weight: 500;
margin-top: 10px;
}
.btn:hover {
background-color: #45a049;
}
.timetable {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.timetable th, .timetable td {
padding: 12px;
text-align: center;
border: 1px solid #ddd;
}
.timetable th {
background-color: #4CAF50;
color: white;
font-weight: 500;
}
.timetable tr:nth-child(even) {
background-color: #f2f2f2;
}
.timetable tr:hover {
background-color: #ddd;
}
Step 3 (JavaScript Code):
Now, it's time to add functionality using JavaScript. Here's a detailed breakdown:
1. Form Submission Handling
document.getElementById('timetable-form').addEventListener('submit', function (e) {
e.preventDefault();
- This line listens for the "submit" event of the form with the ID
timetable-form
. e.preventDefault();
prevents the form from submitting the traditional way (i.e., reloading the page). Instead, it allows custom JavaScript functionality to run.
2. Form Data Collection
const subject = document.getElementById('subject').value;
const startTime = document.getElementById('start-time').value;
const endTime = document.getElementById('end-time').value;
const selectedDays = getSelectedDays();
- It collects values from input fields (
subject
,start-time
,end-time
) and stores them in variables. getSelectedDays()
is called to retrieve the days selected by the user (checkboxes).
3. Validation Check
if (subject && startTime && endTime && selectedDays.length > 0) {
addTimetableEntry(subject, startTime, endTime, selectedDays);
} else {
alert("Please fill in all the fields.");
}
- Checks if all fields (
subject
,startTime
,endTime
, and at least one selected day) are filled. - If valid, it calls
addTimetableEntry()
to add the timetable entry; otherwise, an alert pops up to ask the user to complete all fields.
4. Resetting the Form
this.reset();
- Resets the form fields after submission to clear the input for the next entry.
5. Get Selected Days
function getSelectedDays() {
const days = document.querySelectorAll('#days input[type="checkbox"]:checked');
return Array.from(days).map(day => day.value);
}
- This function collects all checked checkboxes (days) from the form.
- It converts the NodeList of checked checkboxes into an array using
Array.from()
, then maps this array to return their values (e.g., "Monday", "Tuesday").
6. Add Timetable Entry
function addTimetableEntry(subject, startTime, endTime, selectedDays) {
const timetableBody = document.querySelector('#timetable tbody');
let rowExists = false;
let targetRow;
- Gets the table body (
#timetable tbody
) where new timetable entries will be added. - Initializes variables
rowExists
to check if a time slot already exists andtargetRow
to store the row if found.
7. Check if Time Slot Exists
Array.from(timetableBody.rows).forEach(row => {
const rowTime = row.cells[0].textContent;
if (rowTime === `${startTime} - ${endTime}`) {
rowExists = true;
targetRow = row;
}
});
- Loops through existing rows in the timetable and checks if a row with the same
startTime
andendTime
already exists. - If found, sets
rowExists
totrue
and stores that row intargetRow
.
8. Update or Add a New Row
if (rowExists) {
selectedDays.forEach(day => {
const dayIndex = getDayIndex(day);
targetRow.cells[dayIndex].innerHTML = subject;
});
} else {
const newRow = document.createElement('tr');
newRow.innerHTML = `<td>${startTime} - ${endTime}</td><td></td><td></td><td></td><td></td><td></td><td></td>`;
- If the time slot already exists, it updates the relevant columns (days) in that row with the
subject
. - If not, it creates a new row with empty day columns and inserts the
startTime - endTime
into the first cell.
9. Add Subject to Selected Days
selectedDays.forEach(day => {
const dayIndex = getDayIndex(day);
newRow.cells[dayIndex].innerHTML = subject;
});
- For each selected day, it finds the corresponding cell (by
dayIndex
) and fills it with the subject.
10. Insert Row in Order
insertSortedRow(newRow, startTime, timetableBody);
}
}
- Calls
insertSortedRow()
to ensure the new row is inserted in the correct position based on time.
11. Insert Row Sorted by Time
function insertSortedRow(newRow, startTime, timetableBody) {
const existingRows = Array.from(timetableBody.rows);
- Gets all existing rows to compare the time for sorting.
12. Sort and Insert Row
let inserted = false;
for (let i = 0; i < existingRows.length; i++) {
const rowTime = existingRows[i].cells[0].textContent.split(' - ')[0];
if (compareTimes(startTime, rowTime)) {
timetableBody.insertBefore(newRow, existingRows[i]);
inserted = true;
break;
}
}
if (!inserted) {
timetableBody.appendChild(newRow);
}
}
- Loops through existing rows, comparing
startTime
of the new row with existing rows usingcompareTimes()
. - If a suitable position is found, it inserts the new row before the existing row.
- If no earlier time is found, it appends the row to the end.
13. Compare Times
function compareTimes(time1, time2) {
return time1 < time2;
}
- Simple function that compares two times and returns
true
iftime1
is earlier thantime2
.
14. Get Day Index
function getDayIndex(day) {
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
return days.indexOf(day) + 1;
}
- Returns the index of the selected day in the array
days
. - Adds
1
because the first column of the row (index 0) is reserved for the time, so Monday starts at column 1.
document.getElementById('timetable-form').addEventListener('submit', function (e) {
e.preventDefault();
const subject = document.getElementById('subject').value;
const startTime = document.getElementById('start-time').value;
const endTime = document.getElementById('end-time').value;
const selectedDays = getSelectedDays();
if (subject && startTime && endTime && selectedDays.length > 0) {
addTimetableEntry(subject, startTime, endTime, selectedDays);
} else {
alert("Please fill in all the fields.");
}
this.reset();
});
function getSelectedDays() {
const days = document.querySelectorAll('#days input[type="checkbox"]:checked');
return Array.from(days).map(day => day.value);
}
function addTimetableEntry(subject, startTime, endTime, selectedDays) {
const timetableBody = document.querySelector('#timetable tbody');
let rowExists = false;
let targetRow;
Array.from(timetableBody.rows).forEach(row => {
const rowTime = row.cells[0].textContent;
if (rowTime === `${startTime} - ${endTime}`) {
rowExists = true;
targetRow = row;
}
});
if (rowExists) {
selectedDays.forEach(day => {
const dayIndex = getDayIndex(day);
targetRow.cells[dayIndex].innerHTML = subject;
});
} else {
const newRow = document.createElement('tr');
newRow.innerHTML = `<td>${startTime} - ${endTime}</td><td></td><td></td><td></td><td></td><td></td><td></td>`;
selectedDays.forEach(day => {
const dayIndex = getDayIndex(day);
newRow.cells[dayIndex].innerHTML = subject;
});
insertSortedRow(newRow, startTime, timetableBody);
}
}
function insertSortedRow(newRow, startTime, timetableBody) {
const existingRows = Array.from(timetableBody.rows);
if (existingRows.length === 0) {
timetableBody.appendChild(newRow);
} else {
let inserted = false;
for (let i = 0; i < existingRows.length; i++) {
const rowTime = existingRows[i].cells[0].textContent.split(' - ')[0];
if (compareTimes(startTime, rowTime)) {
timetableBody.insertBefore(newRow, existingRows[i]);
inserted = true;
break;
}
}
if (!inserted) {
timetableBody.appendChild(newRow);
}
}
}
function compareTimes(time1, time2) {
return time1 < time2;
}
function getDayIndex(day) {
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
return days.indexOf(day) + 1;
}
Final Output:
Conclusion:
You've successfully created a basic time table generator using HTML, CSS, and JavaScript. This project helps you understand how to dynamically generate tables with JavaScript and style them with CSS. You can extend this project by allowing users to customize the time slots or subjects. You could even save the table as a downloadable file or make it editable directly on the page.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊