DEV Community

Mik
Mik

Posted on

Build a Retro Calculator !!

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 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"

<main class="container">
  <div class="button-body">
    <button class="button-cap">1</button>
  </div>
</main>
Enter fullscreen mode Exit fullscreen mode

Styling our button body

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

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

  padding-top: 2px;
Enter fullscreen mode Exit fullscreen mode

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

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

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

  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);
Enter fullscreen mode Exit fullscreen mode

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

  &: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);
  }
Enter fullscreen mode Exit fullscreen mode

&: 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

  /* layout */
  width: 65px;
  height: 65px;
  border-radius: 5px;
Enter fullscreen mode Exit fullscreen mode

I've width and height to be slightly smaller than the button's body, and styled it as follows

  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);
Enter fullscreen mode Exit fullscreen mode

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

    &: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;
  }
Enter fullscreen mode Exit fullscreen mode

and this should give us a button !!

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 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 !

.top-rows {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 3px;
}
Enter fullscreen mode Exit fullscreen mode

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%;
}
Enter fullscreen mode Exit fullscreen mode

here's the result !!

Create a retro display

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

  <input class="display" readonly type="text" dir="rtl" maxlength="8" placeholder="88888" />
Enter fullscreen mode Exit fullscreen mode

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.

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

  padding: 5px;
  height: 75px;
  width: 320px;
Enter fullscreen mode Exit fullscreen mode

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.

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

For the numbers, I picked the font Autowide again.

  color: black;
  font-size: 3rem;
  font-family: "Audiowide", cursive;
Enter fullscreen mode Exit fullscreen mode

Here's the result !!

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

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

    <div class="button-grid">
.....
Enter fullscreen mode Exit fullscreen mode

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

.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;
}
Enter fullscreen mode Exit fullscreen mode

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.

 function handleNumberClick(value) {
     if (currentInput.length < 8) {
      currentInput += value;
    }
  }
Enter fullscreen mode Exit fullscreen mode

and secondly

function calculateResult() {
    .....
    currentInput = currentInput.length > 8 ? 'ERROR' : currentInput;
  }
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)