Learn how to create a simple Cricket or Football scorecard web template using HTML, CSS, and JavaScript with easy steps for beginners.
HTML Thank You Page Code SnippetTable of Contents
Want to display live match scores on your website? In this blog, you will learn how to create a Cricket and Football scorecard web template using HTML, CSS, and JavaScript. We’ll walk you through simple steps so even beginners can follow. This project will help you practice basic web design and scripting while creating something useful for sports fans.
Prerequisites
Before starting, make sure you:
- Know basic HTML tags
- Understand simple CSS styling
- Have some idea of JavaScript basics
- Have a code editor (like VS Code)
- A modern web browser (like Chrome)
Source Code
Step 1 (HTML Code):
To get started, we first need to create a basic HTML file. In this file, we will include the main structure for our scoreboard template. Let’s break down the HTML code step by step:
Document Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Modern Sports Scorecard</title>
This sets up:
- HTML5 document type.
- English language.
- Character encoding for text (UTF-8).
- Responsive design (viewport ensures it looks good on mobile).
CSS & Fonts
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:...&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles.css">
What it loads:
- Tailwind CSS: A utility-first CSS framework to style your page.
- Chart.js: A library for charts (used in football stats).
- Google Fonts (Inter): A clean, modern font.
- styles.css: Your custom CSS file (if any).
Body Classes
<body class="bg-gray-100 transition-colors duration-300">
- Sets a light gray background and enables smooth color changes (useful for dark mode).
Cricket Modal
<div id="cricketModal" style="display: none; position: fixed; ...">
...
</div>
- A hidden pop-up modal that appears when cricket innings end, showing a message and an OK button.
Header
<header class="...">
<h1>Match Scorecard</h1>
<div class="flex items-center ...">
<div class="flex ...">
<button id="cricket-btn">Cricket</button>
<button id="football-btn">Football</button>
</div>
<button id="dark-mode-toggle"> ... sun/moon icons ... </button>
</div>
</header>
Contains:
- Page title.
- Buttons to switch between Cricket / Football scorecards.
- Dark mode toggle button (switch light/dark theme).
Scorecard Container
<main id="scorecard-container" class="..."></main>
- The main area where scorecard data is dynamically added by JavaScript.
Action Buttons Area
<div id="action-buttons" class="..."></div>
- Space for dynamic buttons (e.g., update scores).
Templates
The templates are hidden HTML blueprints used by JavaScript to inject data.
Cricket template:
- Displays teams, scores, overs, CRR, batsmen, bowler, match progress, and top performer.
Football template:
- Displays teams, score, match time, goal scorers, stats (chart), and top performer.
Example:
<template id="cricket-template"> ... </template>
<template id="football-template"> ... </template>
Scripts
<script src="script.js"></script>
- Links to your custom JavaScript file (handles logic like switching sports, updating scores, charts).
Step 2 (CSS Code):
Once the basic HTML structure of the website is in place, the next step is to add styling to the website using Custom CSS. Let’s break down the CSS code section-by-section:
General font styling
body {
font-family: 'Inter', sans-serif;
}
- Sets the font of the entire webpage to Inter. If Inter is not available, it will fall back to any sans-serif font.
Dark mode base styles
.dark {
background-color: #111827;
color: #f3f4f6;
}
- When an element (typically
<html>or<body>) has the class dark, the background becomes dark gray (#111827) and the text becomes light gray (#f3f4f6).
Dark mode specific elements
.dark .bg-white {
background-color: #1f2937;
}
- Changes any element with bg-white class inside a .dark container to a darker background (#1f2937) instead of white.
.dark .text-gray-800 {
color: #1f2937;
}
- Inside dark mode, elements that would normally have dark gray text (text-gray-800) get a dark shade (#1f2937) so they blend better with the dark background.
.dark .text-gray-600 {
color: #d1d5db;
}
- text-gray-600 in dark mode becomes a lighter gray to ensure good contrast.
.dark .border-gray-200 {
border-color: #374151;
}
- Light gray borders (border-gray-200) become darker in dark mode.
.dark .bg-gray-100 {
background-color: #374151;
}
- Elements that would have a very light gray background (bg-gray-100) get a dark gray background in dark mode.
Tab styling
.tab-active {
border-bottom: 2px solid #4f46e5;
color: #4f46e5;
}
- Marks active tabs by adding a bottom border and changing text color to indigo (#4f46e5).
.dark .tab-active {
border-bottom-color: #818cf8;
color: #818cf8;
}
- In dark mode, active tabs use a lighter indigo (#818cf8) for better visibility on the dark background.
Progress bar
.progress-bar-inner {
transition: width 0.5s ease-in-out;
}
- When the width of a .progress-bar-inner changes (e.g., for loading or progress indicators), the change will animate smoothly over 0.5 seconds with an ease-in-out timing.
body {
font-family: 'Inter', sans-serif;
}
.dark {
background-color: #111827;
color: #f3f4f6;
}
.dark .bg-white {
background-color: #1f2937;
}
.dark .text-gray-800 {
color: #1f2937;
}
.dark .text-gray-600 {
color: #d1d5db;
}
.dark .border-gray-200 {
border-color: #374151;
}
.dark .bg-gray-100 {
background-color: #374151;
}
.tab-active {
border-bottom: 2px solid #4f46e5;
color: #4f46e5;
}
.dark .tab-active {
border-bottom-color: #818cf8;
color: #818cf8;
}
.progress-bar-inner {
transition: width 0.5s ease-in-out;
} Step 3 (JavaScript Code):
Finally, we need to create a function in JavaScript. Let’s break down the JavaScript code step by step:
Event on page load
document.addEventListener('DOMContentLoaded', () => { ... });
- This ensures all code runs only after the HTML has fully loaded.
DARK MODE TOGGLE
darkModeToggle.addEventListener('click', () => {
document.body.classList.toggle('dark');
sunIcon.classList.toggle('hidden');
moonIcon.classList.toggle('hidden');
if (footballChart) {
updateChartTheme(footballChart);
}
});
- Toggles dark mode by adding/removing the dark class on
<body>. - Shows/hides the sun or moon icon.
- If the football chart exists → it updates its colors for dark mode.
function updateChartTheme(chart) { ... }
- Updates grid and text colors of the football chart based on the current mode.
SPORT SWITCHING
window.switchSport = (sport) => { ... };
- Clears timers or destroys the existing football chart.
- Updates currentSport to cricket or football.
- Calls updateUI() to redraw the scorecard + buttons.
UPDATE UI
function updateUI() { ... }
- Highlights the active sport’s button (adds/removes bg classes).
- Loads the right HTML template for the selected sport.
- Populates buttons for actions like "+1 Run", "Goal Team 1", etc.
- If football → sets up tabs and stats chart.
ACTION BUTTONS
function populateActionButtons() { ... }
- Creates sport-specific action buttons dynamically.
- Buttons trigger scoring functions (e.g. updateCricketScore, updateFootballScore).
CRICKET LOGIC
window.updateCricketScore = (runs, wickets) => { ... }
- Adds runs and wickets.
- Updates overs + balls.
- Ends innings on 10 wickets or 20 overs.
- Calls updateDisplay() to refresh scores.
function updateDisplay() { ... }
- Calculates current run rate (CRR).
- Updates score, wickets, overs, CRR in DOM.
- Updates progress bar width.
window.showCricketModal = (msg, winMsg) => { ... }
window.closeCricketModal = () => { ... }
- Shows or hides the cricket end-of-innings modal.
FOOTBALL LOGIC
window.updateFootballScore = (team) => { ... }
- Increases the score of the selected team.
function startFootballTimer() { ... }
- Starts or resets football match timer (updates every second).
FOOTBALL TABS + STATS
function initFootballFeatures() { ... }
- Sets up Summary / Stats tabs for football.
- Creates a chart on switching to the Stats tab.
function createFootballChart() { ... }
- Creates a horizontal bar chart showing team stats.
- Chart style adapts to dark mode.
- Uses Chart.js library.
INITIAL LOAD
updateUI();
- On load, draws the default sport UI (Cricket).
document.addEventListener('DOMContentLoaded', () => {
const darkModeToggle = document.getElementById('dark-mode-toggle');
const sunIcon = document.getElementById('sun-icon');
const moonIcon = document.getElementById('moon-icon');
const scorecardContainer = document.getElementById('scorecard-container');
const actionButtonsContainer = document.getElementById('action-buttons');
let currentSport = 'cricket';
let footballChart;
let timerInterval;
// --- DARK MODE LOGIC ---
darkModeToggle.addEventListener('click', () => {
document.body.classList.toggle('dark');
sunIcon.classList.toggle('hidden');
moonIcon.classList.toggle('hidden');
if (footballChart) {
updateChartTheme(footballChart);
}
});
function updateChartTheme(chart) {
const isDarkMode = document.body.classList.contains('dark');
const gridColor = isDarkMode
? 'rgba(255, 255, 255, 0.1)'
: 'rgba(0, 0, 0, 0.1)';
const textColor = isDarkMode ? '#f3f4f6' : '#374151';
chart.options.scales.x.grid.color = gridColor;
chart.options.scales.y.grid.color = gridColor;
chart.options.scales.x.ticks.color = textColor;
chart.options.scales.y.ticks.color = textColor;
chart.options.plugins.legend.labels.color = textColor;
chart.update();
}
// --- SPORT SWITCHING LOGIC ---
window.switchSport = (sport) => {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
if (footballChart) {
footballChart.destroy();
footballChart = null;
}
currentSport = sport;
updateUI();
};
function updateUI() {
document
.getElementById('cricket-btn')
.classList.toggle('bg-white', currentSport === 'cricket');
document
.getElementById('cricket-btn')
.classList.toggle('dark:bg-gray-900', currentSport === 'cricket');
document
.getElementById('football-btn')
.classList.toggle('bg-white', currentSport === 'football');
document
.getElementById('football-btn')
.classList.toggle('dark:bg-gray-900', currentSport === 'football');
const template = document.getElementById(
`${currentSport}-template`
).innerHTML;
scorecardContainer.innerHTML = template;
populateActionButtons();
if (currentSport === 'football') {
initFootballFeatures();
}
}
function populateActionButtons() {
actionButtonsContainer.innerHTML = '';
let buttons = [];
if (currentSport === 'cricket') {
buttons = [
{ text: '+1 Run', action: () => updateCricketScore(1, 0) },
{ text: '+4 Runs', action: () => updateCricketScore(4, 0) },
{ text: '+6 Runs', action: () => updateCricketScore(6, 0) },
{ text: 'Wicket!', action: () => updateCricketScore(0, 1) },
];
} else {
buttons = [
{ text: 'Goal Team 1', action: () => updateFootballScore(1) },
{ text: 'Goal Team 2', action: () => updateFootballScore(2) },
{ text: 'Update Time', action: startFootballTimer },
];
}
buttons.forEach((btnInfo) => {
const button = document.createElement('button');
button.textContent = btnInfo.text;
button.className =
'bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded-lg m-2 transition-transform transform hover:scale-105';
button.onclick = btnInfo.action;
actionButtonsContainer.appendChild(button);
});
}
// --- CRICKET SPECIFIC LOGIC ---
let c_score = 182,
c_wickets = 4,
c_overs = 18,
c_balls = 2;
let inningsOver = false;
window.updateCricketScore = (runs, wickets) => {
if (inningsOver) return;
c_score += runs;
c_wickets += wickets;
if (c_wickets >= 10) {
c_wickets = 10;
updateDisplay();
showCricketModal('All out!', `Runs needed to win: ${c_score}`);
inningsOver = true;
return;
}
c_balls++;
if (c_balls === 6) {
c_balls = 0;
c_overs++;
}
if (c_overs === 20) {
c_balls = 0;
updateDisplay();
showCricketModal('20 overs completed!', `Runs needed to win: ${c_score}`);
inningsOver = true;
return;
}
updateDisplay();
};
function updateDisplay() {
const oversDisplay = `${c_overs}.${c_balls}`;
const totalBalls = c_overs * 6 + c_balls;
const crr = totalBalls > 0 ? ((c_score / totalBalls) * 6).toFixed(2) : 0;
document.getElementById('c-score').textContent = c_score;
document.getElementById('c-wickets').textContent = c_wickets;
document.getElementById('c-overs').textContent = oversDisplay;
document.getElementById('c-crr').textContent = crr;
const progress = (totalBalls / 120) * 100;
document.getElementById('cricket-progress').style.width = `${Math.min(
progress,
100
)}%`;
}
window.showCricketModal = (msg, winMsg) => {
document.getElementById('cricketModalMsg').textContent = msg;
document.getElementById('cricketWinMsg').textContent = winMsg;
document.getElementById('cricketModal').style.display = 'flex';
};
window.closeCricketModal = () => {
document.getElementById('cricketModal').style.display = 'none';
};
// --- FOOTBALL SPECIFIC LOGIC ---
let f_score1 = 2,
f_score2 = 1,
f_minutes = 78,
f_seconds = 12;
window.updateFootballScore = (team) => {
if (team === 1) {
f_score1++;
document.getElementById('f-score1').textContent = f_score1;
} else {
f_score2++;
document.getElementById('f-score2').textContent = f_score2;
}
};
function startFootballTimer() {
if (timerInterval) clearInterval(timerInterval);
timerInterval = setInterval(() => {
f_seconds++;
if (f_seconds >= 60) {
f_seconds = 0;
f_minutes++;
}
if (f_minutes >= 90) clearInterval(timerInterval);
const timeEl = document.getElementById('f-time');
if (timeEl) {
timeEl.textContent = `${String(f_minutes).padStart(2, '0')}:${String(
f_seconds
).padStart(2, '0')}`;
}
}, 1000);
}
function initFootballFeatures() {
const tabs = scorecardContainer.querySelectorAll('[data-tab]');
const summaryContent = document.getElementById('summary-content');
const statsContent = document.getElementById('stats-content');
tabs.forEach((tab) => {
tab.addEventListener('click', () => {
tabs.forEach((t) => t.classList.remove('tab-active'));
tab.classList.add('tab-active');
summaryContent.classList.toggle(
'hidden',
tab.dataset.tab !== 'summary'
);
statsContent.classList.toggle('hidden', tab.dataset.tab !== 'stats');
if (tab.dataset.tab === 'stats' && !footballChart) {
createFootballChart();
}
});
});
}
function createFootballChart() {
const ctx = document
.getElementById('football-stats-chart')
.getContext('2d');
const isDarkMode = document.body.classList.contains('dark');
const gridColor = isDarkMode
? 'rgba(255, 255, 255, 0.1)'
: 'rgba(0, 0, 0, 0.1)';
const textColor = isDarkMode ? '#f3f4f6' : '#374151';
footballChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [
'Shots',
'Shots on Target',
'Possession %',
'Passes',
'Fouls',
'Yellow Cards',
],
datasets: [
{
label: 'Real Madrid',
data: [14, 8, 58, 550, 8, 1],
backgroundColor: 'rgba(254, 190, 16, 0.8)',
borderColor: 'rgba(254, 190, 16, 1)',
borderWidth: 1,
},
{
label: 'FC Barcelona',
data: [11, 5, 42, 410, 12, 3],
backgroundColor: 'rgba(165, 0, 68, 0.8)',
borderColor: 'rgba(165, 0, 68, 1)',
borderWidth: 1,
},
],
},
options: {
indexAxis: 'y',
scales: {
x: {
beginAtZero: true,
grid: { color: gridColor },
ticks: { color: textColor },
},
y: {
grid: { color: gridColor },
ticks: { color: textColor },
},
},
plugins: {
legend: {
labels: {
color: textColor,
},
},
},
responsive: true,
maintainAspectRatio: false,
},
});
}
// --- INITIAL LOAD ---
updateUI();
});Final Output:
Conclusion:
Congratulations! You have built a simple and clean Cricket and Football scorecard web template using HTML, CSS, and JavaScript. You can now improve it by:
- Adding reset buttons
- Styling it for mobile devices
- Showing match time or other stats
This small project is great for learning web design and JavaScript basics. Try adding your own ideas to make it look and work even better!
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 😊

