- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Tue, 16 Jun 2015 11:23:45 -0700
- To: François REMY <francois.remy.dev@outlook.com>
- Cc: Greg Whitworth <gwhit@microsoft.com>, Florian Rivoal <florian@rivoal.net>, "public-houdini@w3.org" <public-houdini@w3.org>, Shane Stephens <shanestephens@google.com>
On Sat, Jun 13, 2015 at 3:44 AM, François REMY <francois.remy.dev@outlook.com> wrote: > A few additions I would like to see added to the allowed types are : > - "<length-and-percentage>" (accepts "50px", "50%" and "calc(50px + 50%)") Hm, when we were writing it I thought we needed to delay percentages until we got a hookable compute step, because you need to know what percentages are relative to, but I guess you really don't as long as you're okay with handling it in the apply handler, or just using it as a variable. > - "<ident>" (any custom identifier) > - "<ident>(auto, none)" (a list of possible idents which the property does accept) > - "*" (any input, much like a unregistered custom property) Yup, agree with all of these. We should be able to handle the second case with real grammar, like `[auto | none]` > It should also probably be flushed somewhere in the sepc that the "initialValue" should match the given "syntax", of course. Yes, definitely. Should throw if it doesn't match. > ==================================== > [1] It creates a toxic environment > ==================================== > > Give how the "apply" hook is proposed to work, it creates an environment that's so hostile to cooperation between polyfills that I don't see me using it for any of my polyfills. > > Let's say I create a polyfill for the "size" property which is a shorthand for both "width" and "height". That means that no other polyfill can touch those two essential properties anymore. Ditto for any polyfill which wants to handle "transform". Polyfills are going to conflict with each other all the time, making them unusable outside contained demos. That's not sustainable. I'd be very interested in hearing *how* you think polyfills are supposed to coordinate. Seriously, we have no idea how it's possible to coordinate between properties without the scripts explicitly knowing about each other. There's a killer ordering problem that you can't solve without either (a) the stylesheet author specifying an order they run in the stylesheet, or (b) the scripts coordinating with each other. You can, of course, fairly trivially write a coordinator that takes several apply hooks in order and generates a combined apply hook for all of them. Just union their input and output properties, then run them in the passed order. You need a fake output object that masks the inputs for the following hooks, which is the only non-trivial part, but even that should be pretty easy. (Trivial with proxies, but possible without them.) If we use Map-style objects rather than property-bag style, it gets even simpler. Having the spec provide such a coordinator might be possible, of course. > I'm not sure why you state the polyfills are unlikely to modify native properties. Polyfills have literally no other option than setting the value of native properties to have an effect on the page, I expect most polyfills to actually work this way, and not by going the full Custom Layout road. Sure, things like my CSS Grid polyfill would benefit from Custom Layout but I can see how more lightweight tweaks could simply perform style rewrite to map a new syntax to an older syntax after having applied a bit of magic. This is mostly what my current Grid polyfill does, and it's almost powerful enough so I suspect smaller additions could find it sufficient. Custom Paint/Layout are massively more powerful and performant than tweaking existing properties, so when they exist, I expect they'll be used pretty exclusively for the things they're designed for. Without Custom Layout, for example, you can't be auto-sized, and children provide less sizing info with more difficulty. Without Custom Paint, you can't be told what size you're drawing into, or told when it changes, or hook into the painting cycle properly. > ==================================== > [2] It is insufficient to mimick css properties > ==================================== > > Florian's 2.1: >> 2.1) For some properties, but not all, the computed value depends not >> only on the computed value of other properties on the same element (as >> expressed by inputProperties), but also on the parent element. > > To restate Florian's 2.1, a fair amount of usefule css properties don't live on their own. Sure, on one hand, a lot of those are affected by the layout phase (which we could arguably leave to Custom Layout), but on the other hand, even properties which do not have a "layout-computed used value" can depend at computation-time on parent state in a non-"inherit" way. Think, for instance, about "justify-self": the ‘auto’ keyword computes to [...] the computed value of ‘justify-items’ on the parent [...] or ‘start’ if the box has no parent. Yeah, we accept this. We already have some notion of dealing with children's values; we just need to figure out how we want to care about parent's values. > ==================================== > [3] Transitions seem to conflict with the model > ==================================== > > One of the goals of "typed custom properties" is to get transitions working on those custom properties. > > Now, I fail to see how we hope to see this working in addition to the "apply" model. Here's why: > > Let's say we have a hook computing "--both-numbers" to the sum of "--first-number" and "--second-number" (if both are specified) or computing "--first-number"/"--second-number" from "--both-numbers" (if one of them is missing)). Now, imagine that a transition starts on hover: > > element { --first-number: 0; --second-number: 1; transition: really-all 1s; } > element:hover { --first-number: 0; --second-number: 2; } > > Since the css engine cannot know how "--both-numbers" is computed, he has to call the "apply" model on every step of the transition. Don't gender the CSS engine, that's weird. ^_^ It's inanimate, and so "it" is the correct pronoun. Anyway, it'll know at least some of how the properties are handled, because you'll have an apply hook with all three properties as both input and output. > How will the css engine know whether the computed value for "--both-numbers" should or should not transition normally after the "apply" model is run? I may be wrong, but it seems impossible to know, which means it won't transition (however, since "--first-number" and "--second-number" do transition and the "apply" logic is called again at every step, it will looks in this specific case like it does transition, which is great). The apply hook is *after* computed values; the (currently unhookable) compute handler is the only thing run before transitions. So in this case --first-number won't transition, but --second-number will, and then (since one of its inputs changed) the apply handler will run and set --both-numbers appropriately. > Now, the issue happens when you need to handle the real final value of the properties to compute the final value of the computed property, and you want this property to transition normally between those two extremes. This is the case for instance, you set a flag that changes the meaning of some other property, but want the effect of this flag switch to happen gradually (example: a grid where items would move from their old to their new grid area in a transitioned way and not directly like we do now). Since you don't know how far you are in the transition, that's not possible. Hm, good point. Passing in transition information to the apply handler might be useful. > Regardless of whether we want to support this, clearly, we have now put the burden of managing transitions to the "apply" model but the "apply" model doesn't know about transitions which make things very hard. This is why I proposed to use a "StyleTransitionController" model in the past for this purpose (since I've given some more thoughts on the matter since then I'm going to restate what I mean by this hereafter, but you can have a look to http://lists.w3.org/Archives/Public/public-houdini/2015Apr/0007.html for historical notes and context). My goal is to support transitions from and to custom types, but more importantly to make sure property polyfills can easily cooperate by default, something I don't see provided in the "apply" model and which looks out-of-scope in the "Custom Layout" world. > > The model I propose would work as follows: > > > > ====================================== > [1] Registration phase > ====================================== > > [1.1] In any order, JavaScript code registers Custom Properties declarations just like proposed in this spec. Those declarations are not JavaScript-related, and only affect the CSS Parser/Cascader. > > [1.2] In any order, Javascript code registers StyleMutationObservers for a set of css properties he's interested in (aka "inputProperties"). Those will serve to create instances of the StyleTransitionControllers once required (but I can see other use cases for StyleMutationObservers which do not require tweaking the style any further, like building querySelectorLive or a polyfilled touch-action property). > > [1.3] In First-In-Last-Out order*, Javascript code registers StyleTransitionControllers types (=DOMString identifiers) which will be used to ensure the StyleTransitionControllers are always executed in the same order on every element, regardless of when they are actually registered on the elements themselves. It can also be used to ensure one and only one of each type of StyleTransitionController is ever attached to a single element. Registration order doesn't work; it means that async scripts cause race conditions. If two things affect the same properties, and have to run in a particular order to work properly, then it might run correctly most of the time on one computer due to network conditions, but fail in production. ~TJ
Received on Tuesday, 16 June 2015 18:24:36 UTC