(85) 99645-7140 nelclassico@gmail.com Praça Coronel Melquiades, 124
Tecnologia

Calculando e exibindo preços com desconto em CSS

A matemática CSS não se trata apenas da aparência das coisas! Também pode ser usado para descobrir informações numéricas úteis. Por exemplo, você pode calcular e mostrar a porcentagem de tarefas concluídas em uma lista de tarefas com CSS, ajudando os usuários a acompanhar seu progresso. Não há necessidade de script ou computação de servidor. Sem latência. Não há uso de recursos adicionais do navegador.

Trabalhar com matemática ficou muito mais simples e flexível. Vou dar um exemplo usando CSS para calcular e exibir um preço com desconto sempre que você precisar, usando o preço base e o desconto fornecido. É o tipo de coisa que você vê com frequência em sites de comércio eletrônico, onde JavaScript pesado é usado para mostrar o preço total de um produto, o valor do desconto e o preço de venda.

A four column row of product cards showing sale clothing from Gap. Model photos are on top, followed by the product name, price, and sale price.
Captura de tela retirada de gap.com

Podemos fazer isso com certeza em CSS:

CodePen Incorporar Fallback

Ele depende de alguns recursos de ponta que estão esperando para obter mais suporte do navegador, mas acho que ainda é um bom exercício para descobrir como seremos capazes de colocar essas coisas em prática e, eventualmente, usá-las em nosso trabalho diário.

Veja como eu montei tudo.

A marcação inicial

A interface nesta demonstração específica exibe uma lista de serviços de streaming para o usuário escolher – Netflix, Disney+, HBO , HBO Now , HBO Go , HBO Max, etc. Há uma oferta de desconto para estudantes em cada assinatura que retira uma determinada porcentagem do preço total.

<li>
  <!-- Service name, base price, and selection toggle -->
  <label>
    <span>Netflix</span>
    <!-- data-price and data-discount store base price and discount offered -->
    <div class="ott-price" data-price="7.99" data-discount="0.2">$7.99</div>
    <!-- Checkbox to track if the user wants to add this service -->
    <input type="checkbox" class="is-ott-selected">
  </label>

  <!-- Toggle for the student discount -->
  <label>
    <span>Apply Student Discount <br> 20%</span>
    <input type="checkbox" class="is-ott-discounted">
  </label>
</li>

<!-- etc. -->

O preço base e o desconto são incluídos como atributos <li>
<!-- Service name, base price, and selection toggle -->
<label>
<span>Netflix</span>
<!-- data-price and data-discount store base price and discount offered -->
<div class="ott-price" data-price="7.99" data-discount="0.2">$7.99</div>
<!-- Checkbox to track if the user wants to add this service -->
<input type="checkbox" class="is-ott-selected">
</label>

<!-- Toggle for the student discount -->
<label>
<span>Apply Student Discount <br> 20%</span>
<input type="checkbox" class="is-ott-discounted">
</label>
</li>

<!-- etc. --> no elemento que exibe o preço. Lembre-se de que o desconto só entra em vigor quando você seleciona “Aplicar desconto para estudante” e então você verá quanto é o preço após a aplicação do desconto.

Calculando a redução de preço

Quando o desconto entra em vigor, o primeiro passo é reduzir o preço base com uma linha atravessada.

/* When the discount toggle is checked inside the .ott container */
.ott:has(.is-ott-discounted:checked) {
  /* Strike through the original price */
  .ott-price {
    text-decoration: line-through;
  }
}

A seguir, vamos descobrir o novo preço com desconto usando os valores data-* e /* When the discount toggle is checked inside the .ott container */
.ott:has(.is-ott-discounted:checked) {
/* Strike through the original price */
.ott-price {
text-decoration: line-through;
}
}
.

.ott:has(.is-ott-discounted:checked) {
  .ott-price {
    text-decoration: line-through;
    /* 
        Calculate the new price from the data-* attributes:
        Original Price * (1 - Discount Applied)
    */
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));
  }
}

A data-price sintaxe é relativamente nova. A função costumava funcionar apenas com a propriedade data-discount, mas agora suporta qualquer propriedade CSS… e analisa valores em uma variedade de tipos de dados, enquanto antes eles eram sempre analisados ​​como strings.

Esses argumentos:

  1. .ott:has(.is-ott-discounted:checked) {
    .ott-price {
    text-decoration: line-through;
    /*
    Calculate the new price from the data-* attributes:
    Original Price * (1 - Discount Applied)
    */
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));
    }
    }
    :
    Este é o nome do atributo HTML que queremos ver (como attr(<name> <type>), content, ou <name>).
  2. href: Isso diz ao CSS como “ler” o valor (como um data-count, um title ou um <type>). É a nova superpotência que torna possível o trabalho que estamos fazendo aqui.

Em nosso caso, estamos usando a função para analisar data-* e /* When the discount toggle is checked inside the .ott container */
.ott:has(.is-ott-discounted:checked) {
/* Strike through the original price */
.ott-price {
text-decoration: line-through;
}
}
em length, e então subtraímos o desconto do preço com matemática CSS.

O data-price atualizado é super legal, mas não é a linha de base enquanto escrevo isso, então fique de olho nele.

Mostrando o preço com desconto

Veja como exibimos o preço atualizado assim que o desconto for aplicado:

.ott:has(.is-ott-discounted:checked) {
  .ott-price {
    text-decoration: line-through;
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));

    &::after {
      display: inline-block;
      /* Splits the variable --n into two counters: 
          'a' for the whole number (in dollars) and 'b' for the decimals (in cents) */
      counter-set: a calc(round(down, var(--n))) b calc((mod(var(--n), 1)) * 100);
      /* Output: two spaces (2000), a dollar sign ($), the number, a dot, and the decimals */
      content: "20002000$" counter(a) "." counter(b, decimal-leading-zero);
    }
  }
}

A função data-discount nos ajuda a transformar o valor numérico do numbers variável em uma data-discount string. Como os contadores CSS não podem lidar com decimais (eles arredondam o valor por padrão), tratamos os números antes e depois do decimal como contadores separados e depois os combinamos como strings, adicionando um ponto entre eles.

  1. .ott:has(.is-ott-discounted:checked) {
    .ott-price {
    text-decoration: line-through;
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));

    &::after {
    display: inline-block;
    /* Splits the variable --n into two counters:
    'a' for the whole number (in dollars) and 'b' for the decimals (in cents) */
    counter-set: a calc(round(down, var(--n))) b calc((mod(var(--n), 1)) * 100);
    /* Output: two spaces (2000), a dollar sign ($), the number, a dot, and the decimals */
    content: "20002000$" counter(a) "." counter(b, decimal-leading-zero);
    }
    }
    }
    pega a variável numbers e arredonda reduza-o para obter o valor total em dólares (armazenado como --n).

  2. content usa o módulo calc(round(down, var(--n))) função para isolar a fração e, em seguida, multiplica-a por --n para obter os centavos (armazenados como counter(a)).
  3. A propriedade data-discount insere um cifrão antes dos dois contadores e depois os une com um ponto.

Sabemos que mod() tem bastante suporte para navegador. E adivinhe? A função calc(round(down, var(--n))) é nova linha de base!

Isso só se você precisar de decimais e tudo mais. Se você estiver arredondando os preços, isso seria suficiente:

counter-set: price calc(var(--n));
content: counter(price);

Aqui está a demonstração mais uma vez:

CodePen Incorporar Fallback

Concluindo

Então, aí está, uma combinação funcional de recursos CSS mais recentes (a função data-price atualizada), funções matemáticas CSS (calc(round(down, var(--n))), calc()) e contadores personalizados para definir algo que vemos em tantos sites, só que sem scripts. Quando o suporte de data-price para tipos de dados se tornar uma coisa em todos os navegadores, isso é algo que você pode usar em seu trabalho diário.


Calculando e exibindo preços com desconto em CSS originalmente escrito à mão e publicado com amor em CSS-Tricks . Você realmente deveria receber o boletim informativo também.

Deixe um comentário

Seu email não será publicado. Campos obrigatórios marcados com *

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.