- From: Dael Jackson <daelcss@gmail.com>
- Date: Wed, 26 Dec 2018 17:51:31 -0500
- To: public-houdini@w3.org
- Cc: CSS WG <w3c-css-wg@w3.org>
=================================================
These are the official Houdini Task Force
minutes. Unless you're correcting the
minutes, please respond by starting
a new thread with an appropriate subject line.
=================================================
Typed OM
--------
- Resolving values with external information (Issue #798) needs more
time to develop a full proposal.
- The plan is to drop CSSPositionValue from the first level unless a
solution is found for representing positions. (Issue #817)
- A single value when a list is appended will be handled by silently
dropping the single value and making it a list. (Issue #823)
- RESOLVED: Make TypedOM compatible with future Array-like plans,
per issue #825.
Layout API
----------
- There were concerns that the solution for float representation and
rounding to fractional units could be fragile and have problems,
for example, due to differences in rounding and representation
within the layout engine or pixel-snapping (engines try to ensure
certain lengths, such as border widths, resolve to the same
number of pixels given the same abstract length). Google will
experiment with their implementation to see if there are
problems. (Issue #830)
===== FULL MINUTES BELOW ======
Agenda: https://github.com/w3c/css-houdini-drafts/wiki/TPAC-F2F-October-2018
Scribe: heycam
Typed OM
========
Status Update
-------------
https://github.com/w3c/css-houdini-drafts/issues?utf8=%E2%9C%93&q=+is%3Aissue+label%3AAgenda%2B++sort%3Aupdated-desc
TabAtkins: I want to get a bunch more work on this done before next
meeting
TabAtkins: More significant updates in the near future
TabAtkins: We have some impl internally again, brought up some
interesting issues
Resolve values to a px with external information
------------------------------------------------
https://github.com/w3c/css-houdini-drafts/issues/798
TabAtkins: If all of the units you have in a math value are
compatible with pixels e.g. then you can always resolve
them to a single px
TabAtkins: If you have combinations of values that aren't directly
resolvable, there's no way to resolve them
TabAtkins: since the custom layout API works mostly in px values, it
would be useful to give people more direct control over
how they can simplify them down to px
<TabAtkins> https://github.com/w3c/css-houdini-drafts/issues/798#issuecomment-415555133
TabAtkins: So we add an options bag to the to() and toSum() functions
TabAtkins: giving extra information for resolving the values
TabAtkins: In particular, the element being resolved on (for ems
etc.), the property it's on (so font-size can properly
resolve to parent element), and what a % should resolve to
TabAtkins: Going with this explicit % resolution thing to avoid some
problems with some properties resolving %s against
different sizes
TabAtkins: This makes it more explicit with cases like the layout
API, where you have an available space, and you can just
pass that in rather than finding a property to pretend
it's being resolved as
TabAtkins: I think that lets us resolve all the units
TabAtkins: In particular, a comment further down suggests that we
don't have a default value, so if you don't pass an
element, resolve like MQs do, with no context
TabAtkins: Right now, if you call to() without this information and
it needs it, it throws
emilio: The layout API doesn't have access to any element, right?
TabAtkins: Yes
emilio: Can we instead pass what the function depends on explicitly?
what's the expected thing if you pass an element to there, I
assume you have to do style updates etc.?
emilio: What happens if that element's not in the flat tree etc.?
emilio: Would be nice to be more explicit about which data you're
depending on
emilio: then people can use the no context thing without having magic
TabAtkins: There's a lot of information. which font's being used.
it's possible to enumerate this
emilio: Instead of getting a font and doing font matching, you may
as well .... I guess there's no way to get ex height without
script
TabAtkins: A possibility is to allow you to pass an element, but
also enumerate all the things that the various relative
units can depend on
TabAtkins: and if you don't pass a unit, that's the info you have to
work with
TabAtkins: and if you use a unit but no way to determine what that
is, continue to throw
emilio: If you need to download fonts to make this work...
TabAtkins: That's what we have to do
emilio: Normally you wait for a computed value, which triggers all
that
emilio: That only happens if you actually lay out the element
TabAtkins: And the assumption here is you are doing something
layout-y but not with an element
emilio: Let's say you call this function from a layout worklet with
a given font
TabAtkins: Does the layout trigger the font load somewhere?
TabAtkins: Good question
TabAtkins: Possibly
emilio: Does it do it sync? probably not
emilio: You can't make it sync
TabAtkins: I think then we should remove the element resolver,
figure out what relative units we can easily resolve on,
e.g. asking for font-size, other font relative ones are a
bit hard for now
TabAtkins: and then if you try to use an ex unit to px, we just throw
TabAtkins: Then we can remove the property too
fremy: If you still want the behavior to pass an element, you can
have another element, and it returns the properties you would
fill in
TabAtkins: One of those dictionaries
dbaron: I'm not convinced you can remove the property
dbaron: If you're doing it from the element, you still need to know
font-size / line-height behave differently for em and lh
units
TabAtkins: I'm suggesting that just like the 100% line, where you
explicitly indicate what the resolves to, you just supply
what them resolves to
TabAtkins: and then also supply a function that can extract that
from an element automatically
fremy: CSSNumericValue -- is that calc or more stuff?
TabAtkins: Everything
fremy: Can just create a 1em and call to
emilio: Layout API functions could need 1vmax, you need to expose
viewport size to those functions
emilio: not sure if you want to?
<dbaron> The function to extract from an element automatically would
need a property.
iank: No access to viewport info
iank: It's not necessary
iank: The side effect of exposing that info is that when you resize
that viewport, you'd need to call every layout function
iank: since it's a side input
TabAtkins: This would be an implicit dependency
TabAtkins: unless we made it explicit somehow
fremy: We could add a function in the worklet, before calling it
viewport sizes are 0, and only after you can use it...
TabAtkins: We have a case for later registrations of dependencies
iank: Probably you want to do this in the layout registration
dictionary
iank: You don't know which global scope you're doing to run it in
fremy: The other option is to create custom properties that would be
1vmin, etc., type them to be lengths, then you'll get the
value
fremy: it's a bit handwavy but it does work
iank: If this becomes a common pattern, in layout options, say that
resolve vw/vh against the real thing
iank: but part of the precedent for resolving to 0 is what happens
when you set a font-size in an offscreen canvas context, it
resolves to 0
TabAtkins: That's different from how MQs work
iank: Not saying that's good or bad but that's the precedent
TabAtkins: I think that's all the feedback I need; I will come back
with a more mature proposal in the future
Drop CSSPositionValue
---------------------
github: https://github.com/w3c/css-houdini-drafts/issues/817
TabAtkins: CSSPositionValue was in the first draft
TabAtkins: Assumes every position is a horiz/vert offset
TabAtkins: Now they can be logical
TabAtkins: Not certain how best to represent this flexibility in the
object shape
TabAtkins: until I do I plan to drop it from the draft and impl
TabAtkins: If anyone has ideas for representing these values would
love help
astearns: There have been a number of things we've dropped
astearns: Are we tracking those in any way?
astearns: Next level draft?
TabAtkins: I shall soon
TabAtkins: We did a publish a while ago, need to do another one soon
TabAtkins: Before EOY I'll get ready for a new draft
TabAtkins: and I'll have a substantial changes section to outline
what happened
Clarify list-valued properties
------------------------------
github: https://github.com/w3c/css-houdini-drafts/issues/823
TabAtkins: This was brought up by one of our engineers
TabAtkins: I was hoping at the start this issue wouldn't occur. I
was hoping to split props into list values and single
values
TabAtkins: every prop would be one or the other
TabAtkins: anders pointed out we have several props that at minimum
have a neutral value, but sometimes have more than that
TabAtkins: and the list value / single value split is not enforced
in custom props either
TabAtkins: You can always define [ length+ | number+ ]
TabAtkins: Not handling that well
TabAtkins: So rather than declare props to be list valued or single
valued, declare top level productions as being list
valued or single valued in a given prop
TabAtkins: e.g. content
TabAtkins: Some of the productions will be single valued, and they
can't be used with the append() methods
TabAtkins: Some are multi-valued, and can be used with the append()
methods
TabAtkins: and if you do the wrong one, and you call
styleMap.append("counter-reset", "none")
TabAtkins: I believe we'll throw in that case
TabAtkins: One thing I'm not sure is how to handle the case where
it's currently a single value, and you append a list
production
TabAtkins: e.g. it's currently set to none, and you want to append
real values
TabAtkins: The most common case is none, I'd like that to be easier
to handle
TabAtkins: So I'd like to make that silently drop the single value,
and turning it into a multi-value production instead
TabAtkins: Not sure about this, may be more consistent to throw here
TabAtkins: I believe this design in general, is the way to go to
handle all possible props properly
TabAtkins: It's not a significant complexity increase
TabAtkins: It'll be a bit more work continuing we need to make sure
they're properly tracked
heycam: What if we change a property from single-value length to
multi-value length?
TabAtkins: In that case the original length would be classified as a
multi-value
heycam: So in the updated property that would be defined as a
multi-value thing
TabAtkins: So let me know if you have opinions on this
TabAtkins: Otherwise I'll resolve it like this and edit it in
fremy: How you define that syntax, how would you write down your
declaration to say this is single valued or list valued?
TabAtkins: CSS in the specs will define this
TabAtkins: Don't have to do that in the API side
fremy: For custom properties
TabAtkins: Right now, custom props are either a single value or
there's a + in there
TabAtkins: but once we had the # one, those will be multi-valued
Figure out Array-likes
----------------------
github: https://github.com/w3c/css-houdini-drafts/issues/825
TabAtkins: So Typed OM has had a handful of array-like interfaces
since the beginning
TabAtkins: Been clashing with Anne and Domenic on how to handle these
TabAtkins: Last week Domenic and I sat down to look at plausible
future plans
TabAtkins: for array-likes in the future, it should indeed be an
Array subclass
TabAtkins: So Array.prototype stuff works, Array.isArray works
TabAtkins: and then at some point, either as just a spec concept, or
possibly as an author facing API, there'll be a way to
hook get/set indexes
TabAtkins: Although they look like data properties, there is still
some magic
TabAtkins: that intercepts a get/set so it can update length
TabAtkins: just set
TabAtkins: Nothing specwise that stops us using that hook
TabAtkins: This has some implications for the array-likes in typed OM
TabAtkins: In particular, there are 3 arrays-likes -- CSSMathArray
TabAtkins: It's declared to descend from CSSStyleValue
TabAtkins: It's the array that hold calc arguments
TabAtkins: Could switch this over to a new Array subclass
TabAtkins: The other two, CSSUnparsedValue -- for representing
var()s -- and CSSTransformList -- which reps transform
lists
TabAtkins: both are array-like and you can array index them
TabAtkins: There's are directly useful as values you can set to
properties, so can't change them from being CSSStyleValue
TabAtkins: Probably then we'll move the segments / functions to a
property hanging off them, make them array-likes that
inherit from Array
TabAtkins: and have hooks that do type checks to ensure only
transform functions etc. are set
TabAtkins: In anticipation of this working later on, these will
still have getter on them for now
TabAtkins: When we do switch to the real model, worked out in IDL,
we can just remove that and there'll be very little if
any behavior change
bz: Have you talked to JS engine implementors about this?
TabAtkins: I talked to domenic and adam klein about this
bz: In particular the idea of generically hooking set on arrays
they're ok with?
TabAtkins: We can do this right now
bz: Sort of
bz: It's very very special cased for length updates
bz: In the TC39 spec handwaves it
bz: In impls for performance ...
TabAtkins: So they wouldn't be naked Arrays with magical behavior
TabAtkins: Right now indexed setters get the same array-looking
thing and they are optimized (not quite as good as naked
arrays)
bz: So you would be modifying Array.isArray to do something here
TabAtkins: Yes
bz: And deal with subclass construction bits
TabAtkins: domenic has some feedback in TC39 for this
fremy: One question. the segments array in CSSUnparsedValue would
not be read only?
TabAtkins: It's not currently read only
TabAtkins: It only takes strings and var references
TabAtkins: We'll continue doing type checking to make sure other
values aren't set in there
andrew: You don't want to make the transform components subclasses
andrew: They have to descent from array
andrew: What do we do for values we return?
TabAtkins: CSSTransformList remains a CSSStyleValue
TabAtkins: but it has a prop that is an array-like
andrew: If you register a prop with that syntax
TabAtkins: Transform functions are CSSStyleValues as well
TabAtkins: The list inside it
andrew: ok, misunderstood
fremy: If we have the segments thing, it's better
fremy: but there is still the case for when you upgrade
CSSUnparsedValue to another thing
fremy: You should not break the compat
fremy: If right now we don't have a position thing
TabAtkins: No, unparsed value is not the generic value class
TabAtkins: that's CSSStyleValue
fremy: CSSUnparsedValue is only for var?
TabAtkins: Yes
bz: What are the semantics of setting .length on these things?
TabAtkins: Still a great question
TabAtkins: Not 100% sure, but more than likely I'll decide it's fine
to have undefined/holes
TabAtkins: and those are ignored
fremy: In the meanwhile can't we use a normal Array with no checking
fremy: Well it's not compatible with you switch
bz: Code that used to work will start throwing exceptions
TabAtkins: This is detailed enough to know what the direction will
be. Let me know you thoughts
RESOLVED: Make TypedOM compatible with future Array-like plans, per
#825.
Layout API
==========
Precision and rounding in layout API
------------------------------------
github: https://github.com/w3c/css-houdini-drafts/issues/830
iank: I wanted to write down the problem clearly
iank: As specced now, with availableInlineSize: 10.13, the internal
representations in each engine will be different
iank: I believe Blink/WebKit will be 10.125, Gecko will be 10.133,
Edge will be 10.13
iank: Similarly, say that child is auto sized, the value that you
will get out in JS will be 10.125 for Blink/WebKit, some ugly
values near 10.33333 for the others
iank: This is exposed right now
<dbaron> Some of the ugliness is something that we could fix (by
going directly from fixed-point to double rather than
fixed-point to float to double)
iank: If you set width:10.13px on an element, and you call
getClientRects, you will get similar issues
iank: Part of me thinks this is a non-issue
iank: The thing I worry about with rounding is that you'll get
potential tearing
iank: Imagine if you're doing a flexbox-like thing
iank: where you're distributing available space between children
iank: With the current API you won't get any subpixel tear, but if
you round inputs and outputs you will
iank: You'll have to define the whole layout tree working on rounded
precision mode
eae: When you say rounding, you mean rounding to ints or to these
values?
iank: If you round to int values, going in and out of the engine,
you might see tearing
iank: If you're distributing some fractional space in a flexbox-like
thing you can't do that
iank: Also you'd need to specify the whole subtree works in rounded
int precision
smfr: What do you mean by tearing?
iank: If you try to position the two fragments side by side, you'd
get a gap
iank: Similarly, the second class there is if you happen to be
distributing some space that wouldn't get a gap, the element
might be smaller
bz: To be clear, the container being smaller than the elements is a
problem anyway
bz: Even with floats
iank: The conversion to the JS float thing, it's still possible to
get tears accidentally
iank: but because the JS repr is high enough, converting from the
internal fractional to JS to the internal fractional will
result in the same fractional value
chrishtr: What about pixel snapping?
iank: We only do that at paint
iank: We don't pixel snap any of the layout
TabAtkins: Yes we do
TabAtkins: border widths e.g.
eae: Borders are very special
emilio: Device pixels
dbaron: There's a small class of things where you care about the
with of the thing being the same across repeated occurrences
dbaron: Borders, column rules, probably line heights as well
dbaron: but for most other things we don't do internal snapping
dbaron: You round to internal repr then snap edges to the nearest
pixels
iank: The pixel snapping borders we can repr that value in the
LayoutEdges object
bz: Presumably this is snapped to dev pixels here
iank: Yes
chrishtr: Blink currently snaps to CSS px
eae: Not really
chrishtr: In cases where the device pixel ratio is incorporated into
zoom it's device pixels
chrishtr: long term intention is to use device pixels
smfr: Someone mentioned pixel snapping in border would happen at
layout time? isn't purely a paint time operation?
dbaron: For us it's a computed value time thing
Rossen: For us it's also style
Rossen: It matters for lower values, 1, 2, 3, px
Rossen: but over 13, 14px it doesn't really matter
dbaron: But it does matter for not getting the 1px gaps that you do
the snapping before the layout calcs based on it
dbaron: If you do layout calcs based on a non pixel snapped border,
then snap it later, you'll sometimes get 1px gaps or overlaps
Rossen: So we'll do the layout with fractional border sizes
Rossen: then snap during paint
dbaron: But you need to snap all the things next to that border
during paint too or they won't line up
Rossen: No they won't
dbaron: Then your system is different in more complex ways from ours
chrishtr: Is the intention to spec the rounding?
iank: No
chrishtr: Or just things that UAs may do?
iank: My preference is to allow the UA to do internal rounding to
the fractional repr and back
iank: Main thing I want to avoid is the 1px tearing in layouts
chrishtr: It should at least be said if the left/right edge of
things are the same number, there should not be a tear
eae: Can probably find a way to spec that
chrishtr: You'd have to say the rounding and layout is the same, and
that pixel snapping at paint time preserves that
consistency
iank: Yep
Rossen: Does that work for you Simon?
smfr: Yes I think so
smfr: WebKit does some snapping of border widths as well
smfr: I'm trying to understand when you're laying out fragments
iteratively, does the browser tell you how much space is left?
A floating point input
smfr: with custom layout, call layoutnextfragment 3 times
smfr: each time an input is the remaining space?
iank: No you need to do that yourself
iank: So you'll have some available size, layout first child,
subtract the size of it in the JS double
smfr: Was concerned about the conversions between JS doubles and the
quantized values internally
iank: Since it's handled by script it's always the JS doubles
smfr: Trying to think of cases where the rounding would hurt you
smfr: Maybe combining custom paint and layout
smfr: you ask for a certain with with double precision
smfr: then in paint ...
iank: I think previously you've brought up trying to fit into the
one fractional unit, and some engines will leave a tiny
fractional unit over
iank: In one you go into the next line, in another you'll have a
skinny box for some reason
iank: I think it's a super edge case
fremy: My impression is that the only case where this could be an
issue is where you do the data sharing between custom layout
fremy: You could share with full precision, and on the other side of
the API you'd get it
fremy: but I also don't expect this to be a problem
<TabAtkins> Found that the internal->JS->internal conversion is
always accurate up to (10^15)px; at 10^16 there's a few
rounding errors with Microsoft's precision.
<TabAtkins> http://software.hixie.ch/utilities/js/live-dom-viewer/saved/6318
<astearns> you can just add a flag in Blink to use 1/60 or 1/100
internally
<bkardell> astearns are you suggesting google could add that
capability or saying that it already exists?
<astearns> ian said he did it just now :)
<eae> bkardell/astearns it does not exist but we could potentially
do it as an experiment.
smfr: As a data point, this same problem also happens in media
timing values
smfr: Currently they're all floating point, but there've been
discussions about turning them into a rational type
smfr: They're trying to solve some similar way here
iank: I think there's been talk in JS previously about having value
types
TabAtkins: They're not ready yet
iank: They've been vapourware for a while
iank: but the intention would be to work in that fractional type
iank: We shouldn't depend on that
iank: Could imaging a future where JS does get that fractional type,
see if it's compatible to change to that
iank: or otherwise add an option to opt in to it
fremy: This transformation is a rounding
iank: It's a rounding to the fractional representation
fremy: Can we floor rather than round?
fremy: Otherwise if you divide by 7, all your 7 column objects, you
give them avail size / 7
fremy: then you have a layout where each gets the size they can. if
each is rounded up, the sum will be bigger than 100% and
you'll wrap
fremy: Better to floor
fremy: You make sure the sum will all fit
TabAtkins: Flooring starts loosing this internal -> JS double ->
internal relationship more quickly
eae: You can have a situation where you have a lot of space at the
end
eae: which is also not desirable
fremy: People writing the layout will pay attention to this
smfr: Has anyone tried using the prototype to see if it's a problem?
fremy: The prototype is only in one browser
smfr: Still possible to make layouts with hairline gaps
fremy: I've not tried but I guess it's possible
iank: We can see if people run into it
iank: so far surma and fremy haven't run into it
smfr: Your masonry layout wasn't trying to fit something into
something with a border, not obvious there's a gap
iank: We can experiment with prototypes with borders to see if we
can get hairline gaps
fremy: Grid has the opportunity to have these options, but you can
position things at particular points, no wrapping
fremy: Even with 7 column grids, you place them before sizing, so it
doesn't matter
fremy: We should try the flexbox-like thing
iank: I think the action item on us is to play with our impl to see
if we can break
iank: but sounds like people are relatively fine with the float
representation and rounding to fractional units internally
iank: We can report back to the group
<br dur=1hr>
Received on Wednesday, 26 December 2018 22:52:28 UTC