Like / Dislike Counter System with HTML, CSS & JavaScript
30 DAYS 30 PROJECT CHALLENGE
Day #13
Project Overview
The Like / Dislike Counter System is a beginner-friendly project built using HTML, CSS, and JavaScript. It allows users to react to content by clicking either a Like or Dislike button. Whenever a user selects an option, JavaScript immediately updates the corresponding counter on the webpage. It also manages the user’s current reaction. For example, a user cannot increase the Like count repeatedly by clicking the Like button multiple times.ย
This project is useful for beginners who want to understand how JavaScript manages application state and updates the DOM dynamically. Additionally, it demonstrates how event listeners, conditional statements, variables, and CSS classes can work together to create an interactive user interface.
Key Features
- Like Button: Users can click the Like button to show a positive reaction. Once selected, JavaScript increases the Like counter and marks the button as active.
- Dislike Button: Users can also click on Dislike button to show a negative reaction. Similarly, the application increases the Dislike counter and highlights the selected button.
- Single Reaction Selection: It prevents users from selecting the same reaction repeatedly. Therefore, clicking an already selected button does not increase its counter again.
- Switch Between Reactions: This project allows the user to change their reaction at any time. For example, changing from Like to Dislike decreases the Like count before increasing the Dislike count.
- Automatic Counter Updates: JavaScript updates the reaction counters immediately after the user selects a button. As a result, users can instantly see the current number of reactions.
- Active Button Indicator: The selected reaction receives an active CSS class. This visual change helps users identify their current selection.
- Clean Layout: This project displays the Like and Dislike buttons together with their counters in a simple and organized interface.
- Easy to Understand: Users can quickly understand how the system works because the available actions and reaction counts are clearly displayed.
- Easy to Extend: Developers can expand this project by connecting it to posts, comments, user accounts, or an API-based backend system.
What You'll Learn
- Understand how to select HTML elements using JavaScript.
- Learn how click event listeners respond to user actions.
- Practice updating text dynamically with
innerText. - Understand how JavaScript variables store application data.
- Learn how conditional statements control user interactions.
- Understand how a variable can track the user’s current reaction.
- Learn how to prevent repeated actions using conditional statements.
- Understand how JavaScript updates previous values when a user changes an action.
- Practice adding CSS classes with
classList.add(). - Learn how to remove CSS classes with
classList.remove().
HTML Code
HTML creates the basic structure of the Like / Dislike Counter System. First, the style.css file is linked inside the <head> section so CSS can control the appearance and layout of the application. The main content is placed inside the .counter-container. This container holds the project heading, reaction buttons, and reaction counters.
Inside the .buttons section, #likeBtn and #dislikeBtn buttons allow users to select their reactions and each button has a unique ID, which allows JavaScript to select it and attach a click event listener, .counts section displays the current Like and Dislike totals, #likeCount and #dislikeCount <span> elements initially display 0. JavaScript later updates these values when users interact with the buttons.
Finally, the script.js file is loaded at the bottom of the <body>. Therefore, JavaScript can access the HTML elements and provide the required functionality.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Like / Dislike Counter</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="counter-container">
<h2>Like / Dislike System</h2>
<div class="buttons">
<button id="likeBtn">๐ Like</button>
<button id="dislikeBtn">๐ Dislike</button>
</div>
<div class="counts">
<p>Likes: <span id="likeCount">0</span></p>
<p>Dislikes: <span id="dislikeCount">0</span></p>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS Code
CSS controls the appearance and layout of the Like / Dislike Counter System. First, the universal selector applies box-sizing and the Segoe UI font to all elements.ย The .counter-container creates a card-style interface with a white background, padding, rounded corners, and a shadow. Heading also receives bottom spacing. As a result, the content inside the container remains clean and easy to read.
The .buttons section uses Flexbox to place the Like and Dislike buttons next to each other. Each button uses flex: 1, allowing both buttons to receive equal space and the #likeBtn uses a green background, while the #dislikeBtn uses a red background. This difference helps users quickly distinguish between the two actions.
When JavaScript adds the .active class to a button, CSS changes its opacity. Consequently, users receive visual feedback about their selected reaction. Finally, the .counts p selector styles the Like and Dislike counter text with appropriate spacing and font size.
* {
box-sizing: border-box;
font-family: "Segoe UI", sans-serif;
}
body {
min-height: 100vh;
background: #042453;
display: flex;
justify-content: center;
align-items: center;
}
.counter-container {
background: #ffffff;
width: 300px;
padding: 25px;
border-radius: 12px;
text-align: center;
box-shadow: 0 15px 30px rgba(0,0,0,0.1);
}
h2 {
margin-bottom: 20px;
}
.buttons {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
button {
flex: 1;
margin: 0 5px;
padding: 10px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
}
#likeBtn {
background: #22c55e;
color: white;
}
#dislikeBtn {
background: #ef4444;
color: white;
}
button.active {
opacity: 0.7;
}
.counts p {
margin: 5px 0;
font-size: 14px;
}
Javascript Code
JavaScript handles the main functionality of the Like / Dislike Counter System. First, it selects the Like button, Dislike button, and both counter elements using document.getElementById(). It also uses variables to store the total number of likes, dislikes, and the user’s current reaction.
When a user clicks the Like button, JavaScript checks whether the user has already liked the content. If the Like button is already selected, the counter does not increase again. However, if the user previously selected Dislike, JavaScript first decreases the Dislike count and removes its active state. It then increases the Like count, updates the displayed number, and marks the Like button as active.
The Dislike button follows the same logic in the opposite direction. JavaScript checks the user’s previous action and updates the counters accordingly. As a result, users can switch between Like and Dislike, but they cannot select both reactions at the same time. The code also uses innerText to update the counters and classList.add() or classList.remove() to provide visual feedback without refreshing the webpage.
const likeBtn = document.getElementById("likeBtn");
const dislikeBtn = document.getElementById("dislikeBtn");
const likeCount = document.getElementById("likeCount");
const dislikeCount = document.getElementById("dislikeCount");
let likes = 0;
let dislikes = 0;
let userAction = null; // "like" or "dislike"
likeBtn.addEventListener("click", () => {
if (userAction === "like") return;
if (userAction === "dislike") {
dislikes--;
dislikeCount.innerText = dislikes;
dislikeBtn.classList.remove("active");
}
likes++;
likeCount.innerText = likes;
likeBtn.classList.add("active");
userAction = "like";
});
dislikeBtn.addEventListener("click", () => {
if (userAction === "dislike") return;
if (userAction === "like") {
likes--;
likeCount.innerText = likes;
likeBtn.classList.remove("active");
}
dislikes++;
dislikeCount.innerText = dislikes;
dislikeBtn.classList.add("active");
userAction = "dislike";
});
Related Projects
Day 10 : Skeleton Loader (Shimmer Effect)
Displays animated placeholders while content is loading.
Concepts: Loading states, shimmer animation, UI feedback, conditional rendering.
Day 11 : User Profile Card Generator
Generates a user profile card dynamically from form inputs.
Concepts: User input processing, live UI generation, state-based rendering.
Day 15 : Email Subscription Form
Simple email subscription form with validation and feedback messages.
Concepts: Form validation, user input handling, dynamic UI feedback.