Deploy Inc.

The Latest Trends in CSS Transformations

For a few years now, "top", "right", "bottom" and "left" properties have been definitely out of the question when writing CSS3 element transforms/animations. But, there are still some situations where you simply have to think about using those: for instance, when a single element has lots of transforming properties + animation on it in different scenarios.

So, to smooth things out, the latest practice is to use translateX(), translateY() and translateZ() or translate3d(x, y, z) to transform elements around.

There's a difference between these translates also, as translate3d uses hardware acceleration so it might look even smoother than specific translates.

If there are too many transforms/animations, you might still get into a tough spot. This is especially true if you're using translate3d on mobile devices, as their hardware capabilities are far below those of a desktop PC/laptop, thus it might look worse.

One step in improving this situation (as mentioned in the article*) is to use the "will-change" CSS3 property. Unfortunately,  it still doesn't have great browser support: https://caniuse.com/#search=will-change.

The general rule for using the "will-change" prop is to use it at the latest possible moment (before the actual transform/animation and browser repaint). So basically, adding an additional parent class which represents the mid-transition state.

Say we have a wrapper element with one child element which is hidden and moved aside by default (see the HTML example below):

<div class="element__wrapper">
<div class="element__child"></div>
</div>

CSS

.element__child {
transition: all 0.25s ease;
-webkit-transition: all 0.25s ease;
opacity: 0;
transform: translateX(25px);
-webkit-transform: translateX(25px);
}

When the user clicks the wrapper element, we would add "active" class on the wrapper and cause the child to slide in and fade in.

Basically, DEFAULT -> ACTIVE element states.

.element__wrapper.active .element__child {
opacity: 1;
transform: translateX(0);
-webkit-transform: translateX(0);
}

The trick with the "will-change" prop here is to add an additional class to the wrapper. For example, we would first add the "transitioning" class and then add the "active" class.

States here would be DEFAULT -> TRANSITIONING -> ACTIVE

.element__wrapper.transitioning .element__child {
will-change: all; // As we're going to change both opacity and transform properties
}
.element__wrapper.active .element__child {
opacity: 1;
transform: translateX(0);
-webkit-transform: translateX(0);
}

This tells the browser to prepare the painting layers before the transform / animation, thus smoothing it out even further.

Overusing the "will-change" prop can also lead to even worse animation behavior and flickering. By overuse, I mean setting it on all elements by default (for :hover, :active, :visited states and similar) or by using it on too many elements. The "will-change" prop needs to be used with care. There are lots of articles on the web regarding proper usage.

TL;DR

If everything fails, delete the whole project and start a new. (joking)

P.S. Passionate about Front-End? Read more tips & tricks for smoother animations @ https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108#.7eu7pa7s5

Back to blog