More Math Functions?

Recently, a bunch of new math functions has been added to CSS Values and Units:

Rounding functions are being considered right now. Do we need anything else and what for?

mod(x, y)/modf(x, y)

if(p) which evaluates to 1 if p evaluates to true and 0 otherwise. (Iverson bracket notation.)

log(x, b) and the constant e (might as well throw pi in there, too, to go with the trig stuff)

A way to define and call user defined functions to name common calculations that vary only in their parameterization.

With those additions and the rounding functions, you could define pretty much anything you want.

You can already do any continuous function you want with just calc, if you’re really determined and much more easily with pow in the mix. Discontinuous functions are really cumbersome and hacky without floor/mod/if.

Of all of them the ones that come up the most are min/max. if would be very handy for collapsing a lot of piecewise calculations specified in different media queries and variables into one line. floor/mod could make some interesting layouts easy to do more directly without counting queries. log may not come up often except possibly as an error correcting term but I threw it in because it was the largest common function missing. Having a way to name complicated calc computations would help with reusability and readability. Some of them can get hairy and fixing a bug in one place instead of the three it was copied to would be great—and as more things are possible to calculate I imagine this need would get more common.

Conditions with if() are not quite the kind of math most of CSS is concerned with. It has also been proposed and rejected before:

Tab Atkins explained the consequences of the WG resolution to add trigonometric functions thus (with my highlighting):

  1. Adding more functions is on the table if necessary; abs() and mod(), in particular, are probably worth adding. We don’t want to go too deep, as there’s a lot of possible math stuff one could add, and Houdini Custom Functions is the next spec on my list (…)

In that thread, yours truly mentioned some:

Javascript also has cube root, cbrt(), which should mean that some people find this convenient.

It would probably be convenient to also have functions for cotangent, secant and cosecant , even if Javascript does not provide these reciprocal functions. A reciprocal function, 1/x, for just the value, i.e. without changing the unit, might be beneficial as well, but no actual use case comes to mind.

When min() and max() were accepted, I said:

I’m seriously considering to propose sum() or add() and sub() now, because that would also work outside calc() .

mid() / avg(), med(), mod(); abs() etc. would probably also require separate issues.

Here are some other existing proposals for mathematical functions and constants in CSS, sorted by age:

In that thread, yours truly mentioned some: […]

Experience with XSL-FO and other formatting languages, and with XPath, led us to introduce more functions for XPath 2 (and more for XPath 3).

I’m seriously considering to propose sum() or add() and sub() now, because that would also work outside calc() .

sum() and count() are useful, as is format-number() (like printf but with both base and writing system conversion, e.g. to roman numerals; this is already in the XSLT in Web Browsers in an early form [1]).

Overall, custom functions are probably the way to go for more complex stuff, though. For example, if you add count(), people start wanting to count the number of table elements prior to the current point in the document. And as it stands, CSS isn’t strong at doing things like, “colour table cells red if the number in them is less than 0” let alone, “is less than the number in the cell above them”.

You can do these things without custom functions in XPath, but at the cost that XPath is maybe slightly harder to use in simpke cases and becomes quite the logic puzzle for complex cases at times.

Simple maths functions make sense e.g. for calculating aspect ratios, but if you’re trying to do calculus in CSS i think some very specific uses cases are needed.

Things in standards are there because they’re needed for some sense of completeness, because they are hard for individual users to get right themselves or (best of all) to ensure interperability.

[1] https://www.w3.org/TR/xpath-functions-31/#func-format-integer is written to be rather precise and described in detail, but after the spec part there are examples. I’m mentioning it to give an example of the kinds of thing people tend to ask for when you give them functions like max() and count(). Where to stop?

1 Like

Thanks for the links to other issues. I had seen some of them but not most of them.

I had seen the one for if. That one is for a different kind of if. It was correctly rejected for being too powerful. It could be used in any context and refer to properties of the element like width: if(width < 500px, 600px, 400px). It could also be used like if(p, 5%, blue).

The one I proposed only outputs a number and, though I did not specify, it does not have a mechanism to refer to the element, just var, env, attr, the results of other numeric functions, and literals.

With it, you could compute the sign of x as if(var(--x) > 0) - if(var(--x) < 0). If x = 0, it’s 0 - 0 = 0. If x < 0, it’s 0 - 1 = -1. If x > 0, it’s 1 - 0 = 1. Since abs(x) can be defined as x*sgn(x), you also get that for free (though abs and sgn are both probably common enough to deserve shorthands.)

In general, it makes it easy to “toggle” terms on and off in an expression, like width: calc(100px + 50px*if(var(--x) < 10) - 50px*if(var(--y) > 20)) which can be 50, 100, or 150px wide dependent on the values of x and y.

A useful related function would be media(q) that returns 1 if the media query q holds and 0 otherwise. Then you could just do --do-animations: media((prefers-reduced-motion)) instead of defining it to 1 and then redefining it to 0 in a media query.


I’m not sure I see the point of sum, avg, etc. Without lists, you always know how many quantities are involved so sum(1, 2, 3) isn’t much better than calc(1 + 2 + 3). With lists you’d need to add all kinds of list functions too. It’s also unclear to me why one would need to compute the arithmetic mean in css.

If it takes a selector then it’s more useful.

td.ordertable.total { content: calc( sum(td.ordertable.itemprice) * var(–sales-tax) ); }

Same with count(). But (for once?) i’m with Tab here - wait and see what’s wanted. I gave them as examples because we’ve had the experience of going down similar discussions with XPath, and it can really help to anticipate the possibility of wanting stuff like that.

Liam

Ah, yes, if it’s getting the data from the document, it makes sense. As much as I’d like it be possible to do more with css, I’m not sure that’s a good road to go down. It’s long and bumpy and there are a lot of a11y potholes. Best to do such things with js/when generating the html.

1 Like