Build a Retro Calculator !!
Tags: retro, css, art, tutorial
Published: 2023-12-22 22:22:39

I got this idea to whip up a realistic looking retro calculator just for the sheer fun of coding it out, and I figured "Why not document the whole journey in a blog for anyone to read and follow along?", so here we are !

To start with, you'll need some knowledge over the web dev trifecta: HTML, CSS and JS.

I picked the font [Audiowide](https://fonts.google.com/specimen/Audiowide) from Google Fonts because I felt it had a cool retro vibe to it.

Note: The layout and all the visual jazz of the calculator is going to be built in HTML and SCSS, and as for the calculator's logic, I'm using the power of Vanilla JS.


## The Steps

I've broken this down into a series of steps which lets us create a calculator easily !!

Steps:

1. Create a button
2. Create a grid of buttons
3. Create a retro display
4. Create the case and put everything in it !!
5. Add some JS magic

At the end of each section, you'll find a CodePen link that has the complete code. Feel free to check it out and tinker with it! 🛠️

So, let's get started !!

## Creating a Retro Button

This is the basic layout I'm going to use for the button !!

### We have a "button body" and the "button cap"

```html
<main class="container">
  <div class="button-body">
    <button class="button-cap">1</button>
  </div>
</main>
```

### Styling our button body

Let's look at the layout of the `button-body`

```css
  display: flex;
  justify-content: center;
  width: 75px;
  height: 75px;

  padding-top: 2px;
```

I'm using flexbox here for layouts, and `justify-content: center` sets the `button-cap` to the center of the `button-body`

I picked the `width` and `height` by playing around with the values, I was satisfied with how `75px` looked and felt.

`padding-top` lets me offset the `button-cap` from the top of the `button-body`

Note: See how I'm not using `align` properties that FlexBox provides for vertical alignment. If we were to use `align-items: center` then the `button-cap` would be aligned perfectly to the center of the `button-body`, but that's not going to make the button look realistic...


Now, let's style the button !!

To give it a retro and realistic look, we need to employ the POWER OF THE SHADOWS and GRADIENTS !!!!

Shadows and gradients make flat things look like they have shadows and light shining on them, making them seem 3D even though they're not !!

For the shadows and gradients, I'm using this handly tool [neumorphism.io](https://neumorphism.io/#e0e0e0)

This lets me play around with shadow directions, shape and intensity !!

After playing around with the colours and values, I arrived at this !

```css
  background: linear-gradient(145deg, rgb(120, 118, 99), #fff9d6);
  border-radius: 3px;
  box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 0px 2px rgba(16, 22, 26, 0.2),
    0 0px 1px rgba(16, 22, 26, 0.2);
```

and now, we need to add some effects to the button, so when it's clicked, it feels looks like it was clicked !!

```css
  &:active {
    transform: scale(0.95);
    background: linear-gradient(145deg, rgb(120, 118, 99), #fff9d6);
    box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 0px 2px rgba(16, 22, 26, 0.2),
      0 0px 1px rgba(16, 22, 26, 0.2);
  }
```

`&:` in SCSS is a nifty feature that allows me to style the active state of the button-body within the same class. When the button is in the "active" state (like when it's pressed), I've used it to make the button appear a bit smaller by scaling it down.

### Styling our button cap

```css
  /* layout */
  width: 65px;
  height: 65px;
  border-radius: 5px;
```
I've `width` and `height` to be slightly smaller than the button's body, and styled it as follows

```css
  border: none;
  background: linear-gradient(145deg, #d6d2b4, #fff9d6);
  box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 0px 2px rgba(16, 22, 26, 0.2),
    0 0px 1px rgba(16, 22, 26, 0.2);
```

as for effects, I'm just scaling it down and adding an on-hover property to change the cursor to a pointer.

```css
    &:active {
    transform: scale(0.95);
    background: linear-gradient(145deg, #d6d2b4, #fff9d6);
    box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 0px 2px rgba(16, 22, 26, 0.2),
      0 0px 1px rgba(16, 22, 26, 0.2);
  }

  &:hover {
    cursor: pointer;
  }
```

and this should give us a button !!

{% codepen https://codepen.io/Mik1337/pen/ExrXyVZ %}

## Creating a grid of buttons

Now let's take this button and set them in a grid !!

Note: Using a framework like ReactJS is best for this, you can create one button component and use that instead of copy-pasting the code like I've done here lol

There's three main things to note here.

1. Some buttons are blue
2. The first 4 rows are laid out in a CSS Grids
3. The last row is using FlexBox

To find the `background-color: linear gradient` you want to use, play around with this [neumorphism.io](https://neumorphism.io/#e0e0e0) until you're satisfied.

I'm setting the first 4 rows with CSS Grid because it's the most convenient way to do so !

All you have to do is this !

```css
.top-rows {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 3px;
}
```

If you open up your calculator app or if you have a calculator with you, then you'd notice that the buttons in the last row always stretch a little more than the buttons in other rows, and the most convenient way i could do this is using FlexBox, and playing with the width of the wide buttons

```
.bottom-row {
  display: flex;
  justify-content: space-between;
  gap: 5px;
  padding-top: 3px;
}

.wider-button {
  width: 35%;
}

.wider-cap {
  width: 90%;
}
```

here's the result !!

{% codepen https://codepen.io/Mik1337/pen/dyaRXxw %}

## Create a retro display

Creating a display is pretty straight forward, I'm using an input with the following properties

```html
  <input class="display" readonly type="text" dir="rtl" maxlength="8" placeholder="88888" />
```

### Styling the Input Box

For the layout, I've set the `height` to `75px` to match the button body height, and a `width` of `320px` to match the buttons when we put it in a calculator.

```css
  box-sizing: border-box;
  overflow: hidden;

  padding: 5px;
  height: 75px;
  width: 320px;
```

for the display colour, I picked this nice shade of green, and the box shadow makes the display look 3D and stuck in place, just like some old calculators I've seen.

```css
background: rgba(56, 62, 37, 1);
  box-shadow: inset 1px 1px 6px 0px #050505, 0px 0px 4px 2px #000,
    0px 0px 4px 2px #777;
```

For the numbers, I picked the `font` Autowide again.
```css
  color: black;
  font-size: 3rem;
  font-family: "Audiowide", cursive;
```

Here's the result !!
{% codepen https://codepen.io/Mik1337/pen/LYqLRVX %}

## create a retro calculator case

for this all we have to do is wrap wrap the "Display" and "Buttons" in a "Calculator Case" Div and style it appropriately 

```html
 <div class="calculator-case">
    <input id="display" class="display" readonly type="text" dir="rtl" maxlength="8" placeholder="88888" />

    <div class="button-grid">
.....
```

I picked a similar colour to buttons itself (i ran out of creativity here), but compensated for it with some box-shadows !!

```css
.calculator-case {
  /* layout */
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 25px;

  /* style */
  border-radius: 15px;
  background: #d6d2b4;
  box-shadow: inset 5px 5px 18px #c7c3a7, inset -5px -5px 18px #e5e1c1;
}
```

{% codepen https://codepen.io/Mik1337/pen/zYezKbb %}

## Ths JS Magix

Alright, so the previous codepen had the JS in it. Most of it is your standard stuff, but I wanted this Calculator to behave retro too, so I added these in 

Firstly, if the `currentInput` is greater than `8`, i.e. if you're inputting a number bigger than 8 digits long, it just won't record the value.

```js
 function handleNumberClick(value) {
     if (currentInput.length < 8) {
      currentInput += value;
    }
  }
```

and secondly
```js
function calculateResult() {
    .....
    currentInput = currentInput.length > 8 ? 'ERROR' : currentInput;
  }
```

When I'm calculating the result, if the result is bigger longer than 8 digits, I just return an ERROR.

NOW, I KNOW THIS MAKES THE CALCULATOR PRETTY USELESS, BUT THIS IS A VANITY PROJECT SO YEAH, IT'S PRETTY USELESS.

Thank you for reading along. 


PS: This is my first time writing something like this, and i pro-castinated the crap out of it. Initially i was going to write the blog in the css / html file itself, but i scraped that idea when my css file was filled with badly written comments (if u find them, sorry)

PPS: Lmk if you liked it, or if you have any feedback for me.