- From: Dael Jackson <daelcss@gmail.com>
- Date: Thu, 25 Apr 2024 19:46:44 -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.
=========================================
Alternate masonry path forward
------------------------------
- jensimmons presented an overview of the proposal for issue #9041
(Alternate masonry path forward) and an accompanying demo to add
clarity (demo: https://webkit.org/demos/grid3/photos/ )
- The Google & Edge implementors were concerned that the current
proposal would not be implementable because the algorithm would
cause exponential behavior in some cases and proposed some
restrictions to prevent it (full details in this comment:
https://github.com/w3c/csswg-drafts/issues/9041#issuecomment-2075210820 )
- Several folks expressed concern with including this in Grid since,
though they have similarity, understanding masonry in a grid
context would limit what masonry could do. On the other hand,
authors could want to switch between grid and masonry at
different breakpoints which would argue for keeping them together.
- Discussion will continue on github to allow folks time to think
about and discuss the various ideas raised on the call.
CSS Color
---------
- RESOLVED: `none` is preserved in calculations involving CSS math
functions (Issue #10211: Clarify that `none` is preserved
in calculations)
- RESOLVED: When interpolating between two none-containing values,
the result is a calc-mix() expression preserving the
`none` keywords in both values (Issue #10211)
===== FULL MEETING MINUTES ======
Agenda: https://lists.w3.org/Archives/Public/www-style/2024Apr/0006.html
Present:
Rachel Andrew
Rossen Atanassov
Tab Atkins Bittner
Kevin Babbitt
David Baron
Andreu Botella
Oriol Brufau
Stephen Chenney
Emilio Cobos Álvarez
Yehonatan Daniv
Elika Etemad
Robert Flack
Chris Harrelson
Daniel Holbert
Jonathan Kew
Roman Komarov
Una Kravets
David Leininger
Vladimir Levin
Chris Lilley
Alison Maher
Florian Rivoal
Jen Simmons
Miriam Suzanne
Alan Stearns
Brandon Stewart
Bramus Van Damme
Lea Verou
Sebastian Zartner
Regrets:
Eric Meyer
Chair: Rossen
Scribe: fantasai
Scribe's scribe: schenney
Alternate masonry path forward
==============================
github: https://github.com/w3c/csswg-drafts/issues/9041
fantasai: Topics: can masonry replace grid, track info, interaction
of masonry-grid. For authors? For spec?
<fantasai> ->
https://github.com/w3c/csswg-drafts/issues/9041#issuecomment-2071086963
fantasai: Question? Use case for variable track sizes. It's not
necessary, all sorts of objections due to complexity. Jen
Simmons has demos to present and talk through.
jensimmons: We're hoping to make real progress on this question, it's
been 4 years since this question first came up
jensimmons: the demos are online
<bts> Link to demo: https://webkit.org/demos/grid3/photos/
jensimmons: Photos demo is a good start. If we show numbers you can
see multicol layout, where the images go down the first
column, then second, etc.
jensimmons: for this content it's ok, other content it's not great;
but also it doesn't allow loading additional content to
the bottom
jensimmons: If you use grid L1, it lines up in both row and column.
If aspect ratio isn't uniform, doesn't look great
jensimmons: Masonry gives a chance to lay things out going across the
top of the columns, and then keep going across filling
the shortest column
jensimmons: it builds into grid easily, can specify any set of
columns you want and then set rows to 'masonry'
jensimmons: basically turns the rows off
jensimmons: There are other things you can do with grid, because full
power of grid-template-columns
jensimmons: in this demo, first and last cols are fixed sizes, and
the middle columns 1fr, and number of columns scales with
width of window
jensimmons: Next demo, all columns are flexible but we have narrow
and wide columns
jensimmons: and always starts and ends with a narrow column
jensimmons: The basic masonry layout is popular because JS can only
do so much, but building into CSS can do a lot more
jensimmons: Spanning in grid allows some interesting possibilities,
e.g. every 5th item is wider here. Gives more graphic
design interest.
jensimmons: In this version made the landscape photos wider
jensimmons: [shows horizontal masonry demo]
jensimmons: Mega menus are another use case
jensimmons: Multicol would go down the columns, but masonry allows to
lay out the first items across
jensimmons: Text becomes more interesting also.
jensimmons: A lot of websites lay out teaser content by fitting the
content to the regular boxes
jensimmons: often by trucating it
jensimmons: keep everything the same aspect ratio, creates a very
modernist grid
jensimmons: this is why graphic design can feel boring on the web
jensimmons: Classic masonry allows more flow of content, but still
somewhat rigid
jensimmons: start applying different widths and spans, create very
interesting layouts
jensimmons: This last demo is classic masonry, but grid allows some
extra possibilities
jensimmons: the header/sidebar can be shifted to the other side using
explicit placement
jensimmons: or use subgrid to align metadata across cards
jensimmons: subgrid is powerful here
jensimmons: questions?
<florian> I underestimated this Newspaper demo. There's more to it
that I thought at first, and I do find it compelling
<lea> +1 for letting Jen finish. This is important, we can spend 5
more minutes on it. Also, talking about timeboxing came close
to taking more time than the actual presentation.
jensimmons: As I wrote in the article, this is about saying "hey,
we've got grid -- but what if we let go of the idea that
it's only modular grids?"
jensimmons: columnar grids are grid systems, historically in graphic
design
jensimmons: this just lets us turn off rows (or turn off columns)
jensimmons: and contents pack together
keithamus: Is this display: block grid?
jensimmons: no inlines, this is just 'display: grid'
TabAtkins: I posted a long comment to the issue about an hour ago.
Long because I went into our reasoning, but can read tldr
and proposal
TabAtkins: Summary of our position, we the Chrome+Edge engineers find
the current spec unshippable given the algorithm in it
<dbaron> https://github.com/w3c/csswg-drafts/issues/9041#issuecomment-2075210820
TabAtkins: it can trigger quadratic or exponential behavior, which
could brick the page
TabAtkins: we acknowledge they are edge cases
TabAtkins: The restrictions we need are not ones that Jen's demos hit
TabAtkins: We just need to restrict to either a) fixed or flexible
tracks OR b) intrinsic tracks
TabAtkins: Every demo presented works in those constraints
TabAtkins: problem only happens when you can mix intrinsic track with
other types of track sizing
TabAtkins: because that's when spanners start to contribute
differently in different racks
TabAtkins: On a more conceptual level, we think there's a number of
friction points where the syntax is suboptimal because
designed for 2D grid
TabAtkins: or concepts don't directly translate and need to default
values instead of rejecting at parse time
TabAtkins: e.g. auto-fit is treated as auto-fill
TabAtkins: However, we think there's also significant conceptual
similarity to grid. It has tracks, lines, etc.
TabAtkins: so should do as much connection between the two
TabAtkins: e.g. have subgrid take lines from a parent, assuming we
have fixed sizing bits
TabAtkins: Similarly submasonry value, taking lines from parent
TabAtkins: Everywhere they interact, make it easy to translate
knowledge. But they're still not the same thing, and
enough pain points that they should be done in different
display types
<dholbert> TabAtkins' github comment with more details:
https://github.com/w3c/csswg-drafts/issues/9041#issuecomment-2075210820
Lea: These demos are impressive, and this is solving real author pain
points.
Lea: I did have some reservations about how this combines with
multicol from an author point of view, but I think I'm now
convinced this makes sense as a part of grid.
Lea: One thing is that the `masonry` keyword seems a little magical.
How can authors set constraints on the min and max size of these
generated rows/columns? How does it interact with
`grid-auto-flow`?
Lea: e.g. what about 'dense' keyword?
miriam: Agree quite a bit with Lea. Agree we like this as part of
grid. Syntax feels right.
miriam: would like to add a few more constraints
miriam: get that there's some constraints on implementation
miriam: Looking at separate masonry proposal, seems like new terms
for similar things
miriam: Why do I need to learn new terms for the same thing?
miriam: I also might want to switch between grid and masonry at
different break points
miriam: keeping them together makes it a lot easier to do
miriam: I like the grid syntax if we can make it work
<lea> +1 to miriam great point about switching to/from masonry
fantasai: Response to Lea. I don't understand min/max rows columns.
Maybe explain later.
fantasai: Dense, autoflow maybe mergable from ? and ?
jensimmons: We put this out to designers and developers to see what
kind of feedback we would get
jensimmons: Overwhelmingly people want to see this as part of grid.
It's not 100%, but on issue in CSSWG it's roughly 80/20
in favor of building into grid.
jensimmons: Authors prefer making it part of what they're already
familiar with, already learning, as part of CSS Grid
<TabAtkins> wrt the author feedback, note that the blog post argued
exclusively against an overly simplistic model (only
fixed-size, identical tracks, a la multicol). Every demo
was showing how we need more than that. As I said, tho,
every demo is perfectly fine; the actual restrictions we
need are much more subtle. We can't take support for
"what the blog post displayed" as arguments for "build it
into Grid".
ydaniv: +1 to what miriam said before
ydaniv: Thinking about interpolation, animating to/from masonry and
grid
ydaniv: could be easier inside grid than between display types
florian: Thanks Jen & team for the demos, and also for presentation.
I had skimmed the blog but realized more things during
presentation
florian: more compelling, and really makes the case for needing these
capabilities
florian: With regards to Google proposal posted recently, seems it's
fuller than what was originally discussed
florian: I think we need more time on this topic soon, and discuss
the differences between the two
rachelandrew: WebKit team presented to developers saying the only way
is to have grid implementation, and I don't think
that's the case as Tab outlined
rachelandrew: but when I first started showing people Flexbox and
Grid, people would say "it's inconsistent", because it
was different from block layout
rachelandrew: at this point we have good understanding of formatting
contexts
rachelandrew: My worry as someone who teaches this is, if we put
masonry in grid we have to say "these properties only
work in grid that's not masonry" or "these properties
only work in grid that is masonry"
rachelandrew: If we build into a separate display type, can still
have a lot of cool stuff, but not dancing around the
differences
dholbert: We have a prototype implementation of masonry in grid
dholbert: I'm sympathetic to the performance considerations of every
item in every track
dholbert: agree with sharing a lot of the same behavior with grid
dholbert: using a restricted form of track syntax but compatible for
masonry, that's only possible to do by using a different
set of property names
lea: How does masonry work with explicit grid placement?
fantasai: If you specify specific track, masonry item goes there.
fantasai: Just like grid etc, move to that position and keep placing.
florian: Do you ignore a dimension?
fantasai: Yes.
<lea> Yup, just tried it in the demo, it seems to work very
reasonably, nice
<TabAtkins> + there's a switch in masonry-auto-flow about whether to
place all the explicit items first (like Grid does) or in
the normal order.
<lea> big +1 for integrating masonry-auto-flow with grid-auto-flow if
this becomes part of grid
Rossen: Good discussion, let's review comments and come back to it
later.
<astearns> let’s keep posting and conversing in the issue - please do
not wait until we can schedule more call time
CSS Color
=========
scribe: dholbert
Clarify that `none` is preserved in calculations
------------------------------------------------
github: https://github.com/w3c/csswg-drafts/issues/10211
lea: Awhile back we invented 'none' value for color components to
represent achromatic colors (that don't have a particular hue)
lea: when converting gray to a polar format, which hue do you use?
none are relevant
lea: then we expanded to chroma and saturation for same reason
lea: Eventually it turns out once it was deployed, very useful in
many more use cases
lea: lets you represent colors that are parameterizable, that get
meaning based on where you use them
lea: e.g. color with `none`s and lightness, and mix with it to get
tints
lea: with relative color syntax becomes even more useful
lea: When we wrote the spec, what do you output a color that has
'none'?
lea: so we decided to make it convert to zero
lea: When you're converting from one color space to another, e.g. rgb
to lch
lea: you don't want to expose color space conversion math
lea: This conversion to zero is like a last ditch effort. Last thing
you do if there's nothing else reasonable to do
lea: The way this was interpreted by impls, you also convert to zero
when you can't do a computation, e.g. calc(h)
lea: This is against author intent; h and calc(h) should really be
the same
lea: You could imagine having a color in relative color syntax and
using calc or calc-mix to ?
lea: All of these would be solved if we resolved that 'none' was
preserved during calculations. Don't convert `none`s to
anything, `none`s remain `none`s
lea: I've written details about how this might work in the issue
lea: Interpolation operations have the behavior of the current value
of none, only have this behavior if the other value is not
"none-containing"
lea: Of you're interpolating between a value with none to some other
value, you get the non-none-containing value
lea: [missed some]
lea: This reduces magic/discontinuities.
lea: Also need to sort out how to handle this for a syntax that
allows 'none', e.g. clamp's 1st or 3rd argument. Is it the
'none' that means no bound, or 'none' that means the color
meaning of 'none'?
lea: We just need to define precedence. I'd argue for using the color
meaning of 'none', but I don't care too much
lea: Main thing I care about is that 'none' values are not dropped
lea: ChrisL suggests that this is just an editorial change, but
Romain said it's not editorial; hence, running by the group
ChrisL: I no longer think this is editorial. Main thing is preserving
author intent. Coercing none to zero is an option of last
resort if you're literally trying to draw 'none'
ChrisL: Other cases, hue of 'none', does that mean they really want a
bright magenta red? No.
ChrisL: we're seeing people comment on this in implementations,
people complaining about why-are-they-getting-a-red-
arbitrarily
ChrisL: Regardless of the mechanics, the general thing of "we need to
preserve this value unless we can get rid of it" is the main
thing. we can talk about ways to achieve it separately if
needed
<TabAtkins> +1 to preserving none. I think it's probably fine to
treat `clamp()`'s none as the color none in RCS.
<TabAtkins> (Because, as noted, you can always write
`clamp(-infinity, val, infinity)` instead.)
Romain: I was wondering if this is implementable. I assume browsers
have an internal representation of color that's channel
values, but with this proposal you need to preserve much more
information about how the color was specified
Romain: I think this would be very surprising when you move this
across color spaces. When you write: [...]
<Romain> calc(none + 0.2)
Romain: if you write this^ in LCH or oklch, the 0.2 has a different
scale in both. But if you switch color spaces, it gets
preserved and not converted, and that can be surprising
Romain: not an absolute blocker, but does have sharp edges
lea: RE implementability, browsers have to do this with variable
references already
emilio: That's not how variable reference works; they're substituted
before parsing
emilio: You don't have a concept of a calc with variable references;
you have a string with variable references substituted
lea: My point is that not every component actually resolves. Even in
rel color syntax, you keep the values of the base color [??]
<ChrisL> right but you don't have an immediately displayable color
lea: Let's not conflate preserving none in color space conversions &
in calculations
lea: Converting between color spaces is a whole different beast;
that's one of the reasons resolving to 0 was invented
lea: don't want to convert none in a way that exposes color space
conversion math
<ChrisL> https://drafts.csswg.org/css-color-4/#analogous-components
lea: The spec also has a part where if you're converting between two
color spaces, where one component of first color space is
largely orthogonal to the rest and related to a component in
color space b, then swap the none out for zero, and then replace
the none in that component [??]
lea: let's discuss the color space conversion separately; it's hairy
emilio: I agree that preserving 'none' in some way makes sense
emilio: I was going to say something similar to Romain
emilio: When you mix 'none' in more complex calculations... have you
given thought to making 'none' more similar to how NaN works?
as soon as you mix something with 'none', it remains 'none'
instead of being an expression involving 'None'?
<ChrisL> We invented none because the spec said NaN and tab told us
not to :)
emilio: that would be less complex to implement. Interpolating
without having to [...] transforms have such a thing, where
you have to keep them as a mix that isn't simplified
emilio: that seems like a less confusing model, where doing math with
'None' gives you 'None'
ChrisL: That's what the spec used to say; it used NaN explicitly
ChrisL: Tab suggested we use a special value, which is where None
came from
TabAtkins: My argument against NaN was for other reasons, unrelated
to infectiousness
<TabAtkins> (We shouldn't use NaN to indicate "no channel value"
because NaN *also* comes from simple math errors. We
didn't want "author made a math error" to accidentally
also trigger "this channel is powerless and should be
taken from the opposing color". The infectiousness wasn't
a part of this.)
Lea: Infectious none is actually worse than converting it to 0. E.g.
clamp(50, none, 60) is conceptually very different than none,
you're basically saying "I want the component of the other
color, but it needs to be within this range. Converting the
whole component to none in that case could even harm
accessibility, if the constraint was there to e.g. ensure
sufficient contrast.
lea: infections 'none' is worse than converting it to zero
lea: if you have an expression clamping 'none' to 50 or 60, the
author wants it to be in this range
<ChrisL> https://github.com/w3c/csswg-drafts/issues/6107
lea: if you convert the whole thing to none, then that can harm a11y
Romain: This is still related to color space conversion because the
spec says you have to convert to the same color space when
doing interpolation
ChrisL: That's correct, because of missing components
chrishtr: What does calc(none + 20) resolve to?
lea: That's well-defined in the issue. calc(none+20) -- the none
would become the value of that component in another color, and
then you add 20
lea: get the lightness of the other color, and then subtract 20
from it
lea: e.g. if you're trying to interpolate from a certain color to a
darker version of it, regardless of what color you're starting
with
chrishtr: So that means zero is not the right number, in those
use-cases
<ChrisL> So setting hue to calc(none+180) gives you the complement of
the other color, when interpolating for example
lea: Correct, zero is almost never the right number
ChrisL: I've got a suggested resolution for what we want to achieve,
it sounds like we have consensus on that?
ChrisL: "don't get rid of none and replace it with zero unless you
absolutely have to, e.g. if you're forced to use it as a used
value"
lea: That might be all we need?
emilio: I agree
<lea> I wonder if implementations could even internally rewrite to
RCS, in some ways it's like a late-resolving RCS
emilio: I sort of want to review the proposed changes with more
detail; the details of how you do that might be a bit tricky
lea: Proposed: None is preserved in calculations involving css math
functions
lea: ...and also when interpolating between values containing 'none'
and values not-containing-none
<ChrisL> +1
RESOLVED: `none` is preserved in calculations involving CSS math
functions
<lea> When interpolating between two none-containing values, the
result is a calc-mix() expression preserving the `none` values
in both values
PROPOSED: ^
<ChrisL> +1
<lea> PROPOSED: When interpolating between two none-containing
values, the result is a calc-mix() expression preserving the
`none` keywords in both values
dholbert: Do we need to cover interpolating between none/not-none?
lea: That's already defined
flackr: I see in the issue description that there's also a proposal
that 'none' resolves to the other component, if the other
component is not none-containing
lea: That's already how none works / what none does
Romain: That's not true; it's not a placeholder for the other
channel. It makes a channel missing
Romain: it's not like the nesting selector where it's a placeholder
for the parent
Romain: This would be a new mechanic. I'm fine with it being a new
mechanic, but we should call it that
ChrisL: That's already in the spec?
Romain: That's related to color components
flackr: I'd like to know what's used in the other end of the
interpolation. Pulling the color from the other end isn't
what authors would expect
<TabAtkins> That is actually intended behavior, yes
flackr: If you're pulling from 2 color values and a none in the
middle, pulling from two color values at the ends isn't what
authors would expect
lea: That's an orthogonal issue and what happens today
Rossen: Objections?
RESOLVED: When interpolating between two none-containing values, the
result is a calc-mix() expression preserving the `none`
keywords in both values
Received on Thursday, 25 April 2024 23:47:17 UTC