Home > Blog > Projetos Práticos
Projetos Práticos
CSS
Desenvolvimento Web
JavaScript
Programação

Calculadora HTML: Como Criar com CSS e JavaScript

Atualizado em: 14 de julho de 2026

uma calculadora, caneta e um livro de capa vermelha

Neste tutorial, você vai criar uma calculadora HTML completa usando três arquivos: index.html, style.css e script.js. O projeto realiza as quatro operações básicas, porcentagem, números decimais, limpeza, correção de dígitos e também aceita comandos pelo teclado.

A versão abaixo não usa eval(). Em vez de executar uma expressão como texto, o JavaScript mantém o número atual, o número anterior e o operador selecionado. Isso deixa o exemplo mais seguro e mais fácil de entender.

Resumo: o HTML cria o visor e os botões, o CSS organiza a interface com Grid e o JavaScript controla o estado da operação e calcula o resultado.

Teste a calculadora pronta

Clique nos botões abaixo. Para usar o teclado, clique uma vez dentro da calculadora e pressione números, operadores, Enter, Backspace ou Escape.

0

O que você vai praticar

  • estrutura semântica com HTML e atributos data-*;
  • layout responsivo com CSS Grid;
  • seleção de elementos com querySelector();
  • eventos de clique e teclado com addEventListener();
  • funções, condições, estado e conversão de números;
  • tratamento de divisão por zero e entradas decimais.

Crie os arquivos do projeto

Crie uma pasta chamada calculadora-html e adicione estes três arquivos dentro dela:

  • index.html
  • style.css
  • script.js

Abra o arquivo index.html no navegador depois de copiar os três códigos. Você também pode usar o Editor HTML do Código Fácil para testar pequenas alterações.

1. Código HTML da calculadora

O HTML cria o visor, agrupa os botões e usa atributos como data-numero, data-operador e data-acao. Esses atributos permitem que o JavaScript descubra o que cada botão deve fazer sem usar vários atributos onclick.

index.html

HTML
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Calculadora HTML</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="calculadora" data-calculadora tabindex="0">
    <div class="visor" aria-live="polite">
      <span class="historico" data-historico></span>
      <output class="resultado" data-visor>0</output>
    </div>

    <div class="teclado">
      <button type="button" data-acao="limpar">AC</button>
      <button type="button" data-acao="apagar">⌫</button>
      <button type="button" data-acao="porcentagem">%</button>
      <button type="button" class="operador" data-operador="/">÷</button>

      <button type="button" data-numero="7">7</button>
      <button type="button" data-numero="8">8</button>
      <button type="button" data-numero="9">9</button>
      <button type="button" class="operador" data-operador="*">×</button>

      <button type="button" data-numero="4">4</button>
      <button type="button" data-numero="5">5</button>
      <button type="button" data-numero="6">6</button>
      <button type="button" class="operador" data-operador="-">−</button>

      <button type="button" data-numero="1">1</button>
      <button type="button" data-numero="2">2</button>
      <button type="button" data-numero="3">3</button>
      <button type="button" class="operador" data-operador="+">+</button>

      <button type="button" class="zero" data-numero="0">0</button>
      <button type="button" data-acao="decimal">,</button>
      <button type="button" class="igual" data-acao="calcular">=</button>
    </div>
  </main>

  <script src="script.js"></script>
</body>
</html>

Partes importantes do HTML

  • output exibe o resultado e combina melhor com um valor calculado do que um campo editável;
  • aria-live="polite" ajuda leitores de tela a perceber atualizações no visor;
  • type="button" impede que os botões tentem enviar um formulário;
  • tabindex="0" permite focar a calculadora e usar os atalhos do teclado;
  • o CSS e o JavaScript são carregados por arquivos separados.

Para revisar os fundamentos, consulte também o que é HTML.

2. CSS para estilizar a calculadora

O CSS centraliza o projeto na página, cria o painel escuro e organiza os botões em quatro colunas com Grid. A propriedade width: min(100%, 340px) evita que a calculadora ultrapasse a largura disponível em telas pequenas.

style.css

CSS
* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  font-family: system-ui, sans-serif;
  background: #eef2f7;
}

.calculadora {
  width: min(100%, 340px);
  padding: 18px;
  border-radius: 20px;
  background: #161a22;
  box-shadow: 0 18px 45px rgba(0, 0, 0, 0.2);
}

.visor {
  min-height: 96px;
  margin-bottom: 14px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-end;
  overflow: hidden;
  border-radius: 14px;
  background: #f8fafc;
}

.historico {
  min-height: 24px;
  color: #64748b;
  font-size: 0.95rem;
}

.resultado {
  max-width: 100%;
  overflow: hidden;
  color: #0f172a;
  font-size: clamp(2rem, 8vw, 3rem);
  line-height: 1.1;
  text-overflow: ellipsis;
}

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

button {
  min-height: 58px;
  border: 0;
  border-radius: 14px;
  color: #0f172a;
  background: #e2e8f0;
  font: inherit;
  font-size: 1.15rem;
  font-weight: 700;
  cursor: pointer;
}

button:hover {
  filter: brightness(0.96);
}

button:focus-visible {
  outline: 3px solid #38bdf8;
  outline-offset: 2px;
}

.operador,
.igual {
  color: #ffffff;
  background: #2563eb;
}

.zero {
  grid-column: span 2;
}

Como o CSS Grid organiza os botões

A regra grid-template-columns: repeat(4, 1fr) cria quatro colunas do mesmo tamanho. O botão zero recebe grid-column: span 2, por isso ocupa o espaço de duas colunas.

O estilo de foco com :focus-visible também melhora a navegação por teclado. Veja mais exemplos em o que é CSS e em botões personalizados com CSS.

3. JavaScript da calculadora

O JavaScript guarda quatro informações principais: o valor atual, o valor anterior, o operador escolhido e se o próximo número deve iniciar uma nova entrada.

script.js

JavaScript
const calculadora = document.querySelector("[data-calculadora]");
const visor = calculadora.querySelector("[data-visor]");
const historico = calculadora.querySelector("[data-historico]");

let valorAtual = "0";
let valorAnterior = "";
let operador = null;
let aguardandoNovoNumero = false;

function atualizarVisor() {
  visor.textContent = valorAtual;
  historico.textContent =
    operador && valorAnterior
      ? `${valorAnterior} ${simboloDoOperador(operador)}`
      : "";
}

function simboloDoOperador(valor) {
  return { "/": "÷", "*": "×", "-": "", "+": "+" }[valor] ?? valor;
}

function numeroParaCalculo(valor) {
  return Number(valor.replace(",", "."));
}

function numeroParaVisor(valor) {
  if (!Number.isFinite(valor)) {
    return "Erro";
  }

  return String(Number(valor.toFixed(10))).replace(".", ",");
}

function inserirNumero(numero) {
  if (valorAtual === "Erro" || aguardandoNovoNumero) {
    valorAtual = numero;
    aguardandoNovoNumero = false;
  } else {
    valorAtual = valorAtual === "0" ? numero : valorAtual + numero;
  }

  atualizarVisor();
}

function inserirDecimal() {
  if (valorAtual === "Erro" || aguardandoNovoNumero) {
    valorAtual = "0,";
    aguardandoNovoNumero = false;
  } else if (!valorAtual.includes(",")) {
    valorAtual += ",";
  }

  atualizarVisor();
}

function escolherOperador(novoOperador) {
  if (valorAtual === "Erro") {
    limpar();
    return;
  }

  if (operador && !aguardandoNovoNumero) {
    calcular();
  }

  valorAnterior = valorAtual;
  operador = novoOperador;
  aguardandoNovoNumero = true;
  atualizarVisor();
}

function calcular() {
  if (!operador || aguardandoNovoNumero || valorAtual === "Erro") {
    return;
  }

  const primeiro = numeroParaCalculo(valorAnterior);
  const segundo = numeroParaCalculo(valorAtual);
  let resultado;

  switch (operador) {
    case "+":
      resultado = primeiro + segundo;
      break;
    case "-":
      resultado = primeiro - segundo;
      break;
    case "*":
      resultado = primeiro * segundo;
      break;
    case "/":
      resultado = segundo === 0 ? NaN : primeiro / segundo;
      break;
    default:
      return;
  }

  valorAtual = numeroParaVisor(resultado);
  valorAnterior = "";
  operador = null;
  aguardandoNovoNumero = true;
  atualizarVisor();
}

function porcentagem() {
  if (valorAtual === "Erro") {
    return;
  }

  valorAtual = numeroParaVisor(numeroParaCalculo(valorAtual) / 100);
  atualizarVisor();
}

function apagar() {
  if (valorAtual === "Erro" || aguardandoNovoNumero) {
    return;
  }

  valorAtual = valorAtual.length > 1 ? valorAtual.slice(0, -1) : "0";
  atualizarVisor();
}

function limpar() {
  valorAtual = "0";
  valorAnterior = "";
  operador = null;
  aguardandoNovoNumero = false;
  atualizarVisor();
}

calculadora.addEventListener("click", (evento) => {
  const botao = evento.target.closest("button");

  if (!botao) {
    return;
  }

  if (botao.dataset.numero) inserirNumero(botao.dataset.numero);
  if (botao.dataset.operador) escolherOperador(botao.dataset.operador);
  if (botao.dataset.acao === "decimal") inserirDecimal();
  if (botao.dataset.acao === "calcular") calcular();
  if (botao.dataset.acao === "porcentagem") porcentagem();
  if (botao.dataset.acao === "apagar") apagar();
  if (botao.dataset.acao === "limpar") limpar();
});

calculadora.addEventListener("keydown", (evento) => {
  const tecla = evento.key;

  if (/^[0-9]$/.test(tecla)) inserirNumero(tecla);
  else if (["+", "-", "*", "/"].includes(tecla)) escolherOperador(tecla);
  else if (tecla === "," || tecla === ".") inserirDecimal();
  else if (tecla === "Enter" || tecla === "=") calcular();
  else if (tecla === "Backspace") apagar();
  else if (tecla === "Escape") limpar();
  else return;

  evento.preventDefault();
});

atualizarVisor();

Como o cálculo funciona

  • inserirNumero() adiciona dígitos ao visor;
  • inserirDecimal() impede duas vírgulas no mesmo número;
  • escolherOperador() guarda o primeiro número e a operação;
  • calcular() executa soma, subtração, multiplicação ou divisão;
  • numeroParaVisor() limita erros de ponto flutuante e troca ponto por vírgula;
  • porcentagem() divide o valor atual por 100;
  • limpar() restaura todo o estado da calculadora.

A divisão por zero retorna Erro. O código também verifica se o resultado é um número finito antes de mostrá-lo. Para entender melhor os conceitos usados, veja o que é JavaScript.

Atalhos do teclado

TeclaAção
0 a 9Insere números
+ – * /Seleciona a operação
, ou .Insere decimal
Enter ou =Calcula o resultado
BackspaceApaga o último dígito
EscapeLimpa a calculadora

Os eventos de teclado ficam presos ao elemento da calculadora. Assim, os atalhos só são executados quando ela está em foco e não interferem no restante da página.

Por que evitar eval() neste projeto?

A função eval() executa uma string como código JavaScript. Em um exemplo totalmente controlado ela pode parecer conveniente, mas se a entrada puder ser manipulada, o risco aumenta. Além disso, usar funções específicas para cada operação deixa o fluxo mais claro para quem está aprendendo.

Nesta versão, apenas números e operadores conhecidos entram no cálculo. Nenhum texto é executado como código.

Erros comuns e como corrigir

A calculadora aparece sem estilo

Confirme se o arquivo se chama exatamente style.css e está na mesma pasta do index.html. Verifique também o atributo href="style.css".

Os botões não fazem nada

Confira se o arquivo script.js está na mesma pasta e se a linha <script src="script.js"></script> foi colocada antes do fechamento de body.

O separador decimal não funciona

A interface usa vírgula, mas o JavaScript converte o valor para ponto antes de usar Number(). Não remova as conversões feitas em numeroParaCalculo() e numeroParaVisor().

Aparece Erro ao dividir

O resultado Erro é esperado quando o segundo número de uma divisão é zero. Pressione AC ou Escape para começar uma nova operação.

Ideias para evoluir o projeto

  • adicionar memória com botões M+, M- e MR;
  • criar um histórico das últimas operações;
  • incluir tema claro e tema escuro;
  • aceitar parênteses e expressões maiores usando um parser próprio;
  • transformar o projeto em uma calculadora científica;
  • salvar o histórico com localStorage;
  • adicionar testes automatizados para as funções de cálculo.

Perguntas frequentes

É possível criar uma calculadora apenas com HTML?

O HTML consegue montar o visor e os botões, mas não executa os cálculos. Para uma calculadora funcional, você precisa de JavaScript ou de outra linguagem que processe as operações.

Posso colocar HTML, CSS e JavaScript em um único arquivo?

Sim. O CSS pode ficar dentro de uma tag style e o JavaScript dentro de uma tag script. Separar os arquivos, porém, facilita a organização e a manutenção.

Esta calculadora funciona no celular?

Sim. A largura é responsiva e os botões são organizados com CSS Grid. O tamanho máximo de 340 pixels mantém a interface compacta em telas maiores.

A calculadora aceita números negativos?

Ela calcula resultados negativos e permite subtração. Para começar diretamente com um número negativo, seria necessário adicionar uma regra específica para o sinal unário.

Por que o resultado é arredondado?

O método toFixed(10) reduz efeitos comuns da representação de números decimais em ponto flutuante. Depois, Number() remove zeros desnecessários no final.

Conclusão

Você criou uma calculadora HTML funcional com CSS e JavaScript, sem depender de bibliotecas e sem executar expressões com eval(). O projeto já inclui operações básicas, porcentagem, decimais, teclado, acessibilidade e tratamento de divisão por zero.

Depois de testar o código, explore outros projetos práticos de programação e continue aprimorando a interface e a lógica.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita