Observation: Inherited Visibility Transition
- Published on:
- Categories:
- CSS 89, Observation 9
- Current music:
- Mammal Hands —
Quiet Fire
- Current drink:
- Peppermint Tea
Introduction
Do not use transition: all in CSS. Just don’t (unless you are prototyping something, and will 100% remove it later). I won’t go into all the details today about why it’s bad (if I want to write about it well, I’ll need to do more research), but I will share one of the many issues it can cause.
Let’s quickly focus on its interaction with the visibility property, specifically how transitions work with its inheritance.
The Problem
Look at this example, and focus or hover the button inside, then unhover or blur it.
Some hidden text!
.example {
& > button:not(:hover, :focus-visible) + span {
visibility: hidden;
}
em {
transition: all 2s;
}
} <p class="example">
<button type="button">Hover or focus me!</button>
<span>Some <em>hidden</em> text!</span>
</p> If you’re not familiar with how visibility property works, this could be confusing. Like, shouldn’t it be not visible when the parent is not? Well, I wrote an article about this two years ago: “Obscure CSS: Restoring Visibility”.
In short, unlike display or opacity, it is possible to restore the visibility on the descendent elements! And because visibility is an inherited property, when the parent’s value changes, it inherits onto all the elements inside it.
What happens with a descendent element that has transition: all? That inherited value will be animated!
Animating Visibility
And due to the particular way a transition for visibility works, it will be visible for some time after we move the hover/focus away from the button in the example. Let me quote the specs:
For the
visibilityproperty,visibleis interpolated as a discrete step where values of p between 0 and 1 map tovisibleand other values of p map to the closer endpoint; if neither value isvisiblethen discrete animation is used.
That means that while the transition is happening, the element is hidden only when the value is right at zero, and is visible at all other times.
What Should We Do?
Not use transition: all. Use only the necessary list of properties you need to animate.
If you need to have many of them, instead of repeating the easing, duration, and delay, omit the property and then add the transition-property longhand:
em {
transition: 2s 0.3s linear;
transition-property: color, transform, opacity;
}
There is More (But Later)
There are many other reasons why transition: all is bad, but a proper explanation would need more research and would result in a bigger post: thus this is an “observation”.
As it goes, I did also stumble upon a potential browser bug that I’ll need to research, and then fill that is related to this observation.
I’ll try to do both of these later at some point. I hope even this shorter post will be useful to you.