<main>
<h1>Performant Animations</h1>
<p>Favour using the properties <code>transform</code> and <code>opacity</code> for your animations. You will be surprised by how much you can achieve with only these 2 properties. Below, I demonstrate some of the actions you can do with these properties.</p>
<h2>Size</h2>
<div class="item">
<h3>Width</h3>
<figure>
<div class="container">
<div class="rect widen"></div>
</div>
<figcaption>
Changing width of a rectangle
</figcaption>
</figure>
<p>You can change the width of an element with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleX()"><code>transform: scaleX()</code></a>.</p>
<pre>
<code class="language-css">
.widen {
animation: widen 2s infinite alternate;
}
@keyframes widen {
to {
transform: scaleX(2);
}
}
</code></pre>
<p>You can use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale()"><code>transform: scale()</code></a> if you wish to change the width and height together.</p>
</div>
<div class="item">
<h3>Height</h3>
<figure>
<div class="container">
<div class="rect heighten"></div>
</div>
<figcaption>
Changing height of a rectangle.
</figcaption>
</figure>
<p>You can change the height of an element with
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY()"><code>transform: scaleY()</code></a>.
</p>
<pre>
<code class="language-css">
.heighten {
animation: heighten linear 2s infinite alternate;
}
@keyframes heighten {
to {
transform: scaleY(2);
}
}
</code>
</pre>
<p>You can use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale()"><code>transform: scale()</code></a> if you wish to change the width and height together.</p>
</div>
<hr>
<h2>Rotation</h2>
<div class="item">
<h3>Directional Rotation</h3>
<figure>
<div class="container rotation">
<img src="img/arrow-right.svg" alt="a pink arrow" class="arrow arrowRight rotate">
</div>
<figcaption>
Rotating right arrow clockwise 90 degrees.
</figcaption>
</figure>
<p>You can change the direction of an element with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate()"><code>transform: rotate()</code></a>.</p>
<pre>
<code class="language-css">
.rotate {
animation: rotate linear 2s infinite alternate;
}
@keyframes rotate {
to {
transform: rotate(90deg);
}
}
</code>
</pre>
</div>
<div class="item rotation">
<h3>Sideways Rotation</h3>
<figure>
<div class="container">
<img src="img/arrow-right.svg" alt="a pink arrow" class="arrow arrowRight rotateSideways" >
</div>
<figcaption>
This is a right arrow being rotated 360 degrees on Y axis.
</figcaption>
</figure>
<pre>
<code class="language-css">
.rotateSideways {
animation: rotateSideways linear 2s infinite alternate;
}
@keyframes rotateSideways {
to {
transform: rotateY(360deg);
}
}
</code>
</pre>
<p>This was counter-intuitive for me when I was began learning transformations. I thought it would be <code>rotateX()</code> to get this effect.</p>
</div>
<div class="item">
<h3>Lengthways Rotation</h3>
<figure>
<div class="container rotation">
<img src="img/arrow-up.svg" alt="a pink arrow pointing up" class="arrowUp arrow rotateLengthways">
</div>
<figcaption>
This is an up arrow being rotated 360 degrees on the X axis.
</figcaption>
</figure>
<p>You can rotate an element lengthways with
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateX()"><code>transform:rotateX()</code></a>.
</p>
<pre>
<code class="language-css">
.rotateLengthways {
animation: rotateLengthways linear 2s infinite alternate;
}
@keyframes rotateLengthways {
to {
transform: rotateX(360deg);
}
}
</code>
</pre>
<p>This was counter-intuitive for me when I was began learning transformations. I thought it would be <code>rotateY()</code> to get this effect.</p>
</div>
<hr>
<h2>Movement</h2>
<div class="item">
<h3>Horizontal Movement</h3>
<figure>
<div class="container">
<img src="img/arrow-right.svg" alt="a pink arrow pointing to the right" class="arrow arrowRight moveHorizontal">
</div>
<figcaption>
Moving right arrow horizontally.
</figcaption>
</figure>
<p>You can move an element horizontally with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX"><code>transform:translateX()</code></a>.</p>
<pre>
<code class="language-css">
.moveHorizontal {
animation: moveHorizontal linear 2s infinite alternate;
}
@keyframes moveHorizontal {
to {
transform: translateX(150%);
}
}
</code>
</pre>
</div>
<div class="item">
<h3>Vertical Movement</h3>
<figure>
<div class="container">
<img src="img/arrow-up.svg" alt="a pink arrow pointing up" class="arrowUp arrow moveVertical">
</div>
<figcaption>
Moving up arrow vertically.
</figcaption>
</figure>
<p>You can move an element vertically with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY"><code>transform:translateY()</code></a></p>
<pre>
<code class="language-css">
.moveVertical {
animation: moveVertical linear 2s infinite alternate;
}
@keyframes moveVertical {
to {
transform: translateY(30px);
}
}
</code>
</pre>
</div>
<div class="item">
<h3>Diagonal Movement</h3>
<figure>
<div class="container">
<img src="img/arrow-up.svg" alt="a pink arrow pointing up" class="arrowUp arrow moveDiagonally1">
</div>
<figcaption>
Moving right arrow diagonally (north-east).
</figcaption>
</figure>
<p> You can move an element direction diagonally by using <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate"><code>transform:translate()</code></a> to move the element horizontally and vertically at the same time. </p>
<pre>
<code class="language-css">
.moveDiagonally1 {
animation: moveDiagonally1 linear 2s infinite alternate;
}
@keyframes moveDiagonally1 {
to {
transform: translate(-50%, 50%);
}
}
</code>
</pre>
<figure>
<div class="container">
<img src="img/arrow-up.svg" alt="a pink arrow pointing up" class="arrowUp arrow moveDiagonally2">
</div>
<figcaption>
Rotating and moving right arrow diagonally (north-east)</code>.
</figcaption>
</figure>
<p>If you want the element to face in the direction of movement, you need to rotate the element and use <code>translate()</code> to move it in the correct direction.</p>
<p>The order of transformations is important, <code>transform:rotate() translate()</code> and <code>transform:translate() rotate()</code> give different results.</p>
<pre>
<code class="language-css">
.moveDiagonally2 {
animation: moveDiagonally2 linear 2s infinite alternate;
}
@keyframes moveDiagonally2 {
0% {
transform: rotate(45deg) translateY(0);
}
100% {
transform: rotate(45deg) translateY(105%);
}
}
</code>
</pre>
</div>
<div class="item">
<h3>Moving Closer/Further Away</h3>
<figure>
<div class="container">
<img src="img/train.svg" alt="an outline of the front of a train" class="train scale">
</div>
<figcaption>
Moving train closer and further away.
</figcaption>
</figure>
<p>You can use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale()"><code>transform: scale()</code></a> or <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateZ()"><code>transform: translateZ()</code></a>.</p>
<p>Using <code>transform: scale()</code> is shrinking or enlarging an element. It is kind of cheating! It works well to create a perception of depth for simple movement e.g. straight lines.</p>
<pre>
<code class="language-css">
.scale {
animation: scale linear 2s infinite alternate;
}
@keyframes scale {
to {
transform: scale(0);
}
}
</code>
</pre>
<p>For more complex movements, you need to make a translation along the Z-axis. The Z-axis is the depth dimension. Using <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate3D()"><code>transform: translate3d()</code></a> will give you complete control of moving an element in all 3 dimensions.</p>
</div>
<hr>
<h2>Visibility</h2>
<div class="item">
<h3>Hide/Show</h3>
<figure>
<div class="container">
<div class="rect visibility"></div>
</div>
<figcaption>
Hiding/showing rectangle.
</figcaption>
</figure>
<p>Use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/opacity"><code>opacity</code></a> to control visibility of an element. You can use it for toggling between states and flashing objects at a particular frequency.</p>
<pre>
<code class="language-css">
.visibility {
animation: visibility linear 1s infinite alternate;
}
@keyframes visibility {
to {
opacity: 0;
}
}
</code></pre>
</div>
</main>
:root {
--element-color: #ff00bf;
--max-width: 600px;
}
html {
box-sizing: border-box;
}
body {
background-color: black;
color: white;
font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
"Lucida Sans Unicode", Geneva, Verdana, sans-serif;
}
main {
padding: 1rem 0.25rem;
max-width: var(--max-width);
margin: 0 auto;
}
a {
color: var(--element-color);
text-decoration: none;
}
h1,
h2,
h3 {
width: 100%;
text-align: center;
}
h2 {
text-decoration: underline;
}
hr {
color: white;
}
.item {
display: grid;
width: 100%;
max-width: var(--max-width);
row-gap: 1rem;
margin: 1rem auto;
}
figure {
margin: 0 5px;
}
figcaption {
margin-top: 0.5rem;
text-align: center;
font-size: 0.75rem;
}
pre[class*="language-"] {
overflow: auto;
margin: 0 5px;
}
.container {
height: 100px;
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(0, 53, 199);
box-shadow: rgba(88, 188, 255, 0.5) 0 0 2px 2px;
}
/* animated elements */
.rect {
width: 60px;
height: 30px;
background-color: var(--element-color);
box-shadow: rgba(0, 0, 0, 0.3) 0 0 2px 1px;
}
svg {
fill: var(--element-color);
}
.arrow,
.train {
width: 60px;
}
.arrowUp {
width: 40px;
}
@media screen and (min-width: 600px) {
}
/* animations */
.widen {
animation: widen 2s infinite alternate;
}
@keyframes widen {
to {
transform: scaleX(2);
}
}
.heighten {
animation: heighten linear 2s infinite alternate;
}
@keyframes heighten {
to {
transform: scaleY(2);
}
}
.rotate {
animation: rotate linear 2s infinite alternate;
}
@keyframes rotate {
to {
transform: rotate(90deg);
}
}
.rotateSideways {
animation: rotateSideways linear 2s infinite alternate;
}
@keyframes rotateSideways {
to {
transform: rotateY(360deg);
}
}
.rotateLengthways {
animation: rotateLengthways linear 2s infinite alternate;
}
@keyframes rotateLengthways {
to {
transform: rotateX(360deg);
}
}
.moveHorizontal {
animation: moveHorizontal linear 2s infinite alternate;
}
@keyframes moveHorizontal {
to {
transform: translateX(150%);
}
}
.moveVertical {
animation: moveVertical linear 2s infinite alternate;
}
@keyframes moveVertical {
to {
transform: translateY(30px);
}
}
.moveDiagonally1 {
animation: moveDiagonally1 linear 2s infinite alternate;
}
@keyframes moveDiagonally1 {
to {
transform: translate(-50%, 50%);
}
}
.moveDiagonally2 {
animation: moveDiagonally2 linear 2s infinite alternate;
}
@keyframes moveDiagonally2 {
0% {
transform: rotate(45deg) translateY(0);
}
100% {
transform: rotate(45deg) translateY(105%);
}
}
.scale {
animation: scale linear 2s infinite alternate;
}
@keyframes scale {
to {
transform: scale(0);
}
}
.visibility {
animation: visibility linear 1s infinite alternate;
}
@keyframes visibility {
to {
opacity: 0;
}
}
To make CSS animations that have peak performance, you should favour using the properties transform
and opacity
. You will be surprised by how much you can achieve with only these 2 properties. In this demo I walk through how to perform a range of movements and effects with these properties.
If you would like to learn more about how to write highly performant animations, you can read my article – How to design highly performant animations and micro-interactions.