DEV Community

Cover image for Simple Calculator with Dark Mode.
Mohammed Farmaan.
Mohammed Farmaan.

Posted on • Updated on

Simple Calculator with Dark Mode.

Here's a simple calculator built using HTML, CSS and obviously, JavaScript.

This calculator also has dark mode which looks really good. And here's how you can do that:

Here's the markup:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>Calculator</title>
  <meta name="description" content="" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" href="light.css" id="theme" />
  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap" rel="stylesheet" />
</head>
<body>
  <center>
    <div class="container">
      <h1>Calculator</h1>
      <div class="first-row">
        <input type="text" name="result" class="result" id="result" value="" placeholder="Result" readonly />
        <input type="button" value="C" onclick="clearScreen()" class="clear" />
      </div>
      <div class="second-row">
        <input type="button" value="1" onclick="liveScreen(1)" id="one" />
        <input type="button" value="2" onclick="liveScreen(2)" id="two" />
        <input type="button" value="3" id="three" onclick="liveScreen(3)" />
        <input type="button" value="+" onclick="liveScreen('+')" />
      </div>
      <div class="third-row">
        <input type="button" value="4" id="four" onclick="liveScreen(4)" />
        <input type="button" value="5" id="five" onclick="liveScreen(5)" />
        <input type="button" value="6" id="six" onclick="liveScreen(6)" />
        <input type="button" value="-" onclick="liveScreen('-')" />
      </div>
      <div class="fourth-row">
        <input type="button" value="7" id="seven" onclick="liveScreen(7)" />
        <input type="button" value="8" id="eight" onclick="liveScreen(8)" />
        <input type="button" value="9" id="nine" onclick="liveScreen(9)" />
        <input type="button" value="x" onclick="liveScreen('*')" />
      </div>
      <div class="fifth-row">
        <input type="button" value="/" onclick="liveScreen('/')" />
 <input type="button" value="0" id="zero" onclick="liveScreen(0)" />
        <input type="button" value="." class="dot" onclick="liveScreen('.')" />
        <input type="button" value="=" onclick="result.value = eval(result.value)" />
      </div>
      <div class="bottom-buttons">
        <button>
          <i class="fab fa-github"></i>
          <a href="https://github.com/Mohammad-Farmaan/JavaScript-Calculator">GitHub</a>
        </button>
        <button onclick="switchTheme()" id="dark-mode">
          Dark Mode 🌙
        </button>
      </div>
    </div>
  </center>
  <script src="https://kit.fontawesome.com/f28b055962.js" crossorigin="anonymous"></script>
  <script src="script.js" async defer></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

Here's the CSS for Light Mode:

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  font-family: "Open Sans", sans-serif;
  font-weight: bold;
}
body {
  background-color: rgb(28, 231, 221);
  transition: 0.8s;
  -webkit-transition: 0.8s;
  -moz-transition: 0.8s;
  -ms-transition: 0.8s;
  -o-transition: 0.8s;
}
h1 {
  margin-top: 25vh;
  text-align: center;
  margin-bottom: 1.5%;
  color: #fff;
}
.container {
  width: 370px;
}
.result {
  width: 59.1%;
}
input {
  padding: 25px;
  color: rgb(17, 16, 16);
  font-size: 1em;
  cursor: pointer;
  width: 70px;
  background-color: #fff;
  border: none;
  outline: none;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -ms-border-radius: 4px;
  -o-border-radius: 4px;
}

.first-row,
.second-row,
.third-row,
.fourth-row,
.fifth-row {
  margin-bottom: 3px;
}
input[type="text"] {
  background-color: rgb(255, 255, 255);
}
input[type="button"]:hover {
  background-color: rgb(37, 35, 59);
  color: #fff;
}
.clear {
  color: #fff;
  background-color: rgb(255, 42, 42);
}
button {
  border: none;
  background-color: rgb(41, 38, 38);
  padding: 10px;
  color: white;
  margin: 2px;
  cursor: pointer;
  outline: none;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -ms-border-radius: 4px;
  -o-border-radius: 4px;
}

button a {
  text-decoration: none;
  color: #fff;
}
.bottom-buttons {
  float: left;
  margin-left: 10%;
  margin-top: 0.7%;
}

@media (max-width: 640px) {
  h1 {
    margin-top: 15vh;
  }
}
Enter fullscreen mode Exit fullscreen mode

Here's the CSS for Dark Mode:

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  font-family: "Open Sans", sans-serif;
  font-weight: bold;
}

body {
  background-color: rgb(20, 19, 19);
  transition: 0.8s;
  -webkit-transition: 0.8s;
  -moz-transition: 0.8s;
  -ms-transition: 0.8s;
  -o-transition: 0.8s;
}
h1 {
  margin-top: 25vh;
  text-align: center;
  margin-bottom: 1.5%;
  color: #fff;
}
.container {
  width: 370px;
}
.result {
  width: 59.1%;
}
input {
  padding: 25px;
  color: rgb(255, 255, 255);
  font-size: 1em;
  cursor: pointer;
  width: 70px;
  background-color: rgb(47, 51, 50);
  border: none;
  outline: none;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -ms-border-radius: 4px;
  -o-border-radius: 4px;
}

.first-row,
.second-row,
.third-row,
.fourth-row,
.fifth-row {
  margin-bottom: 3px;
}
input[type="text"] {
  background-color: rgb(47, 51, 50);
}
input[type="button"]:hover {
  background-color: rgb(160, 160, 160);
  color: #fff;
}
.clear {
  color: #fff;
  background-color: rgb(255, 42, 42);
}
button {
  border: none;
  background-color: rgb(39, 36, 36);
  padding: 10px;
  color: white;
  margin: 2px;
  cursor: pointer;
  outline: none;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -ms-border-radius: 4px;
  -o-border-radius: 4px;
}

button a {
  text-decoration: none;
  color: #fff;
}
.bottom-buttons {
  float: left;
  margin-left: 10%;
  margin-top: 0.7%;
}

@media (max-width: 640px) {
  h1 {
    margin-top: 15vh;
  }
}

Enter fullscreen mode Exit fullscreen mode

And finally, here's the JavaScript:

// Clears the screen on click of C button.
function clearScreen() {
  document.getElementById("result").value = "";
}
// Displays the entered value on screen.
function liveScreen(value) {
  document.getElementById("result").value += value;
}
// Swaps the style sheet in order to  achieve dark mode.
function switchTheme() {
  let darkMode = document.getElementById("dark-mode");
  let theme = document.getElementById("theme");
  if (theme.getAttribute("href") == "light.css") {
    theme.href = "dark.css";
    darkMode.innerHTML = "Light Mode 🌙";
  } else {
    theme.href = "light.css";
    darkMode.innerHTML = "Dark Mode 🌙";
  }
}
Enter fullscreen mode Exit fullscreen mode

That's it. Now we have a simple calculator with dark mode. Thanks for reading. Hope you like it!

Link to live demo:
https://zxcodes.github.io/Calculator

Here's the link to repo:

GitHub logo zxcodes / Calculator

A Calculator App built with HTML, CSS, and JavaScript which also has a dark mode.

Calculator

A Calculator App with dark mode. Built using HTML, CSS and JavaScript. Feel free to check out the code and don't forget to star the repo.

cal

Top comments (24)

Collapse
 
kretaceous profile image
Abhijit Hota

Great web-app with great UI! I surely learned something about dark-mode implementation.

Although, may I suggest you to add the readonly attribute to the text input for result, since you're using the notorious eval() function? I'm aware that it's a 'simple' calculator but I'm just suggesting.

Great project, though!😄

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Yeah sure. I was more focussed on the UI so I didn't put that little extra effort to look into that. Thanks for the suggestion tho. Glad you learned something!😁

Collapse
 
powerc9000 profile image
Clay Murray

Here you go so you don't have to use eval.

// Turns a string equation into a value eg '2*2 + 4' will return '8'
function calcString(input) {
    const values = input.split("");
    const out = [];
    const ops = [];
    const allOps = ["*", "/", "+", "-", ")", "("];

    let num = "";
    for(let index = 0; index < values.length; index++){
    const v = values[index];
        if(v === " ") {
          continue;
        }
      if(!allOps.includes(v)){
        while(!allOps.includes(values[index]) && values[index] !== " " && index < values.length){
          num += values[index];
                 index ++;
        }
        index--;
      out.push(num);
      num = "";
        continue;
      }          

            if (v === ")"){
                let top = ops.pop();

                while(top !== "(" && ops.length) {
                    out.push(top);
                    top = ops.pop();

                }
                if(top !== "("){
                    return "Mismatched parens"
                }
              continue;
            }
            if(ops.length && v !== "(") {
                let top = ops[ops.length - 1];
                let topP = getPrecedence(top);
                const currP = getPrecedence(v);

              while(currP >= topP && top !== "(" && ops.length) {

                out.push(top)
                ops.pop();
                top = ops[ops.length - 1];
                topP = getPrecedence(top);

              }

            } 
            ops.push(v);


    }
    while(ops.length) {
            out.push(ops.pop());
    }
    const stack = [];
    out.forEach((o)=>{
      if(!allOps.includes(o)){
        stack.push(parseFloat(o, 10));
      } else {
        const r = stack.pop();
        const l = stack.pop();
        switch(o) {
          case "+":
            stack.push(l+r);
            break;
          case "-":
            stack.push(l-r);
            break;
          case "*":
            stack.push(l*r);
            break;
          case "/":
            stack.push(l/r);
            break;
        }
      }
    })

  return ""+stack[0]

}
function getPrecedence(value) {
    const precedence = [["("], ["*", "/"], ["+", "-"]];
    return precedence.findIndex((p)=> {
        return p.includes(value);
    })
}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
zxcodes profile image
Mohammed Farmaan.

Great. Thanks for the explanation!😄

Collapse
 
powerc9000 profile image
Clay Murray • Edited

Totally forgot to mention! Looks really great the design is super nice.

Thread Thread
 
zxcodes profile image
Mohammed Farmaan.

Thank you!😇

Collapse
 
mathurahravi profile image
Mathurah Ravigulan

It would be cool if you could add something with local storage so it saves the dark mode/light mode toggle the user has, so it doesn't automatically change light mode when the screen is reloaded! I came across this blog, thought it could be helpful 😊 joshwcomeau.com/gatsby/dark-mode/

Collapse
 
tadeubdev profile image
Tadeu Barbosa

Congrats! It's a good design and project!

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Thank you!😊

Collapse
 
madza profile image
Madza

Year 2020: If there is not dark mode, it doesn't count xdd

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Yess it doesn't count!😂

Collapse
 
akdeberg profile image
Anik Khan

The UI looks astonishing 😍
And as per the code, I have the same suggestion as @Abhijit.
Thanks a lot for sharing. #Kudos

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Thank you!😄 Yeah I've considered that suggestion.

Collapse
 
yedveshubham profile image
Shubham_Yedve

Impressive Ui/design I loved it. Especially the transition between the light and the dark theme.

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Thank you. I'm glad you liked it!😄

Collapse
 
raounek profile image
touibeg mohamed

good job mohammad ...

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Thank you!😇

Collapse
 
willemodendaal profile image
Willem Odendaal

I like that this is just plain Javascript. Good job :)

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Thank you!😄

Collapse
 
jlohani profile image
Jayant Lohani

This looks amazing. Great work.
I made a calculator a while ago but its design was not good and had some flaws. Will try to create another one like yours which supports dark mode.

Collapse
 
zxcodes profile image
Mohammed Farmaan.

Thank you!😄 Yeah sure. Feel free to check how I implemented things and don't forget to add your own design to it. Good luck.

Collapse
 
jlohani profile image
Jayant Lohani

All I have to do is change the GitHub link at the end.😏
Just kidding.😂😂 Will just look at the implementation and make my own.

Thread Thread
 
zxcodes profile image
Mohammed Farmaan.

Hahah sure. You can do that too xD.😜

Collapse
 
moyohussein_92 profile image
Hussein AbdulQohar

Thumbs up for the design. Did you notice that evaluating 0.2 multiplied by 6 or 0.2 multiplied by 3 is giving a funny answer, or this just happens to be one of the disadvantages of the eval function.