<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>A simple calculator</title>
    <link rel="stylesheet" href="index.css">
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Andika+New+Basic:wght@400;700&display=swap" rel="stylesheet">
    <script src="https://kit.fontawesome.com/3d18fa0c0a.js" crossorigin="anonymous"></script>
</head>
<body>
    <div id="calculator">
        <div id="screen">
            <p id="result"></p>
            <span id="input">0</span>
        </div>
        <div id="grid">
            <button id="butC" class="reset">C</button>
            <button id="but^" class="btnOper small">x&sup2;</button>
            <button  id="but√" class="btnOper">√</button>
            <button  id="but÷" class="btnOper">÷</button>
            <button  id="but7">7</button>
            <button id="but8">8</button>
            <button id="but9">9</button>
            <button id="but×" class="btnOper">&times;</button>
            <button id="but4">4</button>
            <button id="but5">5</button>
            <button id="but6">6</button>
            <button id="but-" class="btnOper">-</button>
            <button id="but1">1</button>
            <button id="but2">2</button>
            <button id="but3">3</button>
            <button id="but+" class="btnOper">+</button>
            <button id="but/" class="small">+/-</button>
            <button id="but0">0</button>
            <button id="but.">.</button>
            <button id="but=" class="btnOper">=</button>
        </div>
    </div>
    
    
    <script type="module" src="js.js"></script>
</body>
</html>
body {
    text-align: center;
    margin: 0;
    padding: 1rem;
    background-color: #f3767c;
    font-family: 'Andika New Basic', sans-serif;
    font-weight: 700;
    user-select: none;
}
#calculator {
    width: 58vh;
    background: rgb(58,57,62);
    background: linear-gradient(124deg, rgba(58,57,62,1) 0%, rgba(19,15,16,1) 100%);
    display: block;
    margin: auto;
    padding: 5vh;
    border-radius: 4vh;
}
#screen {
    padding: 3vh;
    height: 12vh;
    background-color: #A2AF77;
    border-radius: 4vh;
    margin-bottom: 6vh;
    font-size: 6.9vh;
    text-align: right;
    
}
#result {
    color: rgba(58,57,62,0.5);
    height: 4.5vh;
    font-size: 3vh;
    position: relative;
    top: -2vh;
    right: 1vh;
    margin: 0;
}
#input {
    position: relative;
    top: -4vh;
}
#grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);   
    grid-template-rows: auto;
    column-gap: 2.5vh;
    row-gap: 3vh;
    font-size: 6vh;
}
button {
    font-family: 'Andika New Basic', sans-serif;
    font-weight: 700;
    font-size: 1em;
    color: #FBFDFD;
    background-color: #58595B;
    border: none;
    border-radius: 0.1em;
    padding: 0;
    outline: none;
    cursor: pointer;
}
button:hover {
    filter: brightness(0.9);
}
button:active {
    transform: translateY(1px) scale(0.99);
    filter: brightness(0.6);
    
}
button img {
    width: 0.8em;
}
button:disabled {
    pointer-events: none;
    filter: brightness(0.5);
    cursor: none;
}
.btnOper {
    background-color: #130F10;
}
.small {
    font-size: 0.75em;
}
.reset {
    background-color: #F27B13;
} 


const btns = document.querySelectorAll('button[id^=but]')
let input = document.getElementById('input');
let upper = document.getElementById('result');
let result = "0", num = "0";
let op = false, op2 = false;

btns.forEach(btn => {
   btn.addEventListener('click', event => {
        butType(event, btn);
        
        if(isNaN(num) || !isFinite(num)) {
            input.innerHTML = "Error!"
            btns.forEach(btn => {
                if(btn != btns[0]) {
                    btn.disabled = true;
                }
            }) 
        } else {
            if(op == false) {
                result = num;
            } 
            if (op2 == false) {
                if(Decimal(num) >= 10 ** 11 || Decimal(num) <= -(10 ** 11)) {
                    input.innerHTML = Decimal(Decimal(num).toExponential()).toPrecision(6);

                } else {
                    if(String(num).match(/e/)) {
                        input.innerHTML = parseFloat(Decimal(num).toPrecision(6));
                    } else {
                        input.innerHTML = parseFloat(String(num).slice(0, 12));
                    }
                }    
            } else {
                input.innerHTML = num;
            }
        }
        if((op2 == true || result != num) && op != false) {
            upper.innerHTML = Decimal(Decimal(result).toPrecision(11)) + "" + op
        } else {
            upper.innerHTML = ""
        }
   });
});

const butType = (event, btn) => {
    const id = event.currentTarget.id;
    switch(true) {
        case /\d/.test(id):
            butNum(id[3]);
            break;
        case /[√^]/.test(id):
            butSpecialOp(id[3]);
            break;
        case id[3] == "/": 
            butSign();
            break;
        case id[3] == ".": 
            butDot();
            break;
        case id[3] == "=":
            butEqual();
            break;
        case btn.classList.contains("btnOper"):
            butOp(id[3]);
            break;
        default:
            [op, num, op2] = [false, "0", false];
            btns.forEach(btn => {
                btn.disabled = false;
            }) 
    }
}

const butNum = (number) => {
    String(num)
    if(num == "0" || op2 == false) {
        num = number;
        op2 = true;
    } else if (num.match(/[\d\.]/g).length < 12) {
        num += number;
    }

}
const butOp = (opSign) => {
    if((op2 == true || result != num) && op != false) {
        butEqual();
    }

    [op, op2] = [opSign, false]
}
const butSpecialOp = (opSign) => {

    if(opSign == "√") {
        num = Decimal(num).squareRoot();
    } else {
        num = Decimal(num).toPower(2);
    }
    op2 = false;
}

const butDot = () => {
    num = String(num);
    if(num == "0" || op2 == false) {
        num = "0."
    } else if(!num.match(/\./) && num.match(/[\d\.]/g).length < 11) {
        num += ".";
    }
    op2 = true;
}
const butSign = () => {
    num = String(num)
    
    if(num != "0") {
        if(num[0] == "-") {
            num = num.slice(1);
        } else {
            num = "-" + num;
        }
    } 
}
const butEqual = () => {
    if(op != false) {
        num = math[op](parseFloat(result),parseFloat(num))
    }
    [op, op2, result] = [false, false, num]
}
let math = {
    '+': function (x, y) { return Decimal(x + y) },
    '-': function (x, y) { return Decimal(x - y) },
    '×': function (x, y) { return Decimal(x * y) },
    '÷': function (x, y) { return Decimal(x / y) }
};

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/decimal.js/10.2.1/decimal.min.js