CSS max-width after transform + scale vs. pseudo elements
Tags: webdev, css
Published: 2023-08-14 16:58:48

Another one of those situations where order of declarations matters (it often does in CSS anyway) and the don't even seem to be handled consistently across browsers.

## Ensure max-width after scale transformation

A simple use case: restrict the maximum width of an element after transformation. Maybe this problem only applies to pseudo elements, but we'll see.

The actual case adds another aspect that might cause the problem: a translation on the Z-axis which will result in an additional perceived scale transformation when applied to a 2-dimensional browser window.

First, I apply a `z-translation` in order to set up a [parallax perspective effect](https://dev.to/ingosteinke/pure-css-parallax-perspective-beyond-landscape-images-24g2), then I apply a 2d `scale` to compensate for the perceived downsizing.

This worked fine so far (at least in Chrome / Chromium and Firefox, and only in my specific project setup, see below ...)

```css
.container::after {
  content: ""; /* add more visual styles here */
  transform-origin: top left;
  transform: translateZ(-1px) scale(2);
```

Now I want to add an additional restriction to a maximum width on wide screens, so I add

```
  width: auto;
  max-width: 100%;
```

which also worked as intended on Chrome and Firefox. It did not even matter if I put the width before or after the translation, it still got applied to the resulting width - but not in Safari!

Safari consistently used another calculation order, no matter where I put the `max-width` in my code, it will never apply to the element's width after transformation.

### Avoid this combination if you can

This important difference is either documented poorly or just hard to find. It might be another rare edge case that you should avoid if you can, or maybe "max-width", "scale", "transform", "order", and "Safari" are too broad and general terms to yield any helpful result apart from the usual go-to resources covering best practices for beginners.

> **Don't use `transform:translateZ` together with `scale` and ` max-width` if you can avoid it.**

### But if you do ...

I got so frustrated about wasting my time on cross-browser issues again, that I was tempted to use a [CSS browser hack](https://en.wikipedia.org/wiki/CSS_hack) to work around the issue. But this always feels like making it work without knowing why, beyond the perceived browser behavior.

**What I actually want to do is state explicitly that the max-width must be applied to the pseudo element after the transition, not before.**

Now it seems I finally rephrased my problem in a way where I start getting helpful results after all.

![Screenshot of search results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzh8os30v30826qvd6yb.png)

People also asked:

- [Can you define a maximum width/height to CSS transform scale?](https://stackoverflow.com/questions/66128302/can-you-define-a-maximum-width-height-to-css-transform-scale)
- [Position AFTER transform in CSS?](https://stackoverflow.com/questions/15507941/position-after-transform-in-css)
- [How to limit a transform scale to the width and height of the parent?](https://stackoverflow.com/questions/28509544/how-to-limit-a-transform-scale-to-the-width-and-height-of-the-parent-element-in)

I did not even read the other two, because as I prepared a codepen to reproduce the problem in an isolated way, I found it hard to make it behave as I described.

In short, `transformation` combined with `max-width` does not work well, sometimes not at all, on a pseudo element (like `.container::after` but it does work well on a regular DOM child.

### So if you do ...

Avoid using the problematic combination on pseudo elements and make sure to use regular child nodes instead.

Maximum width will then be applied to the calculated width after the transformation has been applied.

Here is the [codepen: Transform + max-width on child nodes vs. pseudo elements](https://codepen.io/openmindculture/pen/zYMgWQL)

{% codepen https://codepen.io/openmindculture/pen/zYMgWQL %}