Here’s a simple and effective Journaling Streak Tracker built using HTML, CSS, and JavaScript. It visually tracks your daily journaling progress and highlights your current streak.
html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Journaling Streak Tracker</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f9f9f9;
color: #333;
text-align: center;
padding: 2rem;
}
h1 {
color: #444;
}
.streak-display {
font-size: 2rem;
margin: 1rem 0;
color: #28a745;
}
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 10px;
margin: 2rem auto;
max-width: 500px;
}
.day {
padding: 1rem;
background: #eee;
border-radius: 8px;
cursor: pointer;
transition: 0.3s;
}
.day.logged {
background: #28a745;
color: #fff;
}
.controls {
margin-top: 2rem;
}
.btn {
background: #007bff;
border: none;
color: white;
padding: 0.6rem 1.2rem;
font-size: 1rem;
border-radius: 5px;
cursor: pointer;
}
.btn:hover {
background: #0056b3;
}
</style>
</head>
<body>
<h1>Journaling Streak Tracker</h1>
<div class="streak-display">Current Streak: <span id="streak">0</span> days</div>
<div class="calendar" id="calendar"></div>
<div class="controls">
<button class="btn" onclick="resetStreak()">Reset Streak</button>
</div>
<script>
const calendar = document.getElementById("calendar");
const streakDisplay = document.getElementById("streak");
const DAYS = 30;
let streak = 0;
let streakDates = JSON.parse(localStorage.getItem("journalStreakDates")) || [];
function isToday(dateString) {
const today = new Date();
const d = new Date(dateString);
return today.toDateString() === d.toDateString();
}
function renderCalendar() {
calendar.innerHTML = "";
const today = new Date();
for (let i = DAYS - 1; i >= 0; i--) {
const date = new Date();
date.setDate(today.getDate() - i);
const dateStr = date.toISOString().split("T")[0];
const day = document.createElement("div");
day.classList.add("day");
day.innerText = date.getDate();
if (streakDates.includes(dateStr)) {
day.classList.add("logged");
}
day.onclick = () => toggleLog(dateStr, day);
calendar.appendChild(day);
}
updateStreakDisplay();
}
function toggleLog(dateStr, dayElement) {
const index = streakDates.indexOf(dateStr);
if (index > -1) {
streakDates.splice(index, 1);
dayElement.classList.remove("logged");
} else {
streakDates.push(dateStr);
dayElement.classList.add("logged");
}
localStorage.setItem("journalStreakDates", JSON.stringify(streakDates));
updateStreakDisplay();
}
function updateStreakDisplay() {
streakDates = streakDates.filter(date => {
const d = new Date(date);
return !isNaN(d.getTime());
});
streakDates.sort((a, b) => new Date(a) - new Date(b));
streak = calculateStreak();
streakDisplay.innerText = streak;
}
function calculateStreak() {
const today = new Date();
today.setHours(0, 0, 0, 0);
let count = 0;
for (let i = streakDates.length - 1; i >= 0; i--) {
const date = new Date(streakDates[i]);
date.setHours(0, 0, 0, 0);
if (i === streakDates.length - 1) {
if ((today - date) / (1000 * 3600 * 24) <= 1) {
count = 1;
} else {
break;
}
} else {
const prev = new Date(streakDates[i + 1]);
const diff = (prev - date) / (1000 * 3600 * 24);
if (diff === 1) {
count++;
} else {
break;
}
}
}
return count;
}
function resetStreak() {
if (confirm("Are you sure you want to reset your streak?")) {
streakDates = [];
localStorage.removeItem("journalStreakDates");
renderCalendar();
}
}
renderCalendar();
</script>
</body>
</html>
Features:
-
Tracks 30 days of journaling activity.
-
Click a date to mark it as “journaled.”
-
Automatically saves to
localStorage. -
Displays current streak based on consecutive days.
-
Includes a reset button.
You can copy and paste this into an .html file and open it in any browser to use the tracker. Let me know if you’d like a version with user accounts or backend integration.
Share this Page your favorite way: Click any app below to share.