Calcular y mostrar precios con descuento en CSS
¡Las matemáticas CSS no se tratan solo de cómo se ven las cosas! También se puede utilizar para calcular información numérica útil. Por ejemplo, puede utilizar CSS para calcular y mostrar el porcentaje de tareas completadas en una lista de tareas pendientes, lo que ayuda a los usuarios a realizar un seguimiento de su progreso. No se requieren scripts ni cálculos del servidor. Sin retraso. No se utilizan recursos adicionales del navegador.
El trabajo matemático se vuelve más fácil y flexible. Le daré un ejemplo usando CSS para calcular y mostrar el precio con descuento cuando lo necesite, utilizando el precio base y el descuento proporcionados. Esto es algo que se ve a menudo en los sitios web de comercio electrónico, donde se utiliza mucho JavaScript para mostrar el precio total, el monto del descuento y el precio de venta de un producto.

Definitivamente podemos hacer esto en CSS:
Se basa en algunas características de vanguardia que están esperando una mayor compatibilidad con el navegador, pero creo que sigue siendo un buen ejercicio profundizar en cómo terminamos poniendo estas cosas en práctica y usándolas en nuestro trabajo diario.
Así es como lo armé.
marca inicial
La interfaz de esta demostración en particular muestra una lista de servicios de transmisión disponibles para el usuario: Netflix, Disney+, HBO, HBO ahora, HBO IrHBO Max, etc. Cada suscripción viene con un descuento para estudiantes, que le brinda un porcentaje del precio 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. -->
Precio base y descuento incluidos. data-* Atributo en el elemento que muestra el precio. Recuerde, el descuento solo entra en vigor si selecciona “Aplicar descuento para estudiantes” y luego verá cuál es el precio con descuento para la aplicación.
Calcular la reducción de precio
Cuando comienza un descuento, el primer paso es recortar el precio base con una línea horizontal.
/* 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 continuación, usemos la siguiente fórmula para calcular el nuevo precio con descuento: data-price y data-discount valores.
.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 attr(<name> <type>) sintaxis Es relativamente nuevo. Esta función solía funcionar sólo con content properties, pero ahora admite cualquier propiedad CSS… y analiza el valor en una secuencia de tipos de datos, mientras que antes siempre se analizaban en cadenas.
Estos argumentos:
<name>: Este es el nombre del atributo HTML que queremos ver (p. ej.href,data-countotitle).<type>: Esto le dice a CSS cómo “leer” el valor (comocolorunonumbero unlength). Son los nuevos superpoderes los que hacen posible el trabajo que hacemos aquí.
En nuestro caso usamos esta función para analizar ambos data-price y data-discount Ingresar numbersy luego usamos CSS para restar matemáticamente el descuento del precio.
actualizado attr() Muy bueno, pero no es Baseline mientras escribo esto, así que mantente atento.
Mostrar precio con descuento
Así es como mostramos los precios actualizados después de que se descuenta una aplicación:
.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: "\2000\2000$" counter(a) "." counter(b, decimal-leading-zero);
}
}
}
este counter() Función Ayúdanos a convertir valores numéricos a --n La variable se convierte content Cadena. Dado que los contadores CSS no pueden manejar decimales (redondean los valores de forma predeterminada), tratamos los números antes y después del decimal como contadores separados, luego los combinamos en una cadena y agregamos un punto entre ellos.
calc(round(down, var(--n)))Obtener variables--ny lo redondea hacia abajo para obtener el monto total en dólares (almacenado comocounter(a)).calc((mod(var(--n), 1)) * 100)utilizar módulomod()Función separa una fracción y luego la multiplica por100obtener centavos (almacenados comocounter(b)).- este
contentLa propiedad inserta un signo de dólar antes de los dos contadores y luego los conecta con un punto.
sabemos calc() Hay suficiente soporte para navegadores. ¿Adivina qué? este mod() ¡Las funciones son la nueva base!
Esto sólo es cierto si necesitas decimales, etc. Si redondeas los precios, esto es suficiente:
counter-set: price calc(var(--n));
content: counter(price);
Aquí está la demostración:
Resumir
Entonces, tenemos una combinación funcional de nuevas características CSS (actualizadas attr() función), función matemática CSS (mod(), round()) y contadores personalizados para determinar lo que vemos en muchos sitios, pero sin secuencias de comandos. cuando attr()La compatibilidad con tipos de datos se convierte en algo común en todos los navegadores, algo que puede utilizar en su trabajo diario.