A gente está acostumado a usar JavaScript para qualquer cálculo no front-end. Mas o CSS moderno está ficando poderoso demais! Com a evolução da função attr() e a chegada de funções matemáticas como calc(), mod() e round(), dá pra fazer coisas complexas direto no estilo. Vamos ver como calcular e mostrar um preço com desconto em um site de e-commerce, tudo isso sem script!

Developer inspecting CSS code in browser devtools to calculate discounted prices Software Concept Art

O HTML Inicial: Preparando o Terreno

Vamos criar um painel de preços de assinatura para um serviço de streaming. A estrutura usa atributos data-* para guardar o preço base e a porcentagem de desconto. Isso mantém o HTML limpo e os dados prontos para nossa lógica em CSS.

<div class="ott">
  <input type="checkbox" id="desconto" class="is-ott-discounted">
  <label for="desconto">Aplicar Desconto de Estudante</label>

  <div class="ott-card">
    <h3>Netflix</h3>
    <p class="ott-price" data-price="7.99" data-discount="0.20">$7.99</p>
  </div>
</div>

Calculando o Desconto: O Poder de attr() e calc()

Quando o usuário marca o desconto, a gente usa o seletor :has() para detectar a mudança e aplicar os cálculos. O segredo é a função attr() atualizada, que agora consegue interpretar valores como number.

/* Quando o toggle de desconto está marcado dentro do container .ott */
.ott:has(.is-ott-discounted:checked) {
  /* Risca o preço original */
  .ott-price {
    text-decoration: line-through;

    /*
      Calcula o novo preço com os atributos data-*:
      Preço Original * (1 - Desconto Aplicado)
    */
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));
  }
}

Nesse trecho, attr(data-price number) extrai o valor 7.99 como número, e attr(data-discount number) extrai 0.20. A função calc() faz a conta do preço com desconto. O resultado fica na variável --n.

E-commerce product card layout displaying original and discounted prices computed with CSS Algorithm Concept Visual

Exibindo o Resultado: Separando Números com mod() e round()

Os contadores do CSS não lidam bem com decimais. Para mostrar o preço certinho (ex: $6.39), a gente separa a parte inteira da decimal. É aqui que as funções mod() e round() brilham.

.ott:has(.is-ott-discounted:checked) {
  .ott-price {
    /* ... estilos anteriores ... */
    &::after {
      display: inline-block;

      /*
        Divide a variável --n em dois contadores:
        'a' para a parte inteira (em dólares) e 'b' para os centavos
      */
      counter-set: a calc(round(down, var(--n))) b calc((mod(var(--n), 1)) * 100);

      /* Saída: dois espaços (\2000), um cifrão ($), o número, um ponto e os centavos */
      content: "\2000\2000
quot; counter(a) "." counter(b, decimal-leading-zero); } } }

Aqui, round(down, var(--n)) nos dá a parte inteira (ex: 6), e mod(var(--n), 1) isola a parte fracionária, que multiplicamos por 100 para achar os centavos (ex: 39). A propriedade content monta a string final com o cifrão e a vírgula.

Laptop showing a streaming service subscription page with student discount applied via CSS Development Concept Image

Limitações e Pontos de Atenção

Apesar de ser uma demonstração incrível do poder do CSS moderno, precisamos ficar de olho nas limitações.

  • Suporte dos Browsers: A função attr() atualizada ainda não tem suporte amplo (não é Baseline). As funções mod() e round() são bem recentes. Sempre confira no caniuse.com os dados de suporte.
  • Acessibilidade: Os leitores de tela podem não interpretar o texto gerado pela propriedade content da mesma forma que o HTML real. Use essa técnica quando o resultado visual for o principal e mantenha o preço original no DOM para contexto.
  • Complexidade: Para lógicas de preço complexas (ex: descontos em cascata, cálculos de imposto), o JavaScript continua sendo a solução mais escalável e fácil de manter. Essa abordagem com CSS é ideal para cálculos simples e estáticos.

Próximos Passos para Aprender

Para aprofundar no que você aprendeu, explore:

  1. CSS Typed OM: O CSS Typed Object Model é a API que torna possível o novo comportamento da attr(). Entender isso vai te ajudar a compreender melhor como os valores CSS funcionam.
  2. Container Queries: Combine essas funções matemáticas com container queries para criar componentes verdadeiramente responsivos.
  3. Experimentação: Tente construir outros elementos, como uma barra de progresso que usa mod() para criar um efeito listrado ou um sistema de avaliação dinâmico que usa round().
Este conteúdo foi elaborado com o auxílio de ferramentas de IA, com base em fontes confiáveis, e revisado pela nossa equipe editorial antes da publicação. Não substitui o aconselhamento de um profissional especializado.