Building a Calculator with HTML, CSS, and JavaScript
Tags: html, css, javascript, beginners
Published: 2024-01-02 02:28:00

In this article, we will discuss how to create a calculator using HTML, CSS, and JavaScript. This project focuses on the most fundamental functionalities, making it an excellent practice project to improve your programming skills as a beginner.

➡️ _[Get the source code for FREE!](https://ericsdevblog.ck.page/source-code)_

![calculator](https://www.ericsdevblog.com/posts/html-css-js-calculator/images/calculator.png)

## Creating the calculator layout

As usual, let's start by creating the HTML skeleton.

```html
<div class="calculator">
  <div class="display">0</div>
  <div class="buttons">
    <div class="button function">AC</div>
    <div class="button function">+/-</div>
    <div class="button function">%</div>
    <div class="button function">/</div>

    <div class="button number">7</div>
    <div class="button number">8</div>
    <div class="button number">9</div>
    <div class="button function">*</div>

    <div class="button number">4</div>
    <div class="button number">5</div>
    <div class="button number">6</div>
    <div class="button function">-</div>

    <div class="button number">1</div>
    <div class="button number">2</div>
    <div class="button number">3</div>
    <div class="button function">+</div>

    <div class="button number">0</div>
    <div class="button function">.</div>
    <div class="button function">=</div>
  </div>
</div>
```

- `.calculator` is a container that wraps around the whole calculator.
- `.display` shows the user input, as well as the output of the calculation.
- `.buttons` contains both the `.number` buttons (0-9) and the `.function` buttons (`+`, `-`, `*`...).

And, of course, you must set up the event listeners so that when a button is clicked, the corresponding function is executed.

```html
<div class="calculator">
  <div class="display" id="display">0</div>
  <div class="buttons">
    <div class="button function" onclick="clearDisplay()">AC</div>
    <div class="button function" onclick="toggleSign()">+/-</div>
    <div class="button function" onclick="percent()">%</div>
    <div class="button function" onclick="appendOperator('/')">/</div>

    <div class="button number" onclick="appendNumber('7')">7</div>
    <div class="button number" onclick="appendNumber('8')">8</div>
    <div class="button number" onclick="appendNumber('9')">9</div>
    <div class="button function" onclick="appendOperator('*')">*</div>

    <div class="button number" onclick="appendNumber('4')">4</div>
    <div class="button number" onclick="appendNumber('5')">5</div>
    <div class="button number" onclick="appendNumber('6')">6</div>
    <div class="button function" onclick="appendOperator('-')">-</div>

    <div class="button number" onclick="appendNumber('1')">1</div>
    <div class="button number" onclick="appendNumber('2')">2</div>
    <div class="button number" onclick="appendNumber('3')">3</div>
    <div class="button function" onclick="appendOperator('+')">+</div>

    <div class="button number" id="Num0" onclick="appendNumber('0')">0</div>
    <div class="button function" onclick="appendOperator('.')">.</div>
    <div class="button function" onclick="calculate()">=</div>
  </div>
</div>
```

Before we start coding, we also need to discuss the general structure of this project.

First of all, there should be a global variable (`displayValue`) to store the displayed value, as well as a helper function (`updateDisplay()`) that updates the `.display` based on the variable. The function selects the display element and updates its content.

There should also be an `appendNumber()` and `appendOperator()` functions that append new digits to `displayValue`. Lastly, you need a `calculate()` function that executes the mathematical expression and returns the value.

And of course, there are other functions such as `clearDisplay()`, `toggleSign()`, and `percent()`.

## Adding styles

Next, you should add some styles so that our calculator actually looks like a calculator.

First of all, the `.buttons` should be a [grid layout](https://www.ericsdevblog.com/courses/html-css/4/#creating-grids) with 4 columns and 5 rows. As an example, I'm making each cell to be `100px` wide, and with a `5px` gap in between.

```css
.buttons {
  display: grid;
  grid-template-columns: 100px 100px 100px 100px;
  gap: 5px;
}
```

And then customize the individual buttons to make them look more pleasing.

```css
.button {
  padding: 20px 0px;
  text-align: center;
}

.function {
  background-color: coral;
}

.number {
  background-color: bisque;
}
```

![number pad grid](https://www.ericsdevblog.com/posts/html-css-js-calculator/images/numbers-grid.png)

The number 0 is a special case, as it [spans over multiple columns](https://www.ericsdevblog.com/courses/html-css/4/#grid-items). This can be achieved using the `grid-column-start` and `grid-column-end` properties.

```html
<div class="button number" id="Num0" onclick="appendNumber('0')">0</div>
```

```css
#Num0 {
  grid-column-start: 1;
  grid-column-end: 3;
}
```

As for the display, it may be designed however you like, as long as it looks good to you. Here is what I did:

```css
.calculator {
  width: fit-content;
}

.display {
  border: 1px solid;
  margin-bottom: 5px;
  padding: 15px 10px;
  text-align: right;
  font-family: "Courier New", Courier, monospace;
  font-size: xx-large;
}
```

## Adding scripts

And finally, for the most important part, the scripts. First of all, as we've discussed before, you need a global variable to store the value that will be displayed, as well as a helper function that updates the display based on the variable.

```javascript
let displayValue = "";

function updateDisplay() {
  if (displayValue === "") {
    document.getElementById("display").innerHTML = "0";
  } else {
    document.getElementById("display").innerHTML = displayValue;
  }
}
```

Here, I'm using the ID selector `getElementById("display")`, so make sure your display element has the correct ID as well.

```html
<div class="calculator">
  <div class="display" id="display">0</div>
  <div class="buttons">. . .</div>
</div>
```

`innerHTML` points to the content of the selected HTML node.

In this example, if the `displayValue` is empty, 0 will be displayed. If not, the actual value will be displayed.

### `appendNumber()` and `appendOperator()`

Next, you need an `appendNumber()` function that updates the `displayValue` by appending new numbers and also updates the display afterward.

```javascript
function appendNumber(number) {
  displayValue += number;
  updateDisplay();
}
```

And of course, the `appendOperator()` function does the same thing, but with the operator keys.

```javascript
function appendOperator(operator) {
  if (
    displayValue !== "" &&
    !isNaN(displayValue.charAt(displayValue.length - 1))
  ) {
    displayValue += operator;
    updateDisplay();
  }
}
```

However, this function is a bit tricker for two reasons. First, you can't have two consecutive operators. For example, the equation `12 */--+ 21` doesn't make any sense. So before adding a new operator digit, you must check that the last digit of `displayValue` is not an operator.

In this example, `displayValue.charAt(displayValue.length - 1)` retrieves the last digit of `displayValue`, `isNaN()` returns `true` if the given value is NOT a number, and `!` flips the given value. Putting them together, line 4 returns `true` if the last digit of `displayValue` is a number.

And second, an equation should not start with an operator, so you have to ensure `displayValue` is not empty before adding an operator (`displayValue !== ""`).

### `calculate()`

```javascript
function calculate() {
  if (
    displayValue !== "" &&
    !isNaN(displayValue.charAt(displayValue.length - 1))
  ) {
    try {
      const result = eval(displayValue);
      displayValue = result.toString();
      updateDisplay();
    } catch (error) {
      displayValue = "Error";
      updateDisplay();
    }
  }
}
```

The `calculate()` function is at the heart of this project, but it is actually rather easy to understand. We are using the built-in function `eval()` to do all the heavy lifting. You simply pass the `displayValue` to the function `eval()`, and it will return the result. However, you should remember to catch the potential errors, just in case the equation doesn't evaluate to a result that makes sense.

> In practice, it is not recommended to use `eval()` in the production environment, as it evaluates all JavaScript expressions given to it without proper validation, and this opens the door to code injection attacks. The source code for this article implemented a more production-ready solution, and it is available for free [here](https://ericsdevblog.ck.page/source-code).

### `clearDisplay()`

```javascript
function clearDisplay() {
  displayValue = "";
  updateDisplay();
}
```

Lastly, the `clearDisplay()` function resets `displayValue` to an empty string.

## Conclusion

You may have noticed we neglected two functions, `toggleSign()` and `percent()`. The exact implementation of these functions is available in the [source code](https://ericsdevblog.ck.page/source-code), which you can download for free. But if you prefer implementing your own version, here is a hint:

- The `toggleSign()` function should examine the first digit of `displayValue`. If it is a number, add a `-` sign in the front. If it is not a number, that means `displayValue` is already a negative value, so simply remove it.
- The `percent()` function should first convert `displayValue` into a number, and then calculate `displayValue / 100`.

If you need more assistance regarding HTML and CSS, check out my course _[HTML & CSS: A Practical Guide](https://www.ericsdevblog.com/courses/html-css/)_.

Happy coding!