Animations and transitions are an important part of web design. Adding subtle animations to your web page will make it more engaging. Simple animations like animated icons, kinetic typography, and animated logos can help enhance the user experience. Learn five awesome animation tricks that can help you enliven your website.

1. Transforming an Element on Hover

One common design practice is to have an element that scales up when interacted upon. For example, you might want to translate buttons a little bit upwards when someone hovers their mouse on it. You can achieve this using the CSS transform property.

Assuming you have a button:

        <button>
  Click me
</button>

You styled the body of the document as well as the button:

        /* Aligns the button to the center of the page */
body {
    display: flex;
    height: 100vh;
    align-items: center;
    justify-content: center;
    background-color: black;
}

/* Styles the button */
button {
    padding: 1em 2em;
    background: blue;
    border: 0;
    color: white;
    border-radius: 0.25rem;
    cursor: pointer;
    font-size: 2rem;
    transition: transform 500ms;
}

/* Hover states */
button:hover,
button:focus {
    transform: translateY(0.75rem) 500ms;
}

With the last block, you're setting hover and focus states on the button. In both states, you translate the button along the Y-axis by 0.75rem. The button would look like this:

Screenshot of blue button

When you hover your mouse on the button, it flicks in an upward direction. The transition takes half a second (500ms) to complete. This is a pattern that you can implement not just on your buttons, but on other elements as well (e.g. images).

2. Declaring Multiple Keyframes With One Declaration

Another common pattern in CSS animations is iterating over the same value multiple times. This could be a specific color, size, or orientation. You can achieve this utilizing CSS keyframe animations by declaring multiple keyframes with one declaration.

Consider the button you created in the previous section. Maybe you want to iterate over several background colors when you click the button. But you also want to go over the same color at different stages of the animation. Let's see how to achieve that in code.

First, you want to animate the button only when clicked. So you'd create a script.js file, inside which you access the button and toggle a class on the button when it's clicked:

        const button = document.querySelector("button")
button.addEventListener("click", (e) => {
    button.classList.toggle('party-time')
})

We used querySelector to access the button from the web page. To learn more about DOM traversal, read our post on how to traverse the DOM using JavaScript.

The party-time class activates an animation titled party:

        .party-time {
    animation: party 2000ms infinite;
}

For the animation, you want to start with red and transition to yellow at 25%. Then you'd come back to red at 50% before moving back to yellow at 75%. Finally, at 100%, you'd settle for a dark blue color:

        @keyframes party {
    0%, 50% {
        background-color: red;
    }
    25%, 75% {
        background-color: yellow;
    }
    100% {
        background-color: hsl(200, 72%, 35%);
    }
}

This approach is quite useful for alternating between colors on a color-based background. Because you can repeat multiple keyframes in one variable, it becomes super easy to use the same property at different stages of your animation.

3. Using @property to Animate Custom Properties

As you may already know, not all properties in CSS are animatable. The official Mozilla documentation keeps an updated record of all animatable CSS properties. If you're looking to animate a non-animatable property, then your best solution would be to use the @property directive.

Start by changing the background color of your button to a linear gradient:

        button {
     // other CSS
    background: linear-gradient(90deg, blue, green);
    // other CSS
}

Here's the output:

Screenshot of button with transient colors

Oftentimes you'd want to animate the color gradient on the button. While there are tricks you can use to move your gradient around, you can't actually animate it. This is because background (as well as background-image) is not an animatable property. This is where @property comes in.

The @property directive allows you to register custom properties. When you use @property, you must provide it with three values, namely syntax, inherits, and initial-value:

        @property --color-1 {
  syntax: "<color>";
  inherits: true;
  initial-value: red;
}

@property --color-2 {
  syntax: "<color>";
  inherits: true;
  initial-value: blue;
}

The first one is the starting property while the second is the destination property. Now, instead of transitioning a background image (that you can't transition), you'd transition from --color-1 to --color-2 (your custom properties) in one second:

        button {
  transition: --color-1 1000ms, --color-2 1000ms;
}

This technique is helpful because you can also add other customizations. For example, you add a delay to give it a smoother experience. The possibilities are endless.

4. Using Negative Animation Delays

Animation delays are crucial for creating smooth animations. Let's see an example of that in action. In this part, add a div element with 15 dots on top of the button:

        <div class="dots">
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
</div>

Here's some basic styling to transform each child div into a dot:

        .dots {
    display: flex;
    gap: .5rem;
    margin-bottom: 20px;
}
.dot {
    width: 10px;
    aspect-ratio: 1;
    background-color: red;
    border-radius: 50%;
}

Here we use Flexbox to place the dots in a horizontal line. To dive deep into Flexbox, you can check our CSS Flexbox tutorial.

Inside script.js, add the code that triggers the animation of the dots. You're toggling the dance class on the dots:

        button.addEventListener("click", (e) => {
    button.classList.toggle('party-time')

    // New code
    dots.forEach((dot) => {
        dot.classList.toggle('dance')
    })
})

The dance class activates an animation titled rise:

        .dot.dance {
    animation: rise 2000ms infinite alternate;
}

As for the animation, simply translate the dots -100px along the Y-axis:

        @keyframes rise {
    100% {
        transform: translateY(-100px)
    }
}

Now it's time to do something interesting. Instead of the dots rising at the same time, you want to animate the dots to flow like a wave. To achieve this, you're to add animation-delay to the dots, and increment each dot by 100ms:

        .dot:nth-child(1) {
    animation-delay: 100ms;
}
.dot:nth-child(2) {
    animation-delay: 200ms;
}
.dot:nth-child(3) {
    animation-delay: 300ms;
}
.dot:nth-child(4) {
    animation-delay: 400ms;
}
/* Keep doing till you reach the 15th dot */

This creates a sleek animation where the dots move up and down in a wavy form. The following image captures the dots in the middle of the animation:

Screenshot showing a bunch of dots moving in wave form

Keep in mind that this can be problematic, which brings us to the fifth tip.

5. Use prefers-reduced-motion to Enable Preferences

Always keep in mind that a lot of people don't like motion-based animations. In fact, most users have preferences in the browser that can turn the motion off. Motion can distract the senses, and in severe cases, lead to nausea.

Fortunately, you can easily take care of this by wrapping your animation inside a no-preference media query like so:

        @media(prefers-reduced-motion: no-preference) {
  .dot.dance {
    animation: rise 2000ms infinite alternate;
  }
}

Now if you were to enable prefers-reduced-motion in your browser, then the animation would not run.

Learn More CSS Tips and Tricks

CSS is full of awesome hacks that go beyond animations and transitions. For example, there are tips and tricks for making your whole layout sleek and responsive. The practices can help you make your website more engaging, accessible, and pleasant to browse. If you want to be a top one percent CSS developer, then having a couple of tricks up your sleeve helps a lot.