- From: Dael Jackson <daelcss@gmail.com>
- Date: Wed, 31 Aug 2022 07:02:58 -0400
- To: www-style@w3.org
========================================= These are the official CSSWG minutes. Unless you're correcting the minutes, Please respond by starting a new thread with an appropriate subject line. ========================================= CSS Backgrounds --------------- - oriol created a demo ( https://people.igalia.com/obrufau/testcases/shadow-radius/ ) of some possible solutions for issue #7103 (The shape of box-shadow should be a circle for a box with border-radius:50% and big spread). - There was some preference to combining a few examples to get the best behavior such as combining 2 & 3. - Whatever is decided here should also be applied toward outlines for consistency. - This sparked some new ideas that also need to be coded for a visual demo. Once those are complete, the group will revisit this issue. CSS Values ---------- - RESOLVED: Add random() and random-item(), mark open issues; goes into values-5 (Issue #2826: random() function) ===== FULL MEETING MINUTES ====== Agenda: https://github.com/w3c/csswg-drafts/projects/30 Scribe: TabAtkins CSS Backgrounds =============== Shape of box-shadow spread -------------------------- github: https://github.com/w3c/csswg-drafts/issues/7103 fantasai: I think we should have demos before we discuss this Rossen: oriol made those an hour ago oriol: You can see a comparison of the different algorithms oriol: I didn't find an algorithm that works perfectly for all oriol: but maybe I'm leaning towards the last one in the demo oriol: [demos] <bramus> https://people.igalia.com/obrufau/testcases/shadow-radius/ oriol: First is no polyfill at all, browser does different things oriol: This is chromium oriol: Here's current spec, where a circular element is a non-circular shadow oriol: Here's another showing that same, with an ellipse oriol: Another algorithm is to increase radius by spread oriol: Similar to firefox, but firefox has a special case for 0 radius that isn't continuous oriol: otherwise I'd say it's not a bad algorithm oriol: There are some variant algorithms that take the border radius, express it as a percentage, then apply the same % to the shadow oriol: good in some cases, but in this ellipse case it gets flat edges oriol: Using the maximum axis improves some cases but not all oriol: ellipse is still flat oriol: Then my original proposal is each percentage is taken independently per axis oriol: This works good I'd say, but has problem shown in this long round rect, oriol: where the shadow gets an elliptical corner when the original element was circular corner oriol: So final variant, finds percentages in each axis, then tries to, for each corner, if the radius has changed its aspect ratio relative to the element, it tries to increase one component to hit the same aspect-ratio oriol: with the limitation that it prevents the radius from going to [missed] oriol: We have a restriction that the x component of top-left and top-right radius shouldn't exceed the width; the spec has an adjustment for that oriol: so the constraint we apply here is we increase one component to restore the aspect ratio, without breaking this constraint oriol: I think this is the best I could find oriol: 0 radius gives square shadow, 1px gives mostly-square shadow oriol: circle and ellipse are still pretty round oriol: circular corners stay circular on the shadow even with long rects oriol: In this example (a "cup" shape) the shadow looks like it becomes thinner, but it is the same arc in both the shape and the shadow oriol: So this is the best idea I could find oriol: if people want to play with this they can look at the source, it's a standalone page <lea> would be nice if one could input their own dimension/spread/ radius values to see the result with the different algorithms oriol: [explains how to modify the demo] Rossen: fantastic, thanks for putting in the time for this <lea> Yes, so great to have a demo! thanks oriol! dbaron: I was looking at the cases where you said your preferred algorithm wasn't great dbaron: I agree it's not that great, like the 3rd from the end case dbaron: It seems what the algorithm is doing wrong is producing too large a radius dbaron: don't know why dbaron: The problem there is the radius we're ending up with seems larger than it should be oriol: Both arcs are circular oriol: inner element has border-radius of 39/39 oriol: shadow has border radius of 107/107 oriol: so x and y components are equal oriol: almost no radius in the top left, and the shadow similarly has almost no radius there fantasai: Last time we discussed this I wanted to ask... fantasai: We have a formula in the spec, and the original proposal that's to use the same percentages fantasai: so, could we decide which formula to use based on whether the original radius was expressed in lengths or percentages? fantasai: so if you have oval that's 50%, the spread would also be 50% fantasai: whereas if it was 200px/100px, we'd use the old formula fantasai: So rather than just doing math on the absolute value, carry over the initial intent fantasai: A different alternative would be fantasai: Looking at these tests, the ones that look bad in the old formula are the ones where the length of the straight part of the border are 0 or close fantasai: whereas the bad ones for %s are where the straight side is pretty long fantasai: so we could have two different formulas, using one when the straight side is 0 or the other when large fantasai: and between the two for some distance, such as radius = straight side to 0, we interpolate the formulas oriol: re: the first thing, choosing the algorithm depending on whether the author specified length or % oriol: I didn't consider that oriol: Issue is you can get the same shape in either way oriol: Seems strange to have two equivalent shapes for the element can produce different shadows fantasai: yeah but consider I have an element that's short, and the border-radius makes a semicircle, I might want that because I want a pillshaped box fantasai: *or* it might be a consequence of this box being short, and I have a set of boxes with rounded corners and straight sides, so I'd prefer the shadow generally to have straight sides fantasai: Dunno if it's a great idea. Authors might not think about their intent, and instead just shove in numbers that get a result oriol: Could be a possibility oriol: Didn't consider it, to have it differentiate would have to [missed] oriol: re: the other thing about combining algorithms oriol: You were mentioning the old algorithm, what browsers used to do and firefox still does fantasai: My understanding is chrome updated to current spec and realized there were problems fantasai: The cases that work poorly are those where you want to get a round shape fantasai: in those %s work great fantasai: but they work bad for rounded corners on a rectangular shape, that's where current spec works well fantasai: so using both formulas and interpolating might be a way to get good results in more cases oriol: But then how do you do this interpolation? fantasai: You look at the straight side, if it's 0 you use percent formula. If it's longer than the radius, use the old formula. Between those two, you do linear interp lea: Not super confident since this is the first time I've seen this lea: but looking through these algorithms lea: as an author, anything with a percent produces surprising results in some cases lea: The one that produces the least surprise, to me at least, is to increase radius by spread lea: except that it produces round from 0 radius lea: This was chrome's behavior before they changed? oriol: Yes, firefox has a discontinuity at 0 lea: So maybe because I was used to previous behavior, this makes sense to me lea: Is discontinuity acceptable? oriol: Another possibility is adding another initial value like "none" which keeps the shadow straight fantasai: If you think about this in terms of being a drop shadow, instead of a way to get a rounded corner outline, the results of "increase radius by spread" the results are clearly pretty unreasonable fantasai: If you switch to current spec it looks a little more like an actual shadow fantasai: the problem with current spec is the case with circles and ovals lea: So you're proposing neither of these fantasai: I'm proposing using current spec for first three examples, percent of side in the next two, and some interpolate in the rest fantasai: so formula I'm suggesting would be... 5th and 6th case would be current spec fantasai: 7th case would get you a combo, one axis would use each fantasai: Second to last would be percent lea: I think it's hard to picture how it looks fantasai: yeah I can code it up lea: I think we should definitely avoid that if you have a fully curved shape, the shadow should have any straight edges fantasai: Right, that's the issue we're trying to solve emilio: The other place where this pops up is outlines emilio: Do you propose to change both? fantasai: Both seems reasonable emilio: You're right that firefox's behavior for second case doesn't make sense for shadows, but I think it makes sense for an outline TabAtkins: Right I think outline is like a border emilio: So right now outline works like a border fantasai: So there's a discontinuity at zero Rossen: Spec has a cubic interpolation fantasai: Been in spec for a long time, chrome just implemented it and discovered problems fantasai: so I think using whatever we end up for spread radius would probably look good, but I think having continuous behavior generally is also pretty good fantasai: so might want to use same for both dbaron: First to emilio, I'm in favor of having a single algorithm in CSS for expanding a rounded rect dbaron: That is the direction I was pushing when I code-reviewed the patch that led to this in the first place <emilio> +1 to have a single algorithm dbaron: I'd like us to be consistent in inflation dbaron: The other point about inflating rounded rects, is you always start from the border edge and do a single inflation dbaron: you never do it from another algorithm dbaron: because inflate(10)+inflate(10) might be different than inflate(20), and certainly inflate(10)+inflate(-10) is definitely not the identity dbaron: can avoid problems by starting from the border edge always dbaron: One reason to keep these consistent is people might have both at the same time dbaron: if outline and shadow use different algorithms, that'll look bad dbaron: I think we'll be okay with a single algorithm dbaron: Looking through oriol's demos, I think the best results generally come from option 2 or 3 dbaron: While I understand the goal was to find the right compromise between 2 and 3, I think the percent options didn't really work out dbaron: I think the goal should be to find the right way to compromise between those two dbaron: There's also the 2-variant that is what browsers did before, which has the 0 discontinuity dbaron: so maybe a comp between 2 and 3 TabAtkins: Next steps, code up fantasai's idea TabAtkins: Anyone with other ideas, put them in the demo as well TabAtkins: Revisit in 2 weeks to decide? Rossen: Again, thanks to oriol for the demo <emilio> oriol++ CSS Values ========== scribe: fantasai random() function ----------------- github: https://github.com/w3c/csswg-drafts/issues/2826 <TabAtkins> https://github.com/w3c/csswg-drafts/issues/2826#issuecomment-1204305712 TabAtkins: This final comment is the current proposal TabAtkins: Idea we've thrown around for awhile TabAtkins: no urgency, but if people like it we can do it TabAtkins: People have asked for random() function in CSS for a long time TabAtkins: to use random colors, random positions, etc. TabAtkins: We've always rejected for good reasons, which is that randomness is stateful TabAtkins: I believe I have a solution TabAtkins: and would allow for JS to fill in the remaining use cases not covered TabAtkins: Proposal as shown in linked comment is 2 functions TabAtkins: 1) random() which takes some optional seed parameters TabAtkins: low, high, and optionally a resolution TabAtkins: same output type as math functions TabAtkins: Resolves to <number> between low and high, stepped by resolution TabAtkins: Important bit is the seed param, you can provide a custom ident TabAtkins: function with same seed and same low/high will always give same value throughout the document TabAtkins: so you can relayout and get the same result TabAtkins: and you can have the same result in multiple places in the document TabAtkins: In addition to custom-ident, could give per-element keyword TabAtkins: which gives a different result per element, but same result on the same element (?) TabAtkins: Second function is similar, but it uses the output as an index into a list of values TabAtkins: and selects a random one for you TabAtkins: that's it! lea: If you have custom property from 0 to 1 you can select any value based on custom property TabAtkins: If you need randomness that resolves at different times, you can use JS to poke it TabAtkins: or adjust seed value 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 flackr: ... TabAtkins: That paint API issue is pending a predictable random value in TC39 TabAtkins: but using this, could get a predictable random value in CSS and use that flackr: But not a bunch of random values TabAtkins: Not an arbitrary number of random values, need API to finish emilio: Debugging this is going to be fun miriam: As someone who uses a lot of randomness in my styles miriam: this would allow me to do that without reprocessing my stylesheet every time I want an update to the randomness so I really like this proposal fantasai: I think this sounds pretty good <bramus> thumbs up from me as well fantasai: I like the idea of using custom ident to coordinate without having to use numbers, just let the browser do it 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 that index from, you might want that to be generic, not specific to randomness fantasai: so you can index into a lit of values with attr() or a variable, etc fantasai: so rather than having a random item function, having something like nth-item() that takes a number and list fantasai: Also you probably want to separate the list with semicolons, like we're doing for mix() and (previously) toggle() <bkardell> I like what fantasai is throwing down TabAtkins: That was brought up earlier in the thread TabAtkins: Reason I didn't do that is because then you need to know the length of the list ahead of time to know what the random number is emilio: mod? TabAtkins: non-uniform results TabAtkins: also generic function probably doesn't want to mod TabAtkins: So yes, having nth-item is something we should have TabAtkins: and it is just slightly too un-ergonomic to use for randomness, unless we already add a count method TabAtkins: and then you have to either repeat your list or whatever TabAtkins: A lot of mess for just give me an item from this list TabAtkins: which I anticipate being reasonably item TabAtkins: not a strike against nth-item() fantasai: If we want them separate, I think we should do them together TabAtkins: Last point about semicolon. I might. Does mean that syntax that random and random-item is different TabAtkins: but that might be fine TabAtkins: Yeah, probably fine, probably should do that. I agree emilio: 1st, what is the syntax for the item in random item? emilio: tokens? TabAtkins: <declaration-value> emilio: So just a bunch of token TabAtkins: It's basically variable expansion emilio: random() presumably doesn't work like that TabAtkins: Correct, it's a math function TabAtkins: We could have them both work at variable time, but making it work as math is a little more useful emilio: Implementation-wise, a lot of stuff relies on being able to filter numbers at parse time emilio: basically once we're done parsing, translate function emilio: So implementation-wise ... TabAtkins: Already have that problem in calc() emilio: For raw numbers, yes emilio: Right now impl heavily rely on TabAtkins: Until you implement calc() per values-4 emilio: If you want this right now, that's where most of the complexity is emilio: just wanted to mention that TabAtkins: I'm trying to remember reason why having as a math function is more useful than var() TabAtkins: but I can't quite recall Rossen: Keep thinking, then emilio: The seed is not mandatory? TabAtkins: Yes, lack of seed is a seed. It's not arbitrary TabAtkins: If you say random(1,10) you get same random value every time lea: Several things, first I would like to express support. This is amazing. I've definitely used JS for this many times lea: It would be nice if we could combine and have one function, do we fundamentally need a different one for integers vs ? TabAtkins: That's literally what we're doing, it returns numbers and there's a step TabAtkins: Look at the last comment lea: Oh!! That's nice!! TabAtkins: [re-explains why having random-item() rather than nth-item(random()) ] fantasai: We can have both. nth-item() and random-item() can have parallel syntax and parallel functionality, and both exist lea: My other points are not relevant anymore then :) 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 TabAtkins: Unrelated issue fantasai: What's the computed value? fantasai: If you put it on an inherited property needs to be the same value on every element it inherits through TabAtkins: Not necessarily, if you ??? fantasai: If you take line-height to a random value for line-height fantasai: you get a different on each descendant? TabAtkins: It would not, it needs to be resolved to something stable TabAtkins: If it's a math function it resolves to a number TabAtkins: otherwise it might resolve later, e.g., if you have a percentage fantasai: Is it returning a number or a length / percent? TabAtkins: Depends on the argument fantasai: Needs to be clarified properly fantasai: so that it inherits properly emilio: Why can't it resolve to a number, and then output resolves later? TabAtkins: Say you want a value between 10% and 50% and step of 100px, how many values is that? emilio: So like clamp( ... ) TabAtkins: If you clamp, you're non-uniform TabAtkins: You need to know exactly how many steps between your low and high emilio: So how would you express that with your proposal <TabAtkins> random(..., 10%, 50%, by 100px) emilio: That's a lot more complex than I was expecting emilio: You have to keep that function around everywhere wherever you can accept the percentage all the way through calc() TabAtkins: I think it's why it had to be a math function, to get that to work fantasai: If you restrict it to the same type it you don't have that problem right? emilio: What fantasai's saying, if you want a percentage random between 50% and 100%, you don't have to wait until used value time emilio: so as long as you restrict it to the same type TabAtkins: Lengths can only be computed at used value type fantasai: No? TabAtkins: For now we've always made sure it's the case fantasai: Lengths are always computable to an absolute length Rossen: We're going too deep here. Let's put it in a spec Rossen: and then make progress on it Rossen: It seems like the group supports this generally Rossen: so let's do that Rossen: Let's try to add this to ... fantasai: values-5 TabAtkins: I'm comfortable to limiting to matching types, if that ends up TabAtkins: I'd still be ok Rossen: So proposal is to add them and maybe restrict it to numbers? Rossen: to CSS Values 5 <fantasai> For the record, I'd really like to restrict this to same type for low/high/step TabAtkins: The way it's written, you might not get the same result across pages. Might not get same result on reload dholbert: I hope we can document the algorithm so that it's stable between browsers TabAtkins: I think that's a great argument that reloads are not stable. But re-layout shouldn't be unstable lea: I think reloads should absolutely not be stable 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 emilio: With preprocessors, you can't do the per-element behavior emilio: That said, depending on how this function computes/resolves/ etc. emilio: Maybe not un-defeatable, but there's a bunch of optimizations that engines have to share styles across elements ... emilio: it's a bit unfortunate TabAtkins: Alternative is people manually decorate their functions emilio: Harder to do than * { z-index: random() } TabAtkins: True Rossen: Any objections? RESOLVED: Add random() and random-item(), mark open issues; goes into values-5 <TabAtkins> * { position: relative; z-index: random(per-element, 0, 2e9); } <miriam> ^ this is now considered 'best practice'
Received on Wednesday, 31 August 2022 11:03:39 UTC