The New CSS Math: round()

CSS added many new Math functions to supplement the old favorites (such as calc()). They all ultimately represent a numeric value, but the nuance in how they work is not always clear from the start. As of October 2023, these are available in the latest Safari and Firefox. They are also available in Edge/Chrome behind the Experimental Web Platform feature flag.

The basics of CSS round() 

In JavaScript we have Math.round() which takes one numeric parameter, and the result will be the nearest integer. So 1.4 rounds down to 1 because it is closer to 1 than 2. Similarly, 3.9 rounds up to 4 since that is the nearest integer.

console.log(Math.round(2.2)); // 2
console.log(Math.round(14.82)); // 15
console.log(Math.round(5.5)); // 6

With CSS, round() behaves similarly by default, except it takes two parameters. The first is the value you want to round, and the second is the precision number.

When you are thinking general math or JavaScript, the precision number would be 1 because we are always looking at integers, and we are expecting our answer to be a multiple of 1. For CSS to have the straight equivalent of JavaScript’s Math.round(), we’d say round(3.9, 1).

line-height: round(2.2, 1); /* 2 */
line-height: round(14.82, 1); /* 15 */
line-height: round(5.5, 1); /* 6 */

But... why do I need two parameters?

Since we are working with a variety of CSS units with various scales, the specification allows us to work in a manner that is most appropriate for our need.

Keeping it unitless for a bit longer, think about opacity. Its reasonable range is from 0 to 1. Rounding here to an integer would always lead to a zero or one. This may be what you want, but maybe you want it with a different interval like the tenths place, such that your opacity is always one of 11 values: 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. CSS rounding allows this, and you can specify it with precision of 0.1. So instead of counting up by one, you count up by one tenth.

opacity: round(.56, 0.1); /* 0.6 */
opacity: round(.54, 0.1); /* 0.5 */

We follow the same logic when considering units. Perhaps I want to always rotate an object at intervals of 45 degrees. I can set 45deg as my precision unit to make sure my rotation is always a multiple of 45 degrees.

rotate: round(20deg, 45deg); /* 0deg */
rotate: round(30deg, 45deg); /* 45deg */
rotate: round(80deg, 45deg); /* 90deg */

You can even mix units if they are of the same syntax. Other angle options exist beyond deg such as turn and rad, so we can use any of these in our function.

rotate: round(20deg, .125turn); /* 0deg */
rotate: round(80deg, .125turn); /* 90deg */

But what if I really want more than two parameters? 

CSS round() takes a third (optional) parameter at the start which allows you to specify a rounding strategy. The earlier examples are all using the default value of nearest. If you want this strategy, you can either leave out the strategy parameter or specify nearest explicitly.

/* the following two both use the nearest strategy */
rotate: round(22.8deg, 1deg); /* 23deg */
rotate: round(nearest, 22.8deg, 1deg); /* 23deg */

If we instead want to always round up, we add a starting parameter to specify our rounding strategy as up. This will be similar to JavaScript’s Math.ceil().

font-size: round(up, 20.01rem, 1rem); /* 21rem */
rotate: round(up, 83deg, 5deg); /* 85deg */
rotate: round(up, -83deg, 5deg); /* -80deg */

Similary, we can round down by specifying round(down, ...), just as JavaScript allows with Math.floor().

font-size: round(down, 20.999rem, 1rem); /* 20rem */
rotate: round(down, 83deg, 5deg); /* 80deg */
rotate: round(down, -83deg, 5deg); /* -85deg */

Finally, there is the round(to-zero, ...) strategy. This one behaves similar to down when working with positive numbers, but behaves as up for negative numbers. It will select the interval number that is closest to zero.

rotate: round(to-zero, 83deg, 5deg); /* 80deg */
rotate: round(to-zero, -83deg, 5deg); /* -80deg */

rotate: round(down, 83deg, 5deg); /* 80deg */
rotate: round(down, -83deg, 5deg); /* 85deg */
rotate: round(up, -83deg, 5deg); /* 80deg */

See the Pen CSS Math round(): angles (Visual Reference) by Dan Wilson (@danwilson) on CodePen.