New CSS transition "back" to original value doesn't work

3 weeks ago 30
ARTICLE AD BOX

Consider a div element we can paint different colors based on the [open] state of a toggleable details element. We start with (1) the details-controller and (2) a next-sibling that is the paintable .zone element:

<div> <details><summary>Painting color: </summary></details> <div class="zone"></div> </div>

First, give the <div> a baseline white background transition that not-very-specifically applies to its class:

.zone { background: white; transition: 10s; /* if nothing else applies, gradually turn white again */ }

Now add two different selectors with more specific rules to change that background property gradually via transition:

/* when details is open, clicks rapidly turn sibling .zone blue */ [open] + .zone:active { background: blue; transition: 3s; } /* when details is not open, clicks rapidly turn sibling .zone red */ :not([open]) + .zone:active { background: red; transition: 3s; } /* for ease of use, let's label the color on the details switch */ summary:after { content: "red brush"; } [open] summary:after { content: "blue brush"; }

So far so good. We can see the square rapidly shift red or blue on click, and then it gradually returns to white when not clicked. Here is a simple running example:

Finally, here comes the trouble: if we instead make the toggle control the square to rapidly turn red or white (the same as the original baseline color), the rapid transition will not take effect. Instead, the square just slowly fades to white, as if we weren't clicking it, and the accelerated :active rule does nothing.

This is slightly astonishing to me; it almost seems like a bug, but it appears consistent across browsers. I understand intuitively that this behavior (i.e., the failure to animate a new transition in favor of an ongoing transition to the same property value) manifests whenever an element is asked to transition one of its properties to a property value that it "already" has.

I also understand I can sidestep this issue with "almost" matching properties (like transitioning to off-white #fffffe instead of white).

I'm looking for a either:

a solution that will allow me to replace an ongoing transition with a differently-timed one to the same target value, or

at least a broadly applicable theory of CSS transitions that allows me to generalize why this behavior occurs.

I stepped into this problem to discover my understanding of CSS transition internals is a yawning void. Exactly how does an element maintain its transition states? What rules decide when to update them or not? I have no idea. Preferably, answers would include references to CSS specifications, but I'd also be happy with practical demonstrations that more clearly pinpoint the issue. (And happiest of all with a way to eliminate this problem altogether.)

Read Entire Article