Categories
CSS Web development

Transforming a static element

When a CSS transform is applied to an element, like

CSS

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:

HTML

To expand the area of the link responding to hovering and clicking/tapping to the whole article we can define a CSS pseudo-element:

CSS

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 <article>.

CSS

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.

The right image shows hovering works on the whole article. In this case the pseudo-element shows itself as a semi-transparent overlay.

Check that this works on CodePen.

Scaling up

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.

CSS

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.

Side effects

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.

Solution

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:

HTML

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.

CSS
Scaled button on hovering the article.

Here’s a final CodePen to see this soluton at work.