- 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