Simple Like Dislike Button With Pure HTML JS – Free Download!

Welcome to a tutorial and example on how to create a like-dislike button. Want to add your own like/dislike button? Here’s a quick sharing of my simple version using pure HTML CSS Javascript, no third-party libraries. Read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Download & Demo Like Dislike Useful Bits & Links
The End

 

DOWNLOAD & DEMO

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

EXAMPLE 1) SIMPLE LIKE/DISLIKE BUTTON

1-simple.html
<!-- (A) LOAD JS + CSS -->
<link rel="stylesheet" href="lidi.css"/>
<script src="lidi.js"></script>
 
<!-- (B) CREATE LIKE/DISLIKE BUTTON HERE -->
<div id="demoA"></div>
 
<!-- (C) JAVASCRIPT -->
<script>
lidi.create({
  status : 1, // OPTIONAL DEFAULT STATUS, 1 LIKE -1 DISLIKE
  hWrap : document.getElementById("demoA"),
  onChange : (status) => {
    // SEND THE NEW STATUS TO UPDATE YOUR SERVER
    var data = new FormData();
    data.append("status", status);
    fetch("1-dummy.txt", { method: "POST", body: data })
    .then(res => res.text())
    .then((txt) => { console.log(txt); })
    .catch((err) => { console.error(err); });
  }
});
</script>

For you guys who just want to use this as a “plugin” without reading everything:

  1. Captain Obvious. Load the CSS and Javascript.
  2. Create a <div> for the like/dislike button.
  3. On page load, simply call lidi.attach() to attach the like/dislike button.
    • status Sets the initial status of the button. 0 for neutral, -1 for dislike, and 1 for like. This defaults to 0 if not set.
    • hWrap Where you want to attach the buttons.
    • onChange A function to handle the like/dislike change. status contains the updated reaction, send this to update your server.

 

 

EXAMPLE 2) LIKE/DISLIKE COUNT

2-count.html
var demo = lidi.create({
  count : [123, 45], // (C1) INIT LIKES & DISLIKES
  hWrap : document.getElementById("demoB"),
 
  // (C2) UPDATE LIKES & DISLIKES COUNT METHOD 1
  // SEND NEW STATUS TO SERVER, SERVER RESPONDS WITH NEW COUNT
  onChange : (status, recount) => {
    var data = new FormData();
    data.append("status", status);
    fetch("2-dummy.txt", { method: "POST", body: data })
    .then(res => res.json())
    .then((update) => { recount(update); })
    .catch((err) => { console.error(err); });
  }
});
 
// (C3) UPDATE LIKES & DISLIKES COUNT METHOD 2
// MANUALLY CALL THE RECOUNT METHOD
// demo.recount([999, 888]);
  • (C1) Setting the initial likes/dislikes count is as easy as passing in count : [LIKES, DISLIKES].
  • The problem comes with updating the count afterward. Everybody has a different process, some don’t even bother to update after the initial load (to save system resources). So I have devised 2 ways to update the count – Use as you see fit, ignore it if you don’t want to update the count after the initial load.
    • (C2) Notice that onChange now has 2 parameters – status contains the current like/dislike status. recount is actually a function. So upon sending the updated status to the server, might as well make it return the updated total count, use recount(RESULTS) to update.
    • (C3) Just call INSTANCE.recount() at any time.

 

 

HOW IT WORKS

All right, for you guys who want to “deep customize” or learn more – Here are the details of the like/dislike button.

 

PART 1) ATTACH LIKE/DISLIKE HTML

likedis.js
// (A) CREATE NEW LIKE/DISLIKE BUTTON
// target : container to generate button
// status : -1 dislike, 0 neutral, 1 like (default 0)
// count : [likes, dislikes] (optional)
create : (opt) => {
  // (A1) NEW INSTANCE & DEFAULT SETTING
  let inst = opt;
  if (!inst.status) { inst.status = 0; }
 
  // (A2) GENERATE HTML
  // WRAPPER
  inst.hWrap.classList.add("lidiWrap");
  if (inst.count) { inst.hWrap.classList.add("count"); }
 
  // LIKE BUTTON
  inst.hUp = document.createElement("div");
  inst.hUp.className = "lidiUp";
  if (inst.status==1) { inst.hUp.classList.add("set"); }
  inst.hWrap.appendChild(inst.hUp);
 
  // LIKES COUNT
  if (inst.count) {
    inst.hUpCount = document.createElement("div");
    inst.hUpCount.className = "lidiUpCount";
    inst.hUpCount.innerHTML = inst.count[0];
    inst.hWrap.appendChild(inst.hUpCount);
  }
 
  // DISLIKE BUTTON
  inst.hDown = document.createElement("div");
  inst.hDown.className = "lidiDown";
  if (inst.status==-1) { inst.hDown.classList.add("set"); }
  inst.hWrap.appendChild(inst.hDown);
 
  // DISLIKES COUNT
  if (inst.count) {
    inst.hDownCount = document.createElement("div");
    inst.hDownCount.className = "lidiDownCount";
    inst.hDownCount.innerHTML = inst.count[1];
    inst.hWrap.appendChild(inst.hDownCount);
  }
 
  // (A3) TOGGLE LIKE/DISLIKE
  inst.hUp.addEventListener("click", () => { lidi.updown(inst, true); });
  inst.hDown.addEventListener("click", () => { lidi.updown(inst, false); });
 
  // (A4) HANDLE LIKE/DISLIKE CHANGE
  if (inst.count) {
    inst.hUp.addEventListener("click", () => {
      inst.onChange(inst.status, (count) => { lidi.recount(count, inst); });
    });
    inst.hDown.addEventListener("click", () => {
      inst.onChange(inst.status, (count) => { lidi.recount(count, inst); });
    });
    inst.recount = (count) => { lidi.recount(count, inst); };
  } else {
    inst.hUp.addEventListener("click", () => { inst.onChange(inst.status); });
    inst.hDown.addEventListener("click", () => { inst.onChange(inst.status); });
  }
 
  // (A5) DONE!
  return inst;
}

This looks massive at first, but you have already used lidi.create(). What does it do? Generate the HTML (will go through that below) and attach all the onclick actions.

 

 

PART 2) TOGGLE LIKE/DISLIKE STATUS

likedis.js
// (B) UPDATE LIKE/DISLIKE STATUS
updown : (inst, up) => {
  // (B1) SET STATUS FLAG
  if (up) { inst.status = inst.status == 1 ? 0 : 1; }
  else { inst.status = inst.status == -1 ? 0 : -1; }
 
  // (B2) SET CSS
  if (inst.status==1) {
    inst.hUp.classList.add("set");
    inst.hDown.classList.remove("set");
  } else if (inst.status==-1) {
    inst.hUp.classList.remove("set");
    inst.hDown.classList.add("set");
  } else {
    inst.hUp.classList.remove("set");
    inst.hDown.classList.remove("set");
  }
}

lidi.updown() is the function that deals with the cosmetics of toggling the like/dislike. Basically, just add a set CSS on the selected like/dislike icon. Remove the set class if the user chooses “neutral”.

 

PART 3) UPDATE LIKES/DISLIKES COUNT

likedis.js
// (C) UPDATE LIKE/DISLIKES COUNT
recount : (count, inst) => {
  inst.hUpCount.innerHTML = count[0];
  inst.hDownCount.innerHTML = count[1];
}

Self-explanatory…

 

 

EXTRA) LIKE/DISLIKE BUTTON HTML

<div id="demoB" class="lidiWrap">
  <div class="lidiUp"></div>
  <div class="lidiUpCount"></div>
  <div class="lidiDown"></div>
  <div class="lidiDownCount"></div>
</div>

Yep, that’s everything the Javascript generates… Take note that the “thumbs up” and “thumbs down” icon is using lidi.png… Feel free to modify section (A2) if you are want to use Font Awesome, Material Icons, or whatever icon set of your own choice.

 

USEFUL BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

COMPATIBILITY CHECKS

Yep, all of these features are well supported in all modern browsers now.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *