Re: [csswg-drafts] [css-values] random() function (#2826)

The CSS Working Group just discussed `random()`, and agreed to the following:

* `RESOLVED: Add random() and random-item(), mark open issues`

<details><summary>The full IRC log of that discussion</summary>
&lt;fantasai> Topic: random()<br>
&lt;fantasai> github: https://github.com/w3c/csswg-drafts/issues/2826<br>
&lt;TabAtkins> https://github.com/w3c/csswg-drafts/issues/2826#issuecomment-1204305712<br>
&lt;fantasai> TabAtkins: This final comment is the current proposal<br>
&lt;fantasai> TabAtkins: idea we've thrown around for awhile<br>
&lt;fantasai> TabAtkins: no urgency, but if ppl like it we can do it<br>
&lt;fantasai> TabAtkins: People have asked for random() function in CSS for a long time<br>
&lt;fantasai> TabAtkins: to use random colors, random positions, etc.<br>
&lt;fantasai> TabAtkins: we've always rejected for good reasons, which is that randomness is stateful<br>
&lt;fantasai> TabAtkins: I believe I have a solution<br>
&lt;fantasai> TabAtkins: and would allow for JS to fill in the remaining use cases not covered<br>
&lt;fantasai> TabAtkins: Proposal aas shown in linked comment is 2 functions<br>
&lt;fantasai> TabAtkins: 1) random() which takes some optional seed params<br>
&lt;fantasai> TabAtkins: low, high, and optionally a resolution<br>
&lt;fantasai> TabAtkins: same output type as math functions<br>
&lt;fantasai> TabAtkins: resolves to &lt;number> between low and high, stepped by resolution<br>
&lt;fantasai> TabAtkins: important bit is the seed param, you can provide a custom ident<br>
&lt;fantasai> TabAtkins: function with same seed and same low/high will always give same seed<br>
&lt;fantasai> TabAtkins: so you can reload and get the same result<br>
&lt;fantasai> TabAtkins: and you can have the same result in multiple pages in the document<br>
&lt;fantasai> TabAtkins: in addition to custom-ident, could give per-element keyword<br>
&lt;fantasai> TabAtkins: which gives a different result per element, but same result on the same element (?)<br>
&lt;fantasai> TabAtkins: second function is similar, but it uses the output as an index into a list of values<br>
&lt;fantasai> TabAtkins: and selects a random one for you<br>
&lt;fantasai> TabAtkins: that's it!<br>
&lt;Rossen_> q?<br>
&lt;flackr> q+<br>
&lt;emilio> q+<br>
&lt;fantasai> lea: if you have custom property from 0 to 1 you can select any value based on custom property<br>
&lt;fantasai> TabAtkins: if you need randomnes that resolves at different times, you can use JS to poke it<br>
&lt;fantasai> TabAtkins: or adjust seed value<br>
&lt;miriam> q+<br>
&lt;Rossen_> ack flackr<br>
&lt;fantasai> flackr: this reminds me an issue with paint API where you want predictable random numbers, so that you wouldn't be exposed to when something is painting<br>
&lt;fantasai> flackr: ...<br>
&lt;fantasai> TabAtkins: that paint API issue is pending a predictable random value in TC39<br>
&lt;fantasai> TabAtkins: but using this, could get a predictable random value in CSS and use that<br>
&lt;fantasai> flackr: but not a bunch of random values<br>
&lt;fantasai> TabAtkins: not an arbitrary number of random values, need API to finish<br>
&lt;Rossen_> ack emilio<br>
&lt;fantasai> emilio: debugging this is going to be fun<br>
&lt;emilio> q-<br>
&lt;emilio> q+<br>
&lt;Rossen_> ack miriam<br>
&lt;fantasai> miriam: As someone who uses a lot of randomness in my styles<br>
&lt;lea> +q<br>
&lt;fantasai> miriam: this would allow me to do that without reprocessing my stylesheet every time i want an update to the randomnes so I really like this proposal<br>
&lt;TabAtkins> fantasai: i think this sounds pretty good<br>
&lt;bramus> thumbs up from me as well<br>
&lt;TabAtkins> fantasai: i like the idea of using custom ident to coordinate without having to use numbers, just let the borwser do it<br>
&lt;Rossen_> ack fantasai<br>
&lt;Zakim> fantasai, you wanted to suggest that index return should be a generic function<br>
&lt;TabAtkins> fantasai: one comment i have right now is random-item(), which has a first argument that returns an index, then a list of items that you select tha tindex from, you might want that to be generic, not specific to randomness<br>
&lt;TabAtkins> fantasai: so you can index into a lit of values with attr() or a variable, etc<br>
&lt;TabAtkins> fantasai: so rather than having a random item function, having something like nth-item() that takes a number and list<br>
&lt;TabAtkins> fantasai: also you probably want to separate th elist with semicolons<br>
&lt;bkardell_> I like what fantasai is throwing down<br>
&lt;fantasai> TabAtkins: that was brought up earlier in the thread<br>
&lt;fantasai> TabAtkins: reason I didn't do that is because then you need to know the lenght of the list ahead of time to know what the random number is<br>
&lt;fantasai> emilio: mod?<br>
&lt;fantasai> TabAtkins: non-uniform results<br>
&lt;fantasai> TabAtkins: also generic function probably doesn't want to mod<br>
&lt;fantasai> TabAtkins: so yes, having nth-item is something we should have<br>
&lt;fantasai> TabAtkins: and it is just slightly too unergonoic to use for randomness, unless we alread add a count method<br>
&lt;bkardell_> q+<br>
&lt;fantasai> TabAtkins: and then you have to either repeat your list or whatever<br>
&lt;fantasai> TabAtkins: a lot of mess for just give me an item from this list<br>
&lt;fantasai> TabAtkins: which I anticipate being reasonably item<br>
&lt;fantasai> TabAtkins: not a strike against nth-item()<br>
&lt;lea> q?<br>
&lt;fantasai> fantasai: If we want the separate, I think we should do them together<br>
&lt;bkardell_> q-<br>
&lt;fantasai> TabAtkins: last point about semicolon. I might. Does mean that syntax that random and random-item is different<br>
&lt;fantasai> TabAtkins: but that might be fine<br>
&lt;fantasai> TabAtkins: yeah, probably fine, probably should do that. I agree<br>
&lt;fantasai> emilio: 1st, what is the syntax for the item in random item?<br>
&lt;fantasai> emilio: tokens?<br>
&lt;fantasai> TabAtkins: &lt;declaration-value><br>
&lt;fantasai> emilio: so just a buch of token<br>
&lt;fantasai> TabAtkins: it's basically variable expansion<br>
&lt;fantasai> emilio: random presumably doesn't work like that<br>
&lt;fantasai> TabAtkins: correct, it's a math function<br>
&lt;fantasai> TabAtkins: we could have them both work at variable time, but making it work as math is a little more useful<br>
&lt;fantasai> emilio: implementation-wise, a lot of stuff relies on being able to filter numbers at parse time<br>
&lt;fantasai> emilio: basically once we're done parsing, translate function<br>
&lt;fantasai> emilio: so implementationwise ...<br>
&lt;fantasai> TabAtkins: already have that problem in calc()<br>
&lt;fantasai> emilio: for raw numbers, yes<br>
&lt;fantasai> emilio: right now impl heavily rely on<br>
&lt;Rossen_> ack emilio<br>
&lt;fantasai> TabAtkins: until you implement calc() per values-4<br>
&lt;fantasai> emilio: if you want this right now, that's where most of the complexity is<br>
&lt;fantasai> emilio: just wanted to mention that<br>
&lt;fantasai> TabAtkins: I'm trying to remember reason why having as a math function is more useful than var<br>
&lt;fantasai> TabAtkins: but I can't quite recall<br>
&lt;fantasai> Rossen_: keep thinking, then<br>
&lt;fantasai> emilio: the seed is not mandatory?<br>
&lt;fantasai> TabAtkins: yes, lack of seed is a seed. It's not arbitrary<br>
&lt;fantasai> TabAtkins: If you say random(1,10) you get same random value ever time<br>
&lt;fantasai> lea: Several things, first I would like to express support. This is amazing. I've definitely used JS for this many times<br>
&lt;fantasai> lea: it would be nice if we could combine and have one function, do we fundamentally need a different one for integers vs ?<br>
&lt;Rossen_> ack lea<br>
&lt;fantasai> TabAtkins: that's literally what we're doing, it returns numbers and there's a step<br>
&lt;fantasai> TabAtkins: look at the last comment<br>
&lt;fantasai> lea: oh!! That's nice!!<br>
&lt;fantasai> TabAtkins: [re-explains why having random-item() rather than nth-item(random()) ]<br>
&lt;fantasai> fantasai: We can have both. nth-item() and random-item() can have parallel syntax and parallel functionality, and both exist<br>
&lt;fantasai> lea: My other points are not relevant anymore then :)<br>
&lt;fantasai> lea: it would also solve a host of use cases if you provide a list of values and get the index back, e.g. have higher-level custom properties and map to other values. Open issue in Web Components for awhile<br>
&lt;fantasai> TabAtkins: unrelated issue<br>
&lt;fantasai> fantasai: what's the computed value?<br>
&lt;Rossen_> ack fantasai<br>
&lt;Zakim> fantasai, you wanted to ask about inheritance<br>
&lt;fantasai> fantasai: if you put it on an inherited property needs to be the same value on every element it inherits through<br>
&lt;fantasai> TabAtkins: not necessarily, if you ???<br>
&lt;emilio> fantasai: if you take line-height to a random value for line-height<br>
&lt;emilio> ... you get a different on each descendant?<br>
&lt;emilio> TabAtkins: it would not, it needs to be resolved to something stable<br>
&lt;emilio> ... if it's a math function it resolves to a number<br>
&lt;emilio> ... otherwise it might resolve later, e.g., if you have a percentage<br>
&lt;emilio> fantasai: is it returning a number or a length / percent?<br>
&lt;emilio> TabAtkins: depends on the argument<br>
&lt;emilio> q+<br>
&lt;emilio> fantasai: needs to be clarified properly<br>
&lt;fantasai> fantasai: so that it inherits properly<br>
&lt;fantasai> emilio: why can't it resolve to a number, and then output resolves later?<br>
&lt;fantasai> TabAtkins: say you want a value between 10% and 50% and step of 100px, how many values is that?<br>
&lt;fantasai> emilio: so like clamp( ... )<br>
&lt;fantasai> TabAtkins: if you clamp, you're non-uniform<br>
&lt;fantasai> TabAtkins: you need to know exactly how many steps between your low and high<br>
&lt;fantasai> emilio: so how would you express that with your proposal<br>
&lt;Rossen_> ack emilio<br>
&lt;TabAtkins> random(..., 10%, 50%, by 100px)<br>
&lt;fantasai> emilio: That's a lot more complex than I was expecting<br>
&lt;fantasai> emilio: you have to keep that function around everywhere wherever you can accept the percentage all the way through calc()<br>
&lt;fantasai> TabAtkins: I think it's why it had to be a math function, to get that to work<br>
&lt;emilio> fantasai: if you restrict it to the same type it you don't have that problem right?<br>
&lt;fantasai> emilio: what fantasai's sying, if you want a percentage random between 50% and 100%, you don't have to wait until used value time<br>
&lt;fantasai> emilio: so as long as you restrict it to the same type<br>
&lt;emilio> TabAtkins: lengths can be computed at used value type<br>
&lt;emilio> fantasai: no?<br>
&lt;fantasai> s/can be/can only be/<br>
&lt;emilio> TabAtkins: for now we've always made sure it's the case<br>
&lt;fantasai> fantasai: lengths are always computable to an absolute length<br>
&lt;fantasai> Rossen_: We're going too deep here. Let's put it in a spec<br>
&lt;fantasai> Rossen_: and then make progress on it<br>
&lt;fantasai> Rossen_: it seems like the group supports this generally<br>
&lt;fantasai> Rossen_: so let's do that<br>
&lt;fantasai> Rossen_: let's try to add this to ...<br>
&lt;fantasai> fantasai: values-5<br>
&lt;fantasai> TabAtkins: I'm comfortable to limiting types, if that ends up<br>
&lt;fantasai> TabAtkins: I'd still be ok<br>
&lt;fantasai> Rossen_: so proposal is to add them and maybe restrict it to numbers?<br>
&lt;fantasai> Rossen_: to CSS Values 5<br>
&lt;fantasai> For the record, I'd really like to restrict this to same type for low/high/step<br>
&lt;fantasai> TabAtkins: The way it's written, you might not get the same result across pages. Might not get same result on reload<br>
&lt;fantasai> dholbert: I hope we can document the algorithm so that it's stable between browsers<br>
&lt;fantasai> TabAtkins: I think that's a great argument that reloads are not stable. But relayout shouldn't be unstable<br>
&lt;lea> q+ to say reloads should absolutely not be stable<br>
&lt;fantasai> lea: I think reloads should absolutely not be stable<br>
&lt;fantasai> lea: if you want a random color for your theme ever time page loads etc, if you get the same thing you might as well pre-compute and be done with it<br>
&lt;Rossen_> ack lea<br>
&lt;Zakim> lea, you wanted to say reloads should absolutely not be stable<br>
&lt;fantasai> emilio: with preprocessors, you can't do the paired element behavior<br>
&lt;dholbert> s/paired element/per-element/<br>
&lt;fantasai> emilio: that said, depending on how this function computes/resolves/etc.<br>
&lt;fantasai> emilio: maybe not undefeatble, but there's a bunch of optimizations that engines have to share styles across elements ...<br>
&lt;fantasai> emilio: it's a bit unfortunate<br>
&lt;fantasai> TabAtkins: alternative is people manually decorate their functions<br>
&lt;fantasai> emilio: harder to do than * { z-index: random() }<br>
&lt;fantasai> TabAtkins: true<br>
&lt;fantasai> Rossen_: any objections?<br>
&lt;fantasai> RESOLVED: Add random() and random-item(), mark open issues<br>
&lt;fantasai> goes into values-5<br>
&lt;TabAtkins> * { position: relative; z-index: random(per-element, 0, 2e9); }<br>
&lt;miriam> ^ this is now considered 'best practice'<br>
&lt;dbaron> next topic is aspect-ratio<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/2826#issuecomment-1204425784 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 3 August 2022 20:11:21 UTC