Build a Simple Calculator: HTML, CSS, JavaScript Tutorial (Source Code)


By Faraz -

Step-by-step guide to building a simple calculator app using HTML, CSS, and JavaScript. Ideal for newcomers to web development.

Build a Simple Calculator HTML, CSS, JavaScript Tutorial.webp

Building a basic calculator from scratch is a great way to understand fundamental web development concepts. In this tutorial, we'll create a simple calculator using HTML for structure, CSS for styling, and JavaScript for functionality.

Source Code

Step 1 (HTML Code):

Start by creating an HTML file and setting up the basic structure. Define the necessary elements such as buttons, display screen, and container divs.

Let's break down the HTML code step by step:

1. <!DOCTYPE html>: This declaration tells the browser that the document is an HTML5 document.

2. <html lang="en">: This tag indicates the start of the HTML document. The lang="en" attribute specifies that the primary language of the document is English.

3. <head>: This section contains meta-information about the HTML document, such as character encoding, viewport settings, stylesheets, scripts, and the document's title.

  • <meta charset="UTF-8" />: Specifies the character encoding for the document as UTF-8, which supports a wide range of characters.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0" />: Sets the viewport properties for responsive design. It ensures that the width of the page is set to the width of the device and the initial zoom level is set to 1.0.
  • <link rel="stylesheet" href="styles.css" />: Links an external CSS file named "styles.css" to apply styles to the HTML document.
  • <link href="https://fonts.goo.." rel="stylesheet" />: Links an external font file from Google Fonts, specifically the Roboto font, to be used in the document.
  • <script src="https://kit.fo.." crossorigin="anonymous"></script>: Links the Font Awesome icon library for the use of icons in the document.
  • <script src="script.js" defer></script>: Links an external JavaScript file named "script.js" with the "defer" attribute, which means the script will be executed after the document is parsed.
  • <title>Calculator</title>: Sets the title of the HTML document to "Calculator".

4. <body>: This section contains the content of the HTML document that will be displayed in the browser.

  • <main class="main">: Defines the main content of the page.
  • <div class="calculator">: Represents the calculator interface.
  • <div class="screen">: Contains the display screen of the calculator.
  • <div class="screen-last" id="lastOperationScreen"></div>: Creates a div element for displaying the last operation performed.
  • <div class="screen-current" id="currentOperationScreen">0</div>: Creates a div element for displaying the current operation. It initially displays "0".
  • <div class="buttons-grid">: Contains the buttons for the calculator.
  • Various <button> elements: Represent buttons for numbers, operators, and other functionalities of the calculator. They have specific classes and attributes for styling and functionality. Some buttons have data-number or data-operator attributes to distinguish between numbers and operators.
  • Some buttons have onclick="this.blur();" attribute, which is used to remove the focus from the button after clicking, preventing visual feedback from clicking on some devices.
  • <button class="btn" onclick="this.blur();" id="pointBtn">.</button>: Represents the decimal point button.
  • <button class="btn" onclick="this.blur();" id="equalsBtn">=</button>: Represents the equals button.

5. </body>: Indicates the end of the body section.

6. </html>: Indicates the end of the HTML document.

Step 2 (CSS Code):

Apply CSS to enhance the visual appeal of the calculator. Style the buttons, display area, and overall layout to make it user-friendly and visually pleasing.

Let's break down each part:

1. Custom Properties (:root):

  • :root is a CSS pseudo-class that represents the root element of the document, which is usually <html>.
  • Custom properties, denoted by --property-name, are defined here to store color values that will be reused throughout the stylesheet.

2. Global Reset (*, *::before, *::after):

  • This rule sets box-sizing to border-box, which ensures that padding and border are included in the element's total width and height.
  • It resets padding and margin to 0 for all elements.

3. HTML and Body Styles:

  • html and body elements are styled to set the background color and font color using the custom properties defined earlier.
  • font-family is set to 'Roboto', a sans-serif font.
  • line-height is set to 1.6.
  • margin-bottom is set to 100px to accommodate for a potential footer.

4. Button Styles:

  • Styles for buttons are defined here.
  • border, color, font-family, and font-size are inherited from the parent element (button).
  • cursor is set to pointer to indicate interactivity.
  • outline is set to none to remove default focus outlines.

5. Main Layout (.main):

  • .main class sets up the main container for the calculator.
  • It's styled as a flex container to center its children both horizontally and vertically.
  • height is set to 75vh (75% of the viewport height), with a minimum height of 500px.
  • padding and margin-top are applied.

6. Calculator (.calculator):

  • Styles for the calculator itself.
  • It has a fixed width, border, border radius, padding, and background color.

7. Screen Styles (.screen):

  • Styles for the display screen of the calculator.
  • It has padding, border, border-radius, margin, background color, text alignment, and word-wrapping properties.

8. Button Grid (.buttons-grid):

  • Defines a grid layout for the buttons with 4 equal columns and a gap of 10px.

9. Button Styles (.btn, .btn-red, .btn-blue):

  • Styles for the calculator buttons.
  • They have padding, border, border-radius, background color, and font size properties.
  • .btn:hover, .btn:active, .btn-red:hover, .btn-red:active, .btn-blue:hover, .btn-blue:active define styles for button hover and active states.

10. Disabling Input Spinners:

  • This part disables input spinners (up and down arrows) for number inputs inside the calculator screen.
:root {
  --background: #f6f6f6;
  --font: #222;
  --border: #333;
  --screen: #eee;
  --calculator: #aaa;
  --btn: #eee;
  --btn-hover: #ddd;
  --btn-active: #ccc;
  --btn-red: #faa;
  --btn-red-hover: #e99;
  --btn-red-active: #d88;
  --btn-blue: #aaf;
  --btn-blue-hover: #99e;
  --btn-blue-active: #88d;

*::after {
  box-sizing: border-box;
  padding: 0;
  margin: 0;

html {
  /* footer support */
  position: relative;
  min-height: 100%;

body {
  background-color: var(--background);
  color: var(--font);
  font-family: 'Roboto', sans-serif;
  line-height: 1.6;
  /* footer support */
  margin-bottom: 100px;

button {
  border: none;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
  outline: none;

/* MAIN */

.main {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 75vh;
  min-height: 500px;
  padding: 10px;
  margin-top: 50px;

.calculator {
  width: 400px;
  border: 2px var(--border) solid;
  border-radius: 15px;
  padding: 20px;
  background-color: var(--calculator);

.screen {
  padding: 10px 20px;
  border: 2px var(--border) solid;
  border-radius: 5px;
  margin-bottom: 20px;
  background-color: var(--screen);
  text-align: right;
  word-wrap: break-word;
  word-break: break-all;

.screen-last {
  min-height: 32px;
  font-size: 20px;

.screen-current {
  min-height: 64px;
  font-size: 40px;

.buttons-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 10px;

.span-2 {
  grid-column: span 2;

.btn {
  padding: 20px;
  border: 2px var(--border) solid;
  border-radius: 5px;
  background-color: var(--btn);
  font-size: 20px;

.btn:hover {
  background-color: var(--btn-hover);

.btn:active {
  background-color: var(--btn-active);

.btn-red {
  background-color: var(--btn-red);

.btn-red:hover {
  background-color: var(--btn-red-hover);

.btn-red:active {
  background-color: var(--btn-red-active);

.btn-blue {
  background-color: var(--btn-blue);

.btn-blue:hover {
  background-color: var(--btn-blue-hover);

.btn-blue:active {
  background-color: var(--btn-blue-active);

/* Disables input spinners in calc screen */
input[type='number']::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;

Step 3 (JavaScript Code):

Utilize JavaScript to add functionality to the calculator. Implement event listeners for button clicks, perform calculations based on user input, and update the display accordingly.

Let's break down the code step by step:

1. Variable Declarations:

  • firstOperand, secondOperand: Store the operands for arithmetic operations.
  • currentOperation: Stores the current operation being performed.
  • shouldResetScreen: Indicates whether the calculator screen should be reset before displaying the next input.

2. DOM Elements:

  • It selects various DOM elements such as number buttons, operator buttons, equals button, clear button, delete button, and point button, and assigns them to respective variables using document.getElementById() and document.querySelectorAll().

3. Event Listeners:

  • Event listeners are attached to the number buttons, operator buttons, equals button, clear button, delete button, and point button. These listeners trigger specific functions when these elements are interacted with.

4. Event Handlers:

  • handleKeyboardInput(e): Handles keyboard inputs and calls respective functions based on the pressed key.
  • appendNumber(number): Appends numbers to the calculator screen.
  • resetScreen(): Resets the calculator screen.
  • clear(): Clears the calculator screen and resets all operands and operations.
  • appendPoint(): Adds a decimal point to the current number.
  • deleteNumber(): Deletes the last digit from the current number.
  • setOperation(operator): Sets the operation to be performed based on the selected operator.
  • evaluate(): Evaluates the arithmetic expression entered and displays the result on the calculator screen.
  • roundResult(number): Rounds the result to three decimal places.
  • convertOperator(keyboardOperator): Converts the keyboard operator symbols to their respective mathematical symbols.

5. Arithmetic Functions:

  • add(a, b), subtract(a, b), multiply(a, b), divide(a, b): Basic arithmetic operations.

6. Operate Function:

  • operate(operator, a, b): Performs the specified arithmetic operation on two operands.
let firstOperand = ''
let secondOperand = ''
let currentOperation = null
let shouldResetScreen = false

const numberButtons = document.querySelectorAll('[data-number]')
const operatorButtons = document.querySelectorAll('[data-operator]')
const equalsButton = document.getElementById('equalsBtn')
const clearButton = document.getElementById('clearBtn')
const deleteButton = document.getElementById('deleteBtn')
const pointButton = document.getElementById('pointBtn')
const lastOperationScreen = document.getElementById('lastOperationScreen')
const currentOperationScreen = document.getElementById('currentOperationScreen')

window.addEventListener('keydown', handleKeyboardInput)
equalsButton.addEventListener('click', evaluate)
clearButton.addEventListener('click', clear)
deleteButton.addEventListener('click', deleteNumber)
pointButton.addEventListener('click', appendPoint)

numberButtons.forEach((button) =>
  button.addEventListener('click', () => appendNumber(button.textContent))

operatorButtons.forEach((button) =>
  button.addEventListener('click', () => setOperation(button.textContent))

function appendNumber(number) {
  if (currentOperationScreen.textContent === '0' || shouldResetScreen)
  currentOperationScreen.textContent += number

function resetScreen() {
  currentOperationScreen.textContent = ''
  shouldResetScreen = false

function clear() {
  currentOperationScreen.textContent = '0'
  lastOperationScreen.textContent = ''
  firstOperand = ''
  secondOperand = ''
  currentOperation = null

function appendPoint() {
  if (shouldResetScreen) resetScreen()
  if (currentOperationScreen.textContent === '')
    currentOperationScreen.textContent = '0'
  if (currentOperationScreen.textContent.includes('.')) return
  currentOperationScreen.textContent += '.'

function deleteNumber() {
  currentOperationScreen.textContent = currentOperationScreen.textContent
    .slice(0, -1)

function setOperation(operator) {
  if (currentOperation !== null) evaluate()
  firstOperand = currentOperationScreen.textContent
  currentOperation = operator
  lastOperationScreen.textContent = `${firstOperand} ${currentOperation}`
  shouldResetScreen = true

function evaluate() {
  if (currentOperation === null || shouldResetScreen) return
  if (currentOperation === '÷' && currentOperationScreen.textContent === '0') {
    alert("You can't divide by 0!")
  secondOperand = currentOperationScreen.textContent
  currentOperationScreen.textContent = roundResult(
    operate(currentOperation, firstOperand, secondOperand)
  lastOperationScreen.textContent = `${firstOperand} ${currentOperation} ${secondOperand} =`
  currentOperation = null

function roundResult(number) {
  return Math.round(number * 1000) / 1000

function handleKeyboardInput(e) {
  if (e.key >= 0 && e.key <= 9) appendNumber(e.key)
  if (e.key === '.') appendPoint()
  if (e.key === '=' || e.key === 'Enter') evaluate()
  if (e.key === 'Backspace') deleteNumber()
  if (e.key === 'Escape') clear()
  if (e.key === '+' || e.key === '-' || e.key === '*' || e.key === '/')

function convertOperator(keyboardOperator) {
  if (keyboardOperator === '/') return '÷'
  if (keyboardOperator === '*') return '×'
  if (keyboardOperator === '-') return '−'
  if (keyboardOperator === '+') return '+'

function add(a, b) {
  return a + b

function substract(a, b) {
  return a - b

function multiply(a, b) {
  return a * b

function divide(a, b) {
  return a / b

function operate(operator, a, b) {
  a = Number(a)
  b = Number(b)
  switch (operator) {
    case '+':
      return add(a, b)
    case '−':
      return substract(a, b)
    case '×':
      return multiply(a, b)
    case '÷':
      if (b === 0) return null
      else return divide(a, b)
      return null

Final Output:

Build a Simple Calculator HTML, CSS, JavaScript Tutorial.gif

See the Pen Untitled by Faraz (@codewithfaraz) on CodePen.


Congratulations! You've successfully created a basic calculator using HTML, CSS, and JavaScript. This project serves as a solid foundation for further exploration into web development.

By following these steps, you can easily create a basic calculator app from scratch. Experiment with different designs and functionalities to further enhance your skills in web development. Happy coding!

Code by: Michal Osman

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox

Latest Post