Build a Calculator Chrome Extension: Scientific Calculator in Your Browser
Have you ever needed to quickly calculate something while browsing the web? Maybe you are comparing prices, converting currencies, or working through a mathematical problem while reading an article. Opening a separate calculator application breaks your workflow and costs precious seconds. This is exactly the problem that a Chrome extension calculator solves.
In this comprehensive guide, we will walk through building a fully functional scientific calculator Chrome extension from scratch. You will learn how to create a popup-based extension using Manifest V3, implement mathematical operations with JavaScript, style an intuitive user interface, and publish your creation to the Chrome Web Store. By the end of this tutorial, you will have a professional-grade calculator extension that lives right in your browser toolbar.
Why Build a Calculator Chrome Extension?
Calculator extensions are among the most useful and popular types of browser extensions. They fill a genuine need that Chrome’s built-in tools do not address. While Chrome has some basic functionality, a dedicated scientific calculator extension offers significant advantages that make the development effort worthwhile.
The primary benefit is instant access. With a calculator Chrome extension, you click the extension icon and immediately have a full-featured mathematical tool at your fingertips. There is no need to switch windows, minimize applications, or search for a calculator app. The calculator appears in a small popup directly in your browser, exactly where you need it.
Another advantage is customization. When you build your own calculator extension, you control every feature. You can add the specific mathematical functions you need, whether that is basic arithmetic, scientific operations like trigonometry and logarithms, or even programmable functions. This level of customization is impossible with generic calculator apps.
From a learning perspective, building a calculator extension is an excellent project for understanding Chrome extension development. It covers the essential concepts: manifest configuration, popup HTML and CSS, JavaScript logic, and browser extension architecture. These skills transfer directly to building any other type of Chrome extension you can imagine.
The calculator extension also presents monetization opportunities. You can offer a free version with basic features and a premium version with advanced scientific functions, unit conversions, or calculation history. Many successful Chrome extensions follow this freemium model, generating revenue while providing value to users.
Understanding Chrome Extension Architecture
Before we write any code, it is essential to understand how Chrome extensions are structured. A Chrome extension is essentially a collection of files that run in the Chrome browser and extend its functionality. These files work together to create the user experience.
At the heart of every Chrome extension is the manifest.json file. This JSON file tells Chrome everything it needs to know about your extension: its name, version, description, permissions required, and which files to load. In Manifest V3, the current standard, the manifest defines the extension’s capabilities and constraints.
Chrome extensions can have several types of components. Background scripts run in the background and handle events or long-running tasks. Content scripts interact with web pages you visit. Popup pages are what we will use for our calculator: a small HTML interface that appears when you click the extension icon in the toolbar.
For our calculator extension, we will use a popup-based architecture. This means our extension will have a popup.html file that defines the calculator interface, a popup.css file for styling, and a popup.js file for the calculator logic. We will also need a manifest.json file to configure the extension properly.
This popup architecture is perfect for calculator extensions because it provides an immediate, focused interface that disappears when you click away. Users get quick access to the calculator without any distractions or additional navigation.
Step 1: Create the Manifest File
Every Chrome extension begins with the manifest.json file. This file is the blueprint that Chrome uses to understand and load your extension. For our scientific calculator, we need to configure several important settings.
Create a new file called manifest.json in your project directory and add the following code:
{
"manifest_version": 3,
"name": "Scientific Calculator",
"version": "1.0",
"description": "A powerful scientific calculator that lives in your browser toolbar. Perform basic and advanced mathematical operations with ease.",
"permissions": [],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
This manifest file defines our extension with several key configurations. The manifest_version set to 3 indicates we are using Manifest V3, which is required for all new extensions and offers improved security and performance.
The action section defines what happens when users click our extension icon. We specify default_popup as popup.html, which means Chrome will display our calculator interface when the icon is clicked. We also define icons at multiple sizes for different contexts in the Chrome UI.
Notice that we do not require any permissions for this basic calculator. Because our extension only performs mathematical calculations locally and does not access any web pages or user data, we do not need to request special permissions. This makes our extension more secure and trustworthy from the user’s perspective.
Step 2: Build the Calculator Interface
Now we need to create the popup.html file that defines our calculator’s user interface. This HTML file will contain the display area where results appear and the button grid where users input numbers and operations.
Create a file called popup.html and add the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scientific Calculator</title>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<div class="calculator">
<div class="display-container">
<div id="expression" class="expression"></div>
<input type="text" id="display" class="display" readonly value="0">
</div>
<div class="buttons">
<div class="row">
<button class="btn function" data-action="sin">sin</button>
<button class="btn function" data-action="cos">cos</button>
<button class="btn function" data-action="tan">tan</button>
<button class="btn function" data-action="log">log</button>
<button class="btn function" data-action="ln">ln</button>
</div>
<div class="row">
<button class="btn function" data-action="sqrt">√</button>
<button class="btn function" data-action="pow">x²</button>
<button class="btn function" data-action="pi">π</button>
<button class="btn function" data-action="e">e</button>
<button class="btn operator" data-action="clear">AC</button>
</div>
<div class="row">
<button class="btn number" data-value="7">7</button>
<button class="btn number" data-value="8">8</button>
<button class="btn number" data-value="9">9</button>
<button class="btn operator" data-action="divide">÷</button>
<button class="btn operator" data-action="percent">%</button>
</div>
<div class="row">
<button class="btn number" data-value="4">4</button>
<button class="btn number" data-value="5">5</button>
<button class="btn number" data-value="6">6</button>
<button class="btn operator" data-action="multiply">×</button>
<button class="btn operator" data-action="backspace">⌫</button>
</div>
<div class="row">
<button class="btn number" data-value="1">1</button>
<button class="btn number" data-value="2">2</button>
<button class="btn number" data-value="3">3</button>
<button class="btn operator" data-action="subtract">−</button>
<button class="btn equals" data-action="calculate">=</button>
</div>
<div class="row">
<button class="btn number zero" data-value="0">0</button>
<button class="btn number" data-value=".">.</button>
<button class="btn operator" data-action="add">+</button>
<button class="btn operator" data-action="parenthesis">(</button>
<button class="btn operator" data-action="parenthesis">)</button>
</div>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>
This HTML structure creates a calculator with several distinct sections. The display container shows both the current expression being built and the main display showing the result or current input. The buttons are organized into rows, with different classes for numbers, operators, and functions.
We use data attributes extensively in our button elements. The data-value attribute stores numeric values, while data-action stores the operation each button should perform. This approach makes our JavaScript code clean and easy to maintain, as we can handle all button clicks through a unified event system.
The button layout includes scientific functions like sine, cosine, tangent, logarithm, and natural logarithm in the top rows. Below that are standard calculator buttons arranged in a familiar grid pattern. This layout provides quick access to both basic and advanced mathematical operations.
Step 3: Style Your Calculator
The visual design of your calculator extension significantly impacts user experience. A well-designed calculator feels intuitive and pleasant to use, while a poorly designed one frustrates users. Let us create a modern, professional-looking calculator with popup.css.
Create a file called popup.css and add the following styles:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
width: 320px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background-color: #1a1a2e;
padding: 16px;
}
.calculator {
background-color: #16213e;
border-radius: 16px;
padding: 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.display-container {
margin-bottom: 16px;
}
.expression {
color: #8b8b9a;
font-size: 14px;
min-height: 20px;
text-align: right;
padding: 4px 8px;
overflow-x: auto;
}
.display {
width: 100%;
background: transparent;
border: none;
color: #ffffff;
font-size: 36px;
text-align: right;
padding: 8px;
font-weight: 300;
}
.display:focus {
outline: none;
}
.buttons {
display: flex;
flex-direction: column;
gap: 8px;
}
.row {
display: flex;
gap: 8px;
justify-content: space-between;
}
.btn {
flex: 1;
height: 48px;
border: none;
border-radius: 12px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.btn.number {
background-color: #0f3460;
color: #ffffff;
}
.btn.number:hover {
background-color: #1a4a7a;
}
.btn.number:active {
background-color: #0a2540;
transform: scale(0.95);
}
.btn.operator {
background-color: #e94560;
color: #ffffff;
}
.btn.operator:hover {
background-color: #ff5a75;
}
.btn.operator:active {
background-color: #c93550;
transform: scale(0.95);
}
.btn.function {
background-color: #533483;
color: #ffffff;
font-size: 14px;
}
.btn.function:hover {
background-color: #6a44a8;
}
.btn.function:active {
background-color: #3d2463;
transform: scale(0.95);
}
.btn.equals {
background-color: #00d9ff;
color: #1a1a2e;
font-weight: 700;
}
.btn.equals:hover {
background-color: #33e1ff;
}
.btn.equals:active {
background-color: #00b8d9;
transform: scale(0.95);
}
.btn.zero {
flex: 2;
}
These styles create a modern dark theme calculator with several carefully designed elements. The color scheme uses deep blues and purples as the base, with vibrant accents for operators and the equals button. This visual hierarchy makes it immediately clear which buttons perform different actions.
The display area features a two-line design: the expression line shows the complete mathematical expression being built, while the main display shows the current input or result. This mirrors the display design of physical scientific calculators and helps users understand their calculations.
Button interactions include hover and active states that provide visual feedback. When users press a button, it slightly shrinks (transform: scale(0.95)), giving a tactile sensation similar to pressing a physical button. The operator buttons use a distinct red color, while function buttons use purple, and number buttons use blue, creating clear visual categories.
Step 4: Implement Calculator Logic
Now comes the most important part: making the calculator actually work. We will create popup.js to handle all the mathematical operations, button interactions, and display updates. This JavaScript file will implement a full scientific calculator with support for basic arithmetic, trigonometric functions, logarithms, and more.
Create a file called popup.js and add the following code:
class ScientificCalculator {
constructor() {
this.display = document.getElementById('display');
this.expression = document.getElementById('expression');
this.currentValue = '0';
this.expressionParts = [];
this.init();
}
init() {
document.querySelectorAll('.btn').forEach(button => {
button.addEventListener('click', (e) => this.handleButtonClick(e));
});
document.addEventListener('keydown', (e) => this.handleKeyboard(e));
}
handleButtonClick(e) {
const button = e.target;
const value = button.dataset.value;
const action = button.dataset.action;
if (value !== undefined) {
this.inputNumber(value);
} else if (action) {
this.handleAction(action);
}
}
handleKeyboard(e) {
const keyMap = {
'0': '0', '1': '1', '2': '2', '3': '3', '4': '4',
'5': '5', '6': '6', '7': '7', '8': '8', '9': '9',
'.': '.', '+': 'add', '-': 'subtract', '*': 'multiply',
'/': 'divide', '=': 'calculate', 'Enter': 'calculate',
'Escape': 'clear', 'Backspace': 'backspace'
};
if (keyMap[e.key]) {
if (e.key === 'Enter' || e.key === '=') {
this.handleAction('calculate');
} else if (keyMap[e.key]) {
if (['+', '-', '*', '/'].includes(e.key)) {
this.handleAction(keyMap[e.key]);
} else if (!isNaN(e.key) || e.key === '.') {
this.inputNumber(e.key);
} else if (e.key === 'Escape') {
this.handleAction('clear');
} else if (e.key === 'Backspace') {
this.handleAction('backspace');
}
}
}
}
inputNumber(num) {
if (this.currentValue === '0' && num !== '.') {
this.currentValue = num;
} else if (num === '.' && this.currentValue.includes('.')) {
return;
} else {
this.currentValue += num;
}
this.updateDisplay();
}
handleAction(action) {
switch (action) {
case 'clear':
this.clear();
break;
case 'backspace':
this.backspace();
break;
case 'add':
case 'subtract':
case 'multiply':
case 'divide':
case 'percent':
this.addOperator(action);
break;
case 'parenthesis':
this.addParenthesis();
break;
case 'calculate':
this.calculate();
break;
case 'sqrt':
case 'pow':
case 'sin':
case 'cos':
case 'tan':
case 'log':
case 'ln':
this.addFunction(action);
break;
case 'pi':
this.addConstant('π');
break;
case 'e':
this.addConstant('e');
break;
}
this.updateDisplay();
}
addOperator(operator) {
const operators = {
'add': '+',
'subtract': '−',
'multiply': '×',
'divide': '÷',
'percent': '%'
};
if (this.expressionParts.length === 0 && this.currentValue !== '0') {
this.expressionParts.push(this.currentValue);
}
if (this.expressionParts.length > 0) {
const lastPart = this.expressionParts[this.expressionParts.length - 1];
if (['+', '−', '×', '÷', '%'].includes(lastPart)) {
this.expressionParts[this.expressionParts.length - 1] = operators[operator];
this.updateExpression();
return;
}
}
this.expressionParts.push(operators[operator]);
this.currentValue = '0';
this.updateExpression();
}
addParenthesis() {
const openCount = this.expressionParts.filter(p => p === '(').length;
const closeCount = this.expressionParts.filter(p => p === ')').length;
if (openCount === closeCount || this.expressionParts.length === 0 ||
['+', '−', '×', '÷', '%', '('].includes(this.expressionParts[this.expressionParts.length - 1])) {
this.expressionParts.push('(');
} else {
this.expressionParts.push(')');
}
this.updateExpression();
}
addFunction(func) {
const functions = {
'sin': 'sin(',
'cos': 'cos(',
'tan': 'tan(',
'log': 'log(',
'ln': 'ln(',
'sqrt': '√(',
'pow': '^2'
};
if (func === 'pow') {
if (this.currentValue !== '0') {
this.expressionParts.push(this.currentValue);
}
this.expressionParts.push('^2');
this.currentValue = '0';
} else {
if (this.currentValue !== '0' && this.expressionParts.length > 0) {
this.expressionParts.push(this.currentValue);
}
this.expressionParts.push(functions[func]);
this.currentValue = '0';
}
this.updateExpression();
}
addConstant(constant) {
if (this.expressionParts.length === 0 ||
['+', '−', '×', '÷', '%', '('].includes(this.expressionParts[this.expressionParts.length - 1])) {
this.expressionParts.push(constant);
} else {
this.currentValue = constant;
}
this.updateExpression();
}
clear() {
this.currentValue = '0';
this.expressionParts = [];
this.updateDisplay();
this.updateExpression();
}
backspace() {
if (this.currentValue.length > 1) {
this.currentValue = this.currentValue.slice(0, -1);
} else {
this.currentValue = '0';
}
this.updateDisplay();
}
calculate() {
if (this.expressionParts.length === 0 && this.currentValue === '0') {
return;
}
let expression = [...this.expressionParts];
if (this.currentValue !== '0') {
expression.push(this.currentValue);
}
let expressionString = expression.join(' ');
expressionString = expressionString.replace(/×/g, '*');
expressionString = expressionString.replace(/÷/g, '/');
expressionString = expressionString.replace(/−/g, '-');
expressionString = expressionString.replace(/π/g, 'Math.PI');
expressionString = expressionString.replace(/e(?!\d)/g, 'Math.E');
expressionString = expressionString.replace(/sin\(/g, 'Math.sin(');
expressionString = expressionString.replace(/cos\(/g, 'Math.cos(');
expressionString = expressionString.replace(/tan\(/g, 'Math.tan(');
expressionString = expressionString.replace(/log\(/g, 'Math.log10(');
expressionString = expressionString.replace(/ln\(/g, 'Math.log(');
expressionString = expressionString.replace(/√\(/g, 'Math.sqrt(');
expressionString = expressionString.replace(/\^2/g, '**2');
try {
let result = eval(expressionString);
if (!isFinite(result) || isNaN(result)) {
this.currentValue = 'Error';
} else {
result = Math.round(result * 10000000000) / 10000000000;
this.currentValue = result.toString();
this.expressionParts = [];
}
} catch (error) {
this.currentValue = 'Error';
}
this.updateDisplay();
this.updateExpression();
}
updateDisplay() {
this.display.value = this.currentValue;
}
updateExpression() {
this.expression.textContent = this.expressionParts.join(' ') + (this.currentValue !== '0' ? ' ' + this.currentValue : '');
}
}
document.addEventListener('DOMContentLoaded', () => {
new ScientificCalculator();
});
This JavaScript implementation provides a comprehensive scientific calculator with multiple features. The class-based structure keeps the code organized and maintainable, with separate methods for handling different types of operations.
The calculator supports keyboard input in addition to button clicks, making it more convenient for users who prefer keyboard shortcuts. You can type numbers, operators, and use Enter to calculate, Escape to clear, and Backspace to delete.
The calculate method includes sophisticated expression parsing. It converts the visual representation (like × for multiplication) into JavaScript operators, replaces constants like π and e with their mathematical values, and converts function names to Math object methods. The eval function then evaluates the resulting expression safely.
Error handling is built in to prevent the calculator from crashing when users enter invalid expressions. If the result is not a number or is infinite, the calculator displays “Error” instead of breaking. The result is also rounded to avoid floating-point precision issues with very long decimal numbers.
Step 5: Create Extension Icons
Every Chrome extension needs icons to represent it in the browser toolbar and Chrome Web Store. You need to create three icon sizes: 16x16, 48x48, and 128x128 pixels. These icons should be PNG files placed in an icons folder.
For a calculator extension, design a simple icon that represents calculation, such as a calculator symbol or the plus sign. You can use any image editing software to create these icons, or use online tools to generate them from a design.
Create an icons folder in your project directory and add the three required PNG files. Name them icon16.png, icon48.png, and icon128.png respectively, matching the filenames specified in your manifest.json.
If you do not have custom icons, Chrome will use a default placeholder, but your extension will look more professional with properly sized icons that match your calculator’s design theme.
Step 6: Test Your Extension
Before publishing your extension, you need to test it locally to ensure everything works correctly. Chrome provides a simple way to load unpacked extensions for testing.
Open Chrome and navigate to chrome://extensions/ in your address bar. This page manages all your installed extensions. In the top right corner, toggle on “Developer mode” to enable extension development features.
Once Developer mode is enabled, you will see new buttons appear, including “Load unpacked”. Click this button and select your project folder. Chrome will load your calculator extension and display it in the extension list.
Now test your extension thoroughly. Click the extension icon in your browser toolbar to open the calculator popup. Try entering various calculations, including basic arithmetic, scientific functions, and complex expressions with parentheses. Verify that all buttons work correctly and that the results are accurate.
Test edge cases as well. Try dividing by zero, entering very large numbers, and using combinations of functions. Make sure error handling works correctly and does not crash the extension.
Step 7: Publish to Chrome Web Store
Once you have tested your extension and confirmed it works correctly, you can publish it to the Chrome Web Store to share with other users. The publishing process requires a Google account and a small one-time developer registration fee.
First, bundle your extension into a ZIP file. Make sure your manifest.json file is at the root of the ZIP, and include all necessary files: popup.html, popup.js, popup.css, and your icons folder. Do not include unnecessary files or folders.
Next, go to the Chrome Web Store Developer Dashboard and sign in with your Google account. Click “New Item” and upload your ZIP file. You will need to fill in details about your extension, including a title, description, and category.
The description you write should include relevant keywords like “chrome extension calculator”, “scientific calculator”, and “browser calculator” to help users find your extension through search. Add screenshots and a promotional image to make your listing more attractive.
After submitting, Google will review your extension. The review process typically takes a few hours to a few days. Once approved, your calculator extension will be available for Chrome users worldwide to install.
Conclusion
Congratulations! You have successfully built a complete scientific calculator Chrome extension from scratch. This project demonstrates the fundamental concepts of Chrome extension development and provides a useful tool that you can use daily.
The calculator extension you created includes basic arithmetic operations, scientific functions like sine, cosine, tangent, logarithms, and square root, keyboard support for faster input, error handling for invalid calculations, and a modern dark theme interface. These features make it a fully functional scientific calculator that rivals many standalone applications.
The skills you learned in this tutorial transfer directly to building other Chrome extensions. Whether you want to create a currency converter, unit converter, note-taking app, or any other browser tool, the architecture and patterns remain the same. You now understand manifest configuration, popup-based interfaces, JavaScript logic, and the Chrome extension submission process.
Consider enhancing your calculator extension with additional features like calculation history, memory functions, unit conversions, or a theme switcher. You could also explore monetization options by offering a premium version with advanced features. The possibilities are endless, and your calculator extension provides a solid foundation for future expansion.
Start using your calculator extension today by loading it in Chrome. Every time you need to make a quick calculation while browsing, you will appreciate the convenience of having a powerful scientific calculator right in your browser toolbar.