When a CSS transform is applied to an element, like
it seems that element’s
position property is forced to
relative. This side effect introduces quirky behaviour, when you depend on the position being static.
Here’s an explanation of what happens. Luckily there’s also a simple solution to this problem.
A child outgrown its parent
Suppose we have an article element that contains a link:
To expand the area of the link responding to hovering and clicking/tapping to the whole article we can define a CSS pseudo-element:
This pseudo-element behaves like a child element of the
<a>-tag in the DOM. By positioning it
absolute and setting
top, left, right and
bottom to 0, it takes up the space of its nearest ancestor that is a positioned element. We want that ancestor to be our
Events received by the large pseudo-element now bubble up to its small parent. Below is an example that shows a box without and with mouseover.
Check that this works on CodePen.
Now suppose we styled the anchor element as a button and we want to react on hovering over the article by making the button bigger.
Can you predict what will happen? Check this CodePen.
It turns out that if you hover over the article but not the anchor the button starts to flicker. What happens is that when a transform is applied, the transformation must be relative to some basic state. Therefor its position is secretly changed to
relative. Now the pseudo-element that was positioned relative to the article is suddenly positioned relative to the button. In effect the pseudo-element shrinks to the size of the button. This ends the hovering and as a consequence the transform and the
position property of the button reverts to
static. And then everything starts over again.
So when a transform is applied to a static element, its position property is changed as a side effect. And as happens more often, side effects cause bugs, or quirky behaviour.
To prevent this I guess transformable objects should be explicitly positioned elements. However, this restriction is not in the W3 specification.
There is a simple solution to this problem. We need to change the HTML structure a bit and place the button inside the anchor element, as a child element:
Apply the transform to the button when the anchor, which is now the parent of the button, is hovered. This leaves the
position property of the anchor alone, and prevents the pseudo-element of the anchor to shrink.
Here’s a final CodePen to see this soluton at work.