Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Math Functions #149

Closed
ramiy opened this issue Sep 23, 2022 · 15 comments
Closed

CSS Math Functions #149

ramiy opened this issue Sep 23, 2022 · 15 comments
Labels
accepted An accepted proposal focus-area-proposal Focus Area Proposal

Comments

@ramiy
Copy link
Contributor

ramiy commented Sep 23, 2022

Description

Cross-browser support for CSS Math Functions:

  • Stepped value functions: round(), mod(), rem()
  • Trigonometric functions: sin(), cos(), tan(), asin(), acos(), atan(), atan2()
  • Exponential functions: pow(), sqrt(), hypot(), log(), exp()
  • Sign-related functions: abs(), sign()

Rationale

Developer needs:

  • It will help framework developers, like me, to create complex calculations using CSS.
  • My CSS data visualization framework Charts.CSS has no JS, only CSS.
  • I can use trigonometric functions to style complex layouts using CSS.
  • Additional needs include calculations inside CSS animations.
  • Non static layouts - replacing simple units with calculations.

Impact:

  • No JS rendering - moving calculations to CSS.
  • Faster load time - developer will no longer need to load CSS and JS assets. They can load only CSS.

Browser compatibility:

Safari is leading the way on support. Firefox is catching up.

  • Safari 15.4 added support for all those functions.
  • Firefox 103 added support for trigonometric functions behind layout.css.trig.enabled flag.
  • Chrome / Edge - no support.

Specification

https://w3c.github.io/csswg-drafts/css-values-4/#math

Tests

Web Platform Tests:

Bug Tracking

WebKit Bugzilla:

Mozilla Bugzilla:

Chromium Bugs:

BCD / MDN

Too many BCD/MDN links, check the main ones:

But, we will finish documenting all the math functions very soon.

@ramiy ramiy added the focus-area-proposal Focus Area Proposal label Sep 23, 2022
@gsnedders gsnedders added this to the Interop 2023 milestone Sep 24, 2022
@gsnedders
Copy link
Member

Rationale

Safari is leading the way on support. Firefox is catching up.

  • Safari 15.4 added support for all those functions.
  • Firefox 103 added support for trigonometric functions behind layout.css.trig.enabled flag.
  • Chrome / Edge - no support.

Hey—when it comes to rational we're primarily interested in web developer and/or end user impact, not the mere existence of bugs (or omitted features); one of the goals of the Interop projects is to focus on things that matter, not just to enumerate every incompatibility out there.

I've opened #151 to try and clarify that in the template, but if you could expand on why you believe this feature is important that would be great!

@ramiy
Copy link
Contributor Author

ramiy commented Sep 24, 2022

Hi @gsnedders, I've updated the "rationale" section. I added my personal rational and my specific needs.

@thebabydino
Copy link

thebabydino commented Sep 24, 2022

abs(), sign(), round() and mod()

Over a year ago, I wrote an article on how to emulate abs(), sign(), round() and mod() using the features already available in CSS. It includes tens of demos just for these four functions. I'll be listing the main categories most uses cases fall into, along with one or more examples. There are many others in the article.

Easy to get linear symmetry in staggered animations/ transitions

This is using the absolute value and the most basic example (live demo) of such an animation can be seen below, along just one direction:

Animated gif. Shows 16 black square tiles in a row, each of them growing from nothing to full size, then melting from the inside until they disappear, with the cycle then repeating. Only now, they don't all animate at the same time. The closer they are to the middle, the sooner they start their animation, those at the very ends of the row being one full cycle behind those in the very middle.

We could also have a symmetric waterfall transition on click (live demo):

Navigation links sliding up and then back down with a delay proportional to how far they are from the selected one.

We can also have linearly, symmetrically staggered animations in 2D, for grids like the ones we have on the faces of this pure CSS cube (live demo):

neon-waterfall

Different styles for items before and after a selected/ middle one

This is using the sign (and in some cases the absolute value as well). Consider this navigation menu, where the vertical lateral bar is on the side nearest to the selected item (live demo):

navigation-menu

Time (and not only) formatting

This uses rounding and modulo and can be seen live in this demo (Chromium only):

Screenshot showing a styled slider with a tooltip above the thumb indicating the elapsed time formatted as mm:ss. On the right of the slider, there's the remaining time formatted as -mm:ss.

Lighting/ shadows for convex & concave 3D shapes as they rotate

The simplest example is that of a rotating CSS cube, but we can also have more interesting shapes, like those used for this pure CSS musical toy:

music-toy


pow()

pow() would help with circularly staggered symmetric animations on a grid as in that case, the animation-delay of a grid cell depends on the sum of the squares of the horizontal and vertical indices, as illustrated here.

circularly-staggered


Trigonometric functions

Trigonometric functions can help in a lot of places too.

Placing items on a circle/ other shapes

Items on a circle is the most common use case (and explaining how to CSS it is one of my most upvoted StackOverflow answers, so there is a lot of practical interest for it).

Trigonometric functions help with computing the radius of the circle we want to place our items on if we know the size of the items and how much room we have around them. Or the other way around, help us size the items we position on the circle based on its radius.

Prior to Safari supporting them, what I used to do was precompute a tangent factor and hardcode it as a custom property --tan in the wrapper's style attribute.

A few months ago, I've started to redo some of my demos where I'm placing items on a circle. For example, this Möbius strip. This demo actually uses trigonometric functions (and it was using sign() too before I ditched that to extend support to Firefox, which supports trigonometric functions but not sign()) so it doesn't work in Chromium at this point.

moebius-trig

This can be extended to placing items on polygon edges, on spheres, on torus knots and so on.

Graphs/ charts

This is something I've been doing for about a decade now. At first, with Sass (live demo), but with Sass, it wasn't dynamic and it involved writing a lot of code.

2D chart

It's not limited to 2D. We can also graph functions in 3D this way. Some ten years ago, I did this with Sass (live demo), but again, a lot of code, not dynamic.

3D mesh

Lately, I've been doing it in a similar manner as positioning items on a circle: by hardcoding precomputed values as custom properties in style attributes.

3D surface

Properly synced animations

Consider such a loading animation (live demo):

tri-open

The inner triangles both rotate and scale at the same time. While the rotation animation is linear, the scaling one isn't. With trigonometric functions in CSS, we could animate just the rotation angle (of course, this would require the ability to register custom properties to animate them) and let the scaling factor depend on the cosine. At this point, I'm animating the two independent transform properties, rotate and scale separately and using a cubic-bezier() curve to approximate the cosine.

1 element loaders: animating radial-gradient() position on a circle

Trigonometric functions in CSS would allow me to code a loader like this one with a single element (currently using four). Or one like this without using filter tricks.

More interesting staggered animations

The conic one detailed in this twitter thread.

There are probably more uses cases, but these were the first that came to mind (and it's past 2:30am here and I'm falling asleep on the laptop).

@foolip foolip moved this to Proposed in Interop 2023 Oct 7, 2022
@foolip foolip removed this from the Interop 2023 milestone Oct 7, 2022
@foolip
Copy link
Member

foolip commented Nov 11, 2022

There were some mentions of math functions in State of CSS 2022, although not enough to make the top list in #248. Most of those were about min(), max() or clamp() which aren't part of this proposal, but 4 mentions were about parts of this proposal:

  • Trigonometric Functions (2 mentions)
  • sin() cos() tan()
  • css math functions like sin() cos() round() mod() atan2() etc.

@foolip
Copy link
Member

foolip commented Nov 11, 2022

In the MDN short survey on CSS & HTML, "CSS math functions (round(), sin(), pow(), abs(), etc.)" was selected by ~27% of survey takers, putting it in the top third of the 20 options. (There is some uncertainty as with any survey data.)

@ramiy
Copy link
Contributor Author

ramiy commented Nov 12, 2022

State of CSS 2022 - no results yet...

MDN CSS & HTML survey - quite high demand, 4th place out of 20.

@thebabydino
Copy link

There were some mentions of math functions in State of CSS 2022, although not enough to make the top list in #248.

This might have something to do with the wording of the questions. They're not something that I see as completely missing, as there is a spec, Safari supports them, Firefox supports a few of them. At the same time, given that both Safari and Firefox implementations are pretty new, from this year, the lack of support in Chromium is not yet at frustrating levels. I'm a lot more frustrated by the lack of support for the filter() function in anything other but Safari after more than half a decade, the lack of support for @property in anything but Chromium after... that's about 5 years too, isn't it?

@foolip
Copy link
Member

foolip commented Nov 15, 2022

@thebabydino the wording of the question in State of CSS 2022 was:

Are there any existing CSS features that you have difficulties using (or avoid altogether) because of lack of support, or differences between browsers?

It was a freeform text question. The most common answer (:has()) is also shipping in some browsers and not others, similar to these math functions, although it's not the same browsers that have/lack support in that case.

Of course a lot of things can affect whether a feature is top-of-mind enough to show up in a question like this, for example I suspect it's much easier to remember and name a single big feature like "container queries" than a collection of functions like this one.

@thebabydino
Copy link

@foolip My point was that in the case of mathematical functions, the implementations that do exist haven't been around enough for this to be an issue. The Safari and Firefox implementations are from this year. I've barely had time to get a bunch of demos done to get a feel for how they work, if there are still bugs to be ironed out (fortunately, haven't hit any). They're a brand new thing I'm just happy I can finally test in some browsers. I haven't arrived at the point where the lack of support in Chromium browsers is a pain yet and I personally took this question as a "place to complain about things where imperfect support frustrates you".

As for :has(), my guess there's a lot of inertia behind that. There has been talk about a parent selector for as long as I've known what CSS even is. It's like a carrot that's been waved in front of the donkey for far too long - give it to me already! Whereas trigonometric functions are like a gift that got dropped in front of you unexpectedly - oh, wow, is this even real?

There's also the fact that in general, it's easy to forget things if they're not right in front of you. A couple of days after taking the survey, I ran into something that I had forgot to mention as an answer here. And some things can change fast. Last weekend, I ended up using for the first time one of the features I labeled as "never heard of" when I took the survey. I happened to see it in someone else's code, had a "what the hell is this anyway?" moment, looked it up and then ended up using it myself.

@foolip
Copy link
Member

foolip commented Nov 17, 2022

I haven't arrived at the point where the lack of support in Chromium browsers is a pain yet and I personally took this question as a "place to complain about things where imperfect support frustrates you".

That was the intention with that question, yeah. There were also these two questions:

  • What features do you feel are currently missing from CSS altogether?
  • Any other pain points related to writing CSS?

The idea was that whatever stage a feature is in, it could make sense to mention somewhere.

I haven't analyzed the freeform text responses to the other two questions (it's time consuming!) but I took a look for math mentions and found these:

  • more complex math
  • more math functions
  • Math functions (sin(), cos())
  • math functions in css across browers, not just safari, firefox
  • Advanced mathematics, e.g. pow, atan, htan

The first 4 was in the "missing" question and the last was from the "other" question.

I can't say for sure without vetting all responses, but I think this won't make the top 20 for either question. There is some signal though, I'm not arguing against the feature being useful.

@foolip
Copy link
Member

foolip commented Nov 17, 2022

@xiaochengh has said that atan2() is a bit tricky because it allows involving relative length units in a <number>, e.g., atan2(1vw, 1em). Is this tested, and is it correctly implemented by any browser?

@ramiy
Copy link
Contributor Author

ramiy commented Nov 17, 2022

@xiaochengh has said that atan2() is a bit tricky because it allows involving relative length units in a , e.g., atan2(1vw, 1em). Is this tested, and is it correctly implemented by any browser?

Both Safari and Firefox correctly implemented atan2().

See the Web Platform Tests - https://wpt.fyi/results/css/css-values/acos-asin-atan-atan2-computed.html?label=master&label=experimental&aligned&view=subtest

@foolip
Copy link
Member

foolip commented Nov 17, 2022

@xiaochengh does that test cover the case you had in mind? AFAICT they all have the same unit for the first and second argument, is the problematic case when it's two different units?

@xiaochengh
Copy link

xiaochengh commented Nov 17, 2022

@foolip No, it doesn't.

is the problematic case when it's two different units?

More precisely, when there are relative length units to resolve (like the case you gave).

In this case, Safari seems to just ignore the units, while Firefox treats it as a parse error.

@foolip foolip added the accepted An accepted proposal label Feb 1, 2023
@foolip
Copy link
Member

foolip commented Feb 1, 2023

Thank you for proposing CSS Math Functions for inclusion in Interop 2023.

We are pleased to let you know that this proposal was accepted as the Math Functions focus area. You can follow the progress of this Focus Area on the Interop 2023 dashboard.

For an overview of our process, see the proposal selection summary. Thank you for contributing to Interop 2023!

Posted on behalf of the Interop team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted An accepted proposal focus-area-proposal Focus Area Proposal
Projects
No open projects
Status: Proposed
Development

No branches or pull requests

5 participants