-
Notifications
You must be signed in to change notification settings - Fork 672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[selectors-4] Add syntax to establish before-change style for css-transitions on new elements. #8174
Comments
I filed #8175 to talk through this particular area separately. |
It could work if :initial is matching if an element had no style (first frame or display:none) before the element style recalc is done for an element and reapply without :initial immediately. I'm not 100% sure about the consequences where we are looking at multiple passes like for container queries. Whether a multi-pass layout is stateless. Since the before-change style would be based on the previous frame's style, or perhaps the :initial based styles, we probably just need to have a single :initial style pass even if the style would flip back and forth between display:none for the same update. |
Rather than thinking terms in of "frames", it could make sense to express this as a way of bringing into existence a before-change style when there otherwise would be none. It could work like this:
|
@ANDUUD It's a really compelling idea to do this just in time for starting transitions, if it helps. Whether to start a transition also seems to depend on the before-change transition duration (demo) though it's unclear from the spec whether this is right. Anyways, in this case we would always have to calculate the initial style, so does it still make sense to do this if it will happen for every element? Also, will this support combinator selectors from :initial? |
@flackr That demo has a mistake which makes it seem like the before-style matters (for the transition properties), but it actually doesn't (fixed demo, the difference is the
Right ... so e.g. does |
Yup! That's great! So we'll only need to do this when we have a non-zero transition duration making this a good optimization.
Yes, this sounds perfect. I think it's reasonable to require |
The CSS Working Group just discussed The full IRC log of that discussion<fantasai> Topic: Pseudo-class before-change style for transitions on new elements<Rossen_> q? <fantasai> github: https://github.com//issues/8174 <fantasai> flackr: when coming from display:none have no display style <fantasai> ... so can't define a from state <fantasai> ... can define in CSS animation, but less ergonomic <fantasai> ... so proposing we add an :initial pseudo-class which establishes the initial style <fantasai> ... the before-change style for CSS transitions <fantasai> ... in discussion, decided that if we made this a pseudo-element <chris> rrsagent, here <RRSAgent> See https://www.w3.org/2023/01/11-css-irc#T17-10-12 <fantasai> ... we could optimize this by preventing e.g. sibling selectors and only require occasional style calculation when it's used <fantasai> ... so proposal is to have ::initial establish the initial style <emilio> q+ <Rossen_> q? <Rossen_> ack emilio <fantasai> emilio: This would be a pseudo-element that matches against an element? <fantasai> emilio: so matches element rules plus magic pseudo-element? <fantasai> pseudo-element would be applied on top of element rules <fantasai> emilio: that's pretty different from pseudo-element <fantasai> emilio: I don't think we have a precedence for this, which is a bit tricky <fantasai> emilio: I'm also confused when you want it <fantasai> emilio: this is for coming back from display:none? <fantasai> emilio: seems implementable, but seems tricky and weird to make it a pseudo-element <fantasai> emilio: because targetting two element styles on one <fantasai> emilio: weird wrt cascade <fantasai> flackr: that's good feedback for pseudo-element approach <fantasai> flackr: could also take pseudo-class approach, but less easily optimizable? <fantasai> emilio: in what sense? <fantasai> flackr: if you have combinator selectors, element showing up in the DOM can cause recalcuation <fantasai> emilio: but that's the case for all pseudo-element <fantasai> flackr: this is extra style recalc that doesn't normally exist <fantasai> emilio: I'm a bit confused, you recalc more if you have :initial along the combinators.... depending how wel you optimize <fantasai> flackr: I think given :initial is only establishing before-change style and otherwise doesn't apply to the element, not that weird that it conflicts with other styles <fantasai> flackr: because those other styles can't initiate transitions from display: none <fantasai> emilio: we have a similar case with pseudo-classes for links <fantasai> emilio: need to resolve :visited / :unvisitied, need to do unconditionally, but dont' understand why :initial would be slower <fantasai> flackr: if initial is a pseudo-class, can be used as part of combinator selectors <fantasai> flackr: so have to resolve all those combinators <fantasai> flackr: but if pseudo-element, can't be used in those combinators <fantasai> emilio: for :visited we have special case <fantasai> emilio: basically :visited on left of sibling is ignored <fantasai> flackr: ah, we could do that <fantasai> emilio: the way I think of implementing it is, we have this element ... <fantasai> emilio: otherwise :initial only matches rightmost compound <fantasai> flackr: that sounds reasonable to me <fantasai> emilio: that would be less weird <futhark> q+ <fantasai> +1 to emilio <Rossen_> ack futhark <fantasai> futhark: ignoring the pseudo-class, when resolving selectors, would have already computed style for previous one so would have eixsting computed style <fantasai> futhark: so :initial wouldn't match on those elements <fantasai> emilio: Right. :initial can only match in this special case <fantasai> emilio: "this element is now :initial", now compute <fantasai> emilio: with :has() have similar dependency... <fantasai> futhark: Similar if getComputedStyle() in display:none subtree <fantasai> futhark: You need to ensure you have styles there to do inherit etc. <fantasai> emilio: not for siblings, but for ancestors <fantasai> emilio: I'd rather say that it only matches on the rightmost <flackr> +1 <chrishtr> +1 <fantasai> fantasai: How does this interact with page loading, partly loading? <fantasai> flackr: applies anytime the element first gets a layout box <emilio> q+ <fantasai> flackr: this would apply any time you add element to a page <fantasai> flackr: separate issue for avoiding running things during load <fantasai> flackr: but this is pre-existing problem for animations, which run on page load <fantasai> Rossen_: So based on description, this would not fire on display:contents ? <fantasai> Rossen_: since it doesn't have a box? <fantasai> flackr: that sounds right <Zakim> fantasai, you wanted to ask how this interacts with loading <Rossen_> ack fantasai <Rossen_> ack emilio <fantasai> emilio: I think I'd rather special-case it to display:none since that's the actual thing <PaulG> q+ <futhark> +1 to emilio. <fantasai> emilio: at least, I don't think display:contents stops animations in the subtree, whereas display:none does <Rossen_> ack PaulG <fantasai> PaulG: If we're leaning towards pseudo-element, how would that affect AX tree? <fantasai> PaulG: if not supposed to be animated at that time, just want to make sure we consider that <fantasai> flackr: don't think we're leaning towards the pseudo-element approach <fantasai> flackr: but not intenteded to establish a separate elmeent, just style the real element in the before-change state <Rossen_> ack fantasai <fantasai> fantasai: Suggest maybe flackr and emilio can come back with a revised proposal, and we can move to other issues <fantasai> flackr: fwiw, AX should be equivalent to animations <fantasai> Rossen_: ok, let's end here <fantasai> Rossen_: come back when you're ready, thanks for introducing |
What does |
APA would want to ensure that any pseudo-element creation (especially in a live region) preserves the current patterns for updating the AxTree and doesn't lead to "double reads" by assistive technology. |
:initial is only used as the before-change style of a transition. So |
@emilio Per the discussion, the new proposed resolution is the original one with your proposed restrictions:
|
My issue with this proposal is that this is designed around browser engine internals rather than concepts web developers understand. Not sure the definition of "initial" will be easy to grasp for web developers. My gut feeling is that the spec should be rewritten in a way where the following "just works", since that is what I think most web developers will expect.
I don't think:
is more explicit than:
nor it is much shorter to write. |
My initial reaction to the issue was that maybe this should be solved with a CSS property + at-rule (like scroll-linked animations for instance), but I realized we could already do this with |
If we could make this work, it would still only work for content which was already in the DOM in a previous state. E.g. I couldn't create an entry transition for a dialog which was just added or had never had style computed before.
Could you write an example of what you're thinking? Or is it basically animation keyframes?
You are absolutely right that with |
:initial as a pseudo class instead of ::initial pseudo element also means we have issues with :is/:where etc: <style>
:is(.a, div:initial, .b) {}
</style>
<div></div>
<div class="a"></div>
<div class="b"></div> Implementations would typically stop matching when a matching selector is found. If :initial is allowed inside :is/:where we would have to match all to detect if the extra before-change style needs to be computed. If we keep :initial as a pseudo class, I think we should add further restrictions to where :initial matches to avoid having to do unnecessary matching to detect presence of :initial styles. |
Agenda+ to propose resolving on the behavior described in this comment. |
This isn't part of the landed spec [1], and will be replaced by a combination of these five CSSWG issues: - w3c/csswg-drafts#4441 - w3c/csswg-drafts#6429 - w3c/csswg-drafts#8174 - w3c/csswg-drafts#8189 - w3c/csswg-drafts#8389 After this CL, you will no longer be able to animate your popover like this: ``` [popover] { opacity: 0; transition: opacity 0.2s; } [popover]:open { opacity: 1; } ``` Instead you'll need to use CSS animations or (eventually) transitions and you'll have to explicitly declare the `display` and `top-layer` properties: ``` transition: opacity 0.2s, display 0.2s, top-layer 0.2s; ``` [1] https://html.spec.whatwg.org/multipage/popover.html Bug: 1307772,1413556 Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
This isn't part of the landed spec [1], and will be replaced by a combination of these five CSSWG issues: - w3c/csswg-drafts#4441 - w3c/csswg-drafts#6429 - w3c/csswg-drafts#8174 - w3c/csswg-drafts#8189 - w3c/csswg-drafts#8389 After this CL, you will no longer be able to animate your popover like this: ``` [popover] { opacity: 0; transition: opacity 0.2s; } [popover]:open { opacity: 1; } ``` Instead you'll need to use CSS animations or (eventually) transitions and you'll have to explicitly declare the `display` and `top-layer` properties: ``` transition: opacity 0.2s, display 0.2s, top-layer 0.2s; ``` [1] https://html.spec.whatwg.org/multipage/popover.html Bug: 1307772,1413556 Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
This isn't part of the landed spec [1], and will be replaced by a combination of these five CSSWG issues: - w3c/csswg-drafts#4441 - w3c/csswg-drafts#6429 - w3c/csswg-drafts#8174 - w3c/csswg-drafts#8189 - w3c/csswg-drafts#8389 After this CL, you will no longer be able to animate your popover like this: ``` [popover] { opacity: 0; transition: opacity 0.2s; } [popover]:open { opacity: 1; } ``` Instead you'll need to use CSS animations or (eventually) transitions and you'll have to explicitly declare the `display` and `top-layer` properties: ``` transition: opacity 0.2s, display 0.2s, top-layer 0.2s; ``` [1] https://html.spec.whatwg.org/multipage/popover.html Bug: 1307772,1413556 Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
This isn't part of the landed spec [1], and will be replaced by a combination of these five CSSWG issues: - w3c/csswg-drafts#4441 - w3c/csswg-drafts#6429 - w3c/csswg-drafts#8174 - w3c/csswg-drafts#8189 - w3c/csswg-drafts#8389 After this CL, you will no longer be able to animate your popover like this: ``` [popover] { opacity: 0; transition: opacity 0.2s; } [popover]:open { opacity: 1; } ``` Instead you'll need to use CSS animations or (eventually) transitions and you'll have to explicitly declare the `display` and `top-layer` properties: ``` transition: opacity 0.2s, display 0.2s, top-layer 0.2s; ``` [1] https://html.spec.whatwg.org/multipage/popover.html Bug: 1307772,1413556 Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
I have done a prototype of :initial in Chrome with the following restrictions:
|
so It will not work in nested rules? |
In some cases that is true for the current prototype, and may be a good argument for allowing :initial to match in (possibly nested) any-matches type of selectors. It comes at the cost that we can not early out of matching matches-any selectors when we are computing styles for the initial styles and we have not matched any :initial pseudo selectors yet. /* Does not work */
:initial {
div & {}
}
/* Works */
div {
& :initial {
}
} |
As discussed at the meeting yesterday, let's try to resolve on the name for this. There were a lot of options so I'll group them by theme and give suggested voting emoji for each if you want to vote on it with emoji reactions. Voting is not intended to decide the name but just inform the discussion. I've intentionally left a few options off since I think we've come up with good reasons not to use them: Generic names suggesting the style before other styles apply: Specific to before-change style being set: |
Given the unanimous 10 votes for |
How does this syntax work if you want a different transition/animation for entry and exit? |
@o-t-w If we're transitioning Screen.Recording.2023-05-18.at.11.57.40.movIf we would be using JS, I don't think CSS would help us a lot with the exit transition, but we could use a class with the exit styles and do “apply this class -> wait for the transition -> remove element”. Which is not ideal, and I wonder if there is something we could do for this ( |
How would it work for an element with a popover attribute being closed? |
@o-t-w Seems to work fine: https://codepen.io/kizu/pen/wvYYmZY — updated the example. Screen.Recording.2023-05-18.at.15.20.45.movWe just have to apply the “exit” state to the |
w3c/csswg-drafts#8174 (comment) Bug: 1412851 Change-Id: Ic689460dac934b93039d1db2d6e30866470a0274 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4474048 Reviewed-by: Mason Freed <masonf@chromium.org> Commit-Queue: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1147154}
@astearns @atanassov I think we can resolve on renaming |
The CSS Working Group just discussed
The full IRC log of that discussion<bramus> chrishtr: This is the feature specify style in first frame of transition<bramus> chrishtr: previously we resolved to add it but needed to bikshed name <bramus> chrishtr: Vote was unanimous for `@starting-style` <bramus> chrishtr: with 11 votes <masonf> now 12 votes <bramus> Rossen_: looking at the folks that voted, there’s a strong Google representation but that’s ok <bramus> Rossen_: Any extra feedback or ideas? <bramus> Proposed resolution: rename `@initial` to `@starting-style` <bramus> RESVOLVED: rename `@initial` to `@starting-style` <bramus> RESOLVED: rename `@initial` to `@starting-style` |
Transitions are ergonomic and easy to use for changes to property values when there is an existing style to transition from. However, when an element is first added to the page or made not
display: none
it has no previous before-change style so developers have to use script to switch from the initial frame state and some state which specifies the post transition style, e.g.It would be great if you could do this directly from CSS perhaps via a pseudoclass selector. E.g.
This
:initial
pseudo-class would match on the initial frame containing a particular element and be removed immediately after style recalc. This does mean we would have to repeat style on that initial frame - hopefully we could target only elements affected by:initial
selectors.This would bring parity with what you can do via css animations, e.g.:
Though thinking ahead, I've also heard frustration around the css animation above animating when you load the page - so we should consider where there's a way for developers to differentiate loading vs post load and only apply animations (and initial transition styles) for new elements.
The text was updated successfully, but these errors were encountered: