Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <body class="body">
  <div class="calculator">
    <div class="calculator__top">
      <div class="calculator__heading">
        <h1 class="calculator__title">CATLOGIC</h1>
        <h2 class="calculator__subtitle">CL-001</h2>
      </div>
      <div class="calculator__sun-battery-container">
        <div class="calculator__sun-battery"></div>
      </div>
    </div>
    <div class="calculator__screen-container">
      <p class="calculator__screen-mem">M</p>
      <input type="text" class="calculator__screen" name="screen" value="0"
        maxlength="10" disabled>
    </div>
    <div class="calculator__keyboard">
      <button type="button" data-type="clear" class="button button_type_reset"
        value="C">C</button>
      <button type="button" data-type="memory" class="button button_type_memory"
        value="MRC">MRC</button>
      <button type="button" data-type="memory" class="button button_type_memory"
        value="MMINUS">M-</button>
      <button type="button" data-type="memory" class="button button_type_memory"
        value="MPLUS">M+</button>
      <button type="button" data-type="function"
        class="button button_type_advanced" value="NEGATE">+/-</button>
      <button type="button" data-type="function"
        class="button button_type_advanced" value="PERCENT">%</button>
      <button type="button" data-type="function"
        class="button button_type_advanced" value="SQUARE">
        <svg class="square-symbol" viewBox="0 0 33 23" fill="none"
          xmlns="http://www.w3.org/2000/svg">
          <path d="M2 10l5 11h2.5l6-19H33" stroke="#fff" stroke-width="3" />
          </svg>
      </button>
      <button type="button" data-type="function"
        class="button button_type_operation" value="BACKSPACE">
        <svg class="backspace-symbol" viewBox="0 0 27 22" fill="none"
          xmlns="http://www.w3.org/2000/svg">
          <path d="M12 2l-9 9 9 9M3 11h24" stroke="#fff" stroke-width="3" />
          </svg>
      </button>
      <button type="button" data-type="number" class="button button_type_number"
        value="7">7</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="8">8</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="9">9</button>
      <button type="button" data-type="operation"
        class="button button_type_operation" value="DIVIDE">÷</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="4">4</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="5">5</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="6">6</button>
      <button type="button" data-type="operation"
        class="button button_type_operation" value="MULTIPLY">×</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="1">1</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="2">2</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="3">3</button>
      <button type="button" data-type="operation"
        class="button button_type_operation" value="SUBTRACT">-</button>
      <button type="button" data-type="number" class="button button_type_number"
        value="0">0</button>
      <button type="button" data-type="number" class="button button_type_number"
        value=".">.</button>
      <button type="button" data-type="equals"
        class="button button_type_operation" value="EQUALS">=</button>
      <button type="button" data-type="operation"
        class="button button_type_operation" value="ADD">+</button>
    </div>
  </div>
</body>
              
            
!

CSS

              
                .body {
  padding: 0;
  margin: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-image: linear-gradient(to top, #09203f 0%, #537895 100%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
}

.calculator {
  width: 300px;
  min-width: 300px;
  box-sizing: border-box;
  padding: 20px 25px 45px;
  background: radial-gradient(ellipse farthest-corner at 20% 65%, #525864, #130f0e);
  color: rgba(255, 255, 255, .8);
  font-family: 'Overpass Mono', monospace;
  border-top-left-radius: 100% 30px;
  border-top-right-radius: 100% 30px;
  border-bottom-left-radius: 100% 60px;
  border-bottom-right-radius: 100% 60px;
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, .7),
    0 0 20px 0 rgba(0, 0, 0, .5),
    0 0 25px 0 rgba(0, 0, 0, .3),
    10px 0 4px 10px rgba(0, 0, 0, .3),
    inset 0 0 3px 0 rgba(0, 0, 0, .7),
    inset 0 0 10px 0 rgba(0, 0, 0, .5),
    inset 0 -25px 5px 0 rgba(0, 0, 0, .2),
    inset 0 -5px 10px 0 rgba(255, 255, 255, .3);
}

.calculator__top {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.calculator__heading {
  font-family: 'Slabo 27px', serif;
  text-shadow: 0 0 2px rgba(255, 255, 255, .2);
}

.calculator__title {
  margin: 0 0 -4px;
  font-size: 25px;
}

.calculator__subtitle {
  margin: 0;
  font-size: 18px;
}

.calculator__sun-battery-container {
  border-radius: 3px;
  border-right: 1px solid rgba(255, 255, 255, .2);
}

.calculator__sun-battery {
  width: 107px;
  height: 30px;
  border-radius: 3px;
  background-color: #3d2115;
  box-shadow: 0 -3px 5px -3px rgba(255, 255, 255, .2),
    5px 0 3px -5px rgba(255, 255, 255, .8),
    0 2px 5px -2px rgba(0, 0, 0, .5),
    -3px 0 3px -1px rgba(0, 0, 0, .8),
    inset 0 -5px 3px -3px rgba(0, 0, 0, .5),
    inset 5px 0 5px -2px rgba(0, 0, 0, .8);
  background-image: repeating-linear-gradient(to right,
      transparent,
      transparent 26px,
      rgba(255, 255, 255, .1) 26px,
      rgba(255, 255, 255, .1) 27px);
  /* box-shadow: inset 0 0 3px 0 rgba(0, 0, 0, .5); */
}

.calculator__screen-container {
  position: relative;
  margin: 20px 0;
  border-radius: 5px;
  border-right: 1px solid rgba(255, 255, 255, .2);
}

.calculator__screen {
  background-image: linear-gradient(-155deg, #44443a 0%, #656f66 100%);
  width: 100%;
  display: block;
  box-sizing: border-box;
  border: 0;
  text-align: right;
  font-size: 40px;
  padding: 10px;
  font-family: 'Share Tech Mono', monospace;
  letter-spacing: -2px;
  border-radius: 5px;
  box-shadow: 0 -4px 4px -3px rgba(255, 255, 255, .3),
    5px 0 3px -5px rgba(255, 255, 255, .8),
    0 5px 5px -3px rgba(0, 0, 0, .5),
    -3px 0 3px -1px rgba(0, 0, 0, .8),
    inset 0 -5px 3px -4px rgba(0, 0, 0, .5),
    inset 5px 0 5px -2px rgba(0, 0, 0, .8);
}

.calculator__screen:disabled {
  color: #000;
}

.calculator__screen-mem {
  font-family: 'Share Tech Mono', monospace;
  position: absolute;
  top: 0;
  left: 12px;
  color: #000;
  font-size: 20px;
  line-height: 18px;
  visibility: hidden;
}

.calculator__screen-mem_visible {
  visibility: visible;
}

.calculator__keyboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 30px) repeat(4, 40px);
  gap: 15px;
}

.button {
  font-family: inherit;
  font-size: 30px;
  border-radius: 7px;
  border: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  padding-top: 5px;
  letter-spacing: -2px;
  outline: none;
  position: relative;
  background: linear-gradient(25deg, #525a65, #3b424c);
  color: rgba(255, 255, 255, .8);
  text-shadow: 0 0 2px rgba(255, 255, 255, .2);
  box-shadow: inset 2px -1px 1px 0 rgba(255, 255, 255, .2),
    inset -3px 2px 5px 0 rgba(0, 0, 0, .2),
    4px 1px 1px 0 rgba(0, 0, 0, .5),
    -1px -3px 1px 0 rgba(0, 0, 0, .5),
    4px -3px 1px 0 rgba(0, 0, 0, .5),
    -1px -1px 5px 0 rgba(0, 0, 0, .5);
  /* 5px -1px 1px 0 rgba(255, 255, 255, .3); */
}

.button:active {
  box-shadow: inset 2px -1px 1px 0 rgba(255, 255, 255, .2),
    inset -3px 2px 5px 0 rgba(0, 0, 0, .2),
    3px 1px 1px 0 rgba(0, 0, 0, .5),
    -1px -1px 1px 0 rgba(0, 0, 0, .5),
    3px -1px 1px 0 rgba(0, 0, 0, .5),
    -1px -1px 5px 0 rgba(0, 0, 0, .5),
    4px 0 1px 0 rgba(255, 255, 255, .3);
  transform: translate(1px, -1px);
}

.button[value="NEGATE"] {
  font-size: 20px;
}

.button[value="SQUARE"],
.button[value="BACKSPACE"] {
  padding: 0;
}

.square-symbol {
  width: 31px;
  height: 19px;
}

.button_type_operation {
  font-size: 36px;
}

.button_type_memory {
  font-size: 24px;
}

.button_type_advanced {
  font-size: 24px;
}

.button_type_reset {
  background: linear-gradient(25deg, #9cc9dc, #68a4c0);
}

.backspace-symbol {
  width: 24px;
  height: 18px;
}

              
            
!

JS

              
                'use strict';

const buttons = document.querySelectorAll('.button');
const currentOutput = document.querySelector('.calculator__screen');
const memoryIndicator = document.querySelector('.calculator__screen-mem');
const result = [];
let currentOperator = null;
let operator = null;
let equalsPressed = false;
let secondValue = null;
let functionAdded = false;
let memory = 0;

// Return the number currently on screen
const getOutput = () => currentOutput.value;
// Convert & put the number on screen
const setOutput = (value) =>
  (currentOutput.value = value.toString().slice(0, 10));

const printNumber = (value) => {
  let output = getOutput();
  // Reset after pressing 'EQUALS' || on error
  if (equalsPressed || output === 'Error') {
    reset();
    output = '';
  }
  // If operator was pressed clear the screen
  if (currentOperator) {
    operator = currentOperator;
    currentOperator = null;
    output = '';
  }
  // If functional key was pressed clear the screen
  if (functionAdded) {
    functionAdded = false;
    output = '';
  }
  // Only one decimal point allowed, removing leading zero
  if (value === '.') {
    if (output.indexOf('.') !== -1) return;
  } else if (output === '0') output = '';
  // Print the number if typed
  setOutput((output += value));
};

const addOperator = (operation) => {
  // Prevent logging of multiple operation pressing || operations on error
  if (currentOperator || getOutput() === 'Error') return;
  // Ability to continue calculation after 'EQUALS' operation
  if (equalsPressed) operator = null;
  // Continue calculation without 'EQUALS' pressed
  if (operator) calculateResultHandler();
  // Clear 'calculation complete' & 'function key pressed' flags
  equalsPressed = false;
  functionAdded = false;
  // Add to the log
  result.push(+getOutput(), operation);
  // Save the operator for the calculation
  currentOperator = operation;
};

const calculateResultHandler = () => {
  // Memorize result if 'EQUALS' pressed again
  if (equalsPressed) result.push(+getOutput(), operator);
  // Setting up values for the calculation
  else secondValue = +getOutput();
  const firstValue = result[result.length - 2];
  // Forbid dividing by zero
  if (operator === 'DIVIDE' && secondValue === 0) {
    setOutput('Error');
    return;
  }
  let resultValue = calculateResult(operator, firstValue, secondValue);
  result.push(secondValue, 'EQUALS');
  // Setting 'calculation complete' flag
  equalsPressed = true;
  console.log(result);
  // Show 'Error' if result is bigger than the screen length
  if (resultValue > 9999999999) {
    setOutput('Error');
    operator = null;
  } else setOutput(resultValue);
};

const calculateResult = (operation, firstValue, secondValue) => {
  switch (operation) {
    case 'ADD':
      return +math.add(math.bignumber(firstValue), math.bignumber(secondValue));
    case 'SUBTRACT':
      return +math.subtract(
        math.bignumber(firstValue),
        math.bignumber(secondValue)
      );
    case 'MULTIPLY':
      return +math.multiply(
        math.bignumber(firstValue),
        math.bignumber(secondValue)
      );
    case 'DIVIDE':
      return +math.divide(
        math.bignumber(firstValue),
        math.bignumber(secondValue)
      );
  }
};

const addFunction = (func) => {
  let output = getOutput();
  if (output === 'Error' || output === '0') return;
  switch (func) {
    case 'NEGATE':
      output = -output;
      break;
    case 'SQUARE':
      // Prevent for negative numbers
      if (+output >= 0) {
        //TODO Write to log
        output = +math.sqrt(math.bignumber(output));
        // Setting 'function key pressed' flag
        functionAdded = true;
      } else {
        output = 'Error';
      }
      break;
    case 'PERCENT':
      output = +math.multiply(math.bignumber(output), 0.01);
      // Setting 'function key pressed' flag
      functionAdded = true;
      break;
    case 'BACKSPACE':
      // Prevent deleting when calculation is in progress
      if (currentOperator) return;
      if (output.length > 1) {
        output = output.slice(0, -1);
      } else output = 0;
      break;
  }
  setOutput(output);
};

const memoryAccess = (type) => {
  let output = getOutput();
  if (output === 'Error') return;
  switch (type) {
    case 'MPLUS':
      memory += +output;
      memoryIndicator.classList.add('calculator__screen-mem_visible');
      break;
    case 'MMINUS':
      memory -= +output;
      memoryIndicator.classList.add('calculator__screen-mem_visible');
      break;
    //TODO Clear memory
    case 'MRC':
      setOutput(memory);
      // Enable calculation with memory recall as second argument
      if (currentOperator) operator = currentOperator;
      currentOperator = null;
  }
  functionAdded = true;
};

const buttonHandler = (type, value) => {
  switch (type) {
    case 'number':
      printNumber(value);
      break;
    case 'operation':
      addOperator(value);
      break;
    case 'equals':
      // If the calculation is in progress
      if (operator) calculateResultHandler();
      break;
    case 'clear':
      reset();
      break;
    case 'function':
      addFunction(value);
      break;
    case 'memory':
      memoryAccess(value);
      break;
  }
};

const reset = () => {
  currentOperator = null;
  operator = null;
  equalsPressed = false;
  secondValue = null;
  result.length = 0;
  memory = 0;
  memoryIndicator.classList.remove('calculator__screen-mem_visible');
  setOutput(0);
  console.clear();
};

for (const element of buttons) {
  element.addEventListener('click', function handler() {
    buttonHandler(element.dataset.type, element.value);
  });
}

              
            
!
999px

Console