CSS math isn’t nearly how issues look! It can be used to work out helpful numeric data. As an illustration, you could possibly calculate and present the share of duties accomplished in a to-do record with CSS, serving to customers maintain observe of their progress. No want for script or server computation. No latency. No use of extra browser sources.
Working with math has change into a lot easier and extra versatile. I’m going to offer you an instance utilizing CSS to calculate and show a reduced value everytime you want it, utilizing the bottom value and {discount} supplied. It’s the type of factor you see usually on e-commerce websites the place heavy JavaScript is used to indicate a product’s full value, its {discount} quantity, and its sale value.

We are able to completely do this in CSS:
It does depend on some bleeding-edge options which can be ready to achieve extra browser help, however I believe it’s nonetheless an excellent train to dig into how we’ll finally have the ability to put this stuff in follow and finally use them in our on a regular basis work.
Right here’s how I put it collectively.
The preliminary markup
The interface on this particular demo shows an inventory of streaming providers for the person to select from — Netflix, Disney+, HBO, HBO Now, HBO Go, HBO Max, and so on. There’s a scholar {discount} provide on every subscription that takes a sure proportion quantity off the complete value.
The bottom value and {discount} are included as data-* attributes within the ingredient displaying the worth. Simply bear in mind, the {discount} solely kicks in when you choose “Apply Scholar Low cost,” and you then’ll see how a lot the worth is after the {discount} is utilized.
Calculating the worth minimize
When the {discount} kicks in, step one is to slash the bottom value with a line throughout it.
/* When the {discount} toggle is checked contained in the .ott container */
.ott:has(.is-ott-discounted:checked) {
/* Strike by way of the unique value */
.ott-price {
text-decoration: line-through;
}
}
Subsequent, let’s work out the brand new discounted value utilizing the data-price and data-discount values.
.ott:has(.is-ott-discounted:checked) {
.ott-price {
text-decoration: line-through;
/*
Calculate the brand new value from the data-* attributes:
Authentic Worth * (1 - Low cost Utilized)
*/
--n: calc(attr(data-price quantity) * (1 - attr(data-discount quantity)));
}
}
The attr( syntax is comparatively new. The operate used to solely work with the content material property, however now helps any CSS property… and parses values into a spread of information varieties, whereas earlier than they have been all the time parsed as strings.
These arguments:
: That is the identify of the HTML attribute we need to have a look at (likehref,data-count, ortitle).: This tells CSS find out how to “learn” the worth (like acoloration, aquantity, or asize). It’s the newer superpower that makes the work we’re doing right here potential.
In our case, we’re utilizing the operate to parse each data-price and data-discount into numbers, after which we subtract the {discount} from the worth with CSS math-iness.
The upgraded attr() is tremendous cool, however not Baseline as I’m scripting this, so regulate it.
Displaying the discounted value
Right here’s how we show the up to date value as soon as the {discount} is utilized:
.ott:has(.is-ott-discounted:checked) {
.ott-price {
text-decoration: line-through;
--n: calc(attr(data-price quantity) * (1 - attr(data-discount quantity)));
&::after {
show: inline-block;
/* Splits the variable --n into two counters:
'a' for the entire quantity (in {dollars}) and 'b' for the decimals (in cents) */
counter-set: a calc(spherical(down, var(--n))) b calc((mod(var(--n), 1)) * 100);
/* Output: two areas (2000), a greenback signal ($), the quantity, a dot, and the decimals */
content material: "20002000$" counter(a) "." counter(b, decimal-leading-zero);
}
}
}
The counter() operate helps us flip the numeric worth of the --n varable right into a content material string. Since CSS counters can’t deal with decimals (they spherical the worth by default), we deal with the numbers earlier than and after the decimal as separate counters after which mix them as strings, including a dot between them.
calc(spherical(down, var(--n)))takes the variable--nand rounds it right down to get the entire greenback quantity (saved ascounter(a)).calc((mod(var(--n), 1)) * 100)makes use of the modulomod()operate to isolate the fraction, then multiplies it by100to get the cents (saved ascounter(b)).- The
content materialproperty inserts a greenback signal earlier than the 2 counters after which joins them with a dot.
We all know that calc() has loads of browser help. And guess what? The mod() operate is newly Baseline!
That’s provided that you want decimals and all that. In case you’re rounding costs, this may be lots sufficient:
counter-set: value calc(var(--n));
content material: counter(value);
Right here’s the demo as soon as once more:
Wrapping up
So, there now we have it, a working mixture of newer CSS options (the upgraded attr() operate), CSS math features (mod(), spherical()), and customized counters to nail down one thing that we see in so many web sites, solely with out scripts. When attr()‘s help for information varieties turns into a factor in all browsers, that is one thing you need to use in your on a regular basis work.









