Master of the universe

Transitions - How To Create Smooth CSS Animations Between States

Introduction

Smooth and visually appealing animations can significantly enhance a user's experience when interacting with websites or web applications. By leveraging the power of CSS transitions, web developers can create polished animations between different states of an element with minimal effort.

In this article, we'll dive deep into understanding CSS transitions, explore their various properties, and learn how to create smooth animations between states. We'll also discuss some best practices and tips for achieving the best performance with your CSS transitions.

Understanding CSS Transitions

CSS transitions provide a simple way to animate changes in CSS property values over a specified duration. A transition occurs when a specified property's value changes from its initial state to its final state.

To better understand how to create smooth animations with CSS transitions, it's crucial to dive into the different transition properties: transition-property, transition-duration, transition-timing-function, and transition-delay. These properties can also be set using the transition shorthand property.

Transition Property

The transition property is a shorthand property that allows you to set the individual transition properties in a single declaration. The syntax for the transition property is as follows:

transition: <property> <duration> <timing-function> <delay>;

You can specify one or multiple transitions for a single element using the transition shorthand. To define multiple transitions, separate each transition with a comma. For example:

transition: background-color 0.5s ease, border 0.3s linear;

Now, let's dive into each component of the shorthand property to gain a better understanding.

Transition-Property

The transition-property CSS property specifies which properties should be animated when a value change occurs. You can either use the keyword all to target all animatable properties or list individual properties separated by commas.

An example of using the all keyword:

.example {
  transition-property: all;
}

An example of specifying individual properties:

.example {
  transition-property: background-color, border-radius;
}

Keep in mind that not all CSS properties are animatable. To find out whether a particular property can be animated or not, refer to the MDN Web Docs.

https://www.youtube.com/watch?v=SgmNxE9lWcY

Transition-Duration

The transition-duration CSS property determines the duration of the transition, i.e., how long the animation takes to complete. The duration is defined using time units: s (seconds) or ms (milliseconds).

Here's an example of setting the duration for a background-color transition:

.example {
  transition-property: background-color;
  transition-duration: 0.5s;
}

In this example, the background-color transition will take 0.5 seconds to complete.

Transition-Timing-Function

One of the most crucial aspects of creating smooth animations is controlling the pace of the animation. The transition-timing-function CSS property lets you define the easing function for the transition, controlling how the animation progresses over time.

There are several predefined timing functions you can use:

  • linear: A consistent speed throughout the animation.
  • ease: Starts slow, accelerates, and then decelerates (default value).
  • ease-in: Starts slow and accelerates.
  • ease-out: Starts fast and decelerates.
  • ease-in-out: Starts slow, accelerates in the middle, then decelerates.
.example {
  transition-property: background-color;
  transition-duration: 0.5s;
  transition-timing-function: ease-out;
}

In addition to the predefined timing functions, you can create custom timing functions using the cubic-bezier() function. The cubic-bezier() function accepts four parameters (x1, y1, x2, y2), which control the shape of the bezier curve. You can use online tools, such as Cubic-bezier.com, to experiment and generate custom timing functions for your transitions.

Transition-Delay

Sometimes, you may want to start the animation after a brief pause. The transition-delay CSS property allows you to set a delay before the transition begins. Like transition-duration, the delay is defined using time units: s (seconds) or ms (milliseconds).

Here's an example of adding a delay to the background-color transition:

.example {
  transition-property: background-color;
  transition-duration: 0.5s;
  transition-timing-function: ease-out;
  transition-delay: 0.2s;
}

In this example, the background-color transition will be triggered after a 0.2-second pause.

Creating Smooth Transitions

Now that we have a solid understanding of CSS transition properties, let's explore some practical examples and techniques for creating smooth animations between different states.

Hover Effects

One of the most common use cases for CSS transitions is to create smooth hover effects on buttons or links. The following example demonstrates how to add a subtle background-color change and border-radius transition to a button when the user hovers over it:

.button {
  background-color: #007bff;
  border-radius: 4px;
  color: #fff;
  padding: 10px 15px;
  text-decoration: none;
  transition: background-color 0.3s ease-in-out, border-radius 0.3s ease-in-out;
}

.button:hover {
  background-color: #0056b3;
  border-radius: 50%;
}

In this example, the button's background-color and border-radius will smoothly transition between their initial and final states when the user hovers over or moves their pointer away from the button. You can further enhance the hover effect by using the transform property to apply scaling, rotation, or translations.

Fading Elements In and Out

Creating smooth fadeIn and fadeOut effects can improve the user experience when elements appear and disappear on a page. The following example demonstrates how to create smooth fadeIn and fadeOut effects using the opacity and visibility properties:

.fade {
  opacity: 0;
  transition: opacity 0.4s ease-in-out, visibility 0s 0.4s;
  visibility: hidden;
}

.fade.visible {
  opacity: 1;
  transition-delay: 0s;
  visibility: visible;
}

In this example, the element with the fade class will be initially hidden. By adding the visible class, the element will smoothly transition to fully visible (opacity: 1). The visibility property is used to control whether the element is accessible; the 0.4s delay for the visibility transition ensures that it aligns with the opacity transition.

Slide-in and Slide-out Effects

Slide-in and slide-out effects are often used to animate elements like sidebars, modals, or dropdown menus. The following example demonstrates how to create a smooth slide-in and slide-out effect using the transform and max-height properties:

.slide {
  max-height: 0;
  overflow: hidden;
  transform: translateY(-100%);
  transition: transform 0.4s ease-in-out, max-height 0s 0.4s;
}

.slide.visible {
  max-height: 300px;
  transform: translateY(0);
  transition-delay: 0s;
}

In this example, the .slide class hides the element by default, setting max-height to zero and transform property to translate the element vertically upward (translateY(-100%)). When the .visible class is added, the element smoothly transitions into view with translateY(0) and a defined maximum height. Similar to the fadeIn and fadeOut example, the transition-delay is used to ensure a proper transition matching the element's appearance.

Expanding and Collapsing Elements

Smooth expand and collapse effects are useful for animating accordions or other content sections that can be toggled. The following example demonstrates how to create a smooth expand and collapse effect using the height, overflow, and max-height properties:

.collapse {
  height: 0;
  overflow: hidden;
  transition: height 0.4s ease-in-out;
}

.collapse.open {
  height: auto;
  max-height: 500px;
}

In this example, the element with the collapse class will have a height of 0 by default. Adding the class open will enable the element to smoothly expand until it reaches its defined maximum height or its natural height when height: auto is applied. Note that you need to set a max-height value to achieve the smooth transition, as CSS transitions cannot directly animate the height property between 0 and auto.

Best Practices and Tips

Creating high-quality animations requires following certain best practices and tips to ensure that the transitions not only look great but also perform well across various devices and browsers. In this section, we will cover some of these best practices to help you optimize your CSS transitions.

Using will-change Property

The will-change CSS property allows you to inform the browser that certain properties of an element are likely to be modified shortly. This hint enables the browser to optimize rendering and provide a better user experience, especially for animations or transitions that can trigger layout changes or repaints.

To use the will-change property, simply assign the CSS properties that are likely to change. For example, if you know that an element's transform and opacity properties will change due to an upcoming animation, you can add the following code:

.example {
  will-change: transform, opacity;
}

Keep in mind that will-change should be used sparingly and only for elements that will indeed have changes. Overusing this property can lead to performance issues, as the browser may allocate unnecessary resources to optimize elements that remain unchanged.

Animating transform and opacity Properties

When creating animations, it's a good idea to animate the transform and opacity properties whenever possible. Animating these properties has less impact on the browser's rendering process and therefore results in better performance compared to animating properties that cause layout reflow or repaints.

For example, instead of animating an element's width or height properties, try using the transform: scale() function to achieve a similar effect with better performance:

.example {
  transition: transform 0.4s ease-in-out;
}

.example:hover {
  transform: scale(1.2);
}

Combining Transitions with Media Queries

CSS transitions can be combined with media queries to create responsive animations that adapt according to screen size or device orientation. By adjusting transition properties within media queries, you can ensure smooth animations across various screen sizes and devices.

For example, you can create a slide-in effect that varies the transition duration based on the screen size:

.slide {
  transform: translateX(-100%);
  transition: transform 0.5s ease-in-out;
}

.slide.visible {
  transform: translateX(0%);
}

@media screen and (max-width: 600px) {
  .slide {
    transition-duration: 0.8s;
  }
}

In this example, the slide-in effect will have a duration of 0.5 seconds on screens larger than 600px in width, and 0.8 seconds on smaller screens.

Fallback for Older Browsers

While most modern browsers support CSS transitions, it's essential to provide a graceful degradation for older browsers or browsers that do not support this feature.

One way to achieve this is by using JavaScript to detect browser support for CSS transitions and applying animation styles if the feature is supported. Here's an example using the Modernizr library:

<script>
  Modernizr.on('csstransitions', function (result) {
    if (result) {
      var css = '.button { transition: background-color 0.3s ease; }';
      var style = document.createElement('style');
      style.type = 'text/css';
      style.appendChild(document.createTextNode(css));
      document.head.appendChild(style);
    }
  });
</script>

In this example, the JavaScript code checks whether CSS transitions are supported by the browser using the Modernizr library. If supported, it adds a transition style for the button element.

Advanced CSS Transition Techniques

While we've already covered essential information and techniques for creating smooth CSS animations, let's explore some advanced techniques that can further enhance your transitions and make your animations stand out.

Staggered Transitions

Staggered transitions involve creating a slight delay between the start of each transition in a series of elements. These transitions can be useful when revealing a list of items or creating more complex animations. To create staggered transitions, you can utilize CSS variables and the nth-child() selector. For example:

.item {
  --stagger-delay: 0.1s;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out;
}

.item.visible {
  opacity: 1;
  transform: translateY(0);
}

.item:nth-child(2) {
  transition-delay: calc(1 * var(--stagger-delay));
}

.item:nth-child(3) {
  transition-delay: calc(2 * var(--stagger-delay));
}

.item:nth-child(4) {
  transition-delay: calc(3 * var(--stagger-delay));
}

In this example, we use the --stagger-delay CSS variable and the nth-child() selector to add a delay to each .item based on its position in the list. When the .visible class is added to the items, their transitions will be triggered one after the other, creating a staggered reveal effect.

Transitioning with Custom Properties (CSS Variables)

Custom properties, also known as CSS variables, can be useful when animating components with dynamic or user-defined values. For example, let's imagine we have a button that can change its background-color based on a user-selected theme:

.button {
  background-color: var(--background-color, #007bff);
  color: #fff;
  padding: 10px 15px;
  text-decoration: none;
  transition: background-color 0.3s ease-in-out;
}

.button:hover {
  background-color: var(--hover-background-color, #0056b3);
}

In this example, the background-color of the button is determined by the --background-color and --hover-background-color custom properties. These custom properties can be updated using JavaScript to change the button's appearance dynamically, while still maintaining a smooth background-color transition.

Animating Along a Path

Animating elements along a curved or complex path can elevate your animations to the next level. Using the offset-path property, you can define a path and then animate the offset-distance property to move an element along that path. For example:

.path-animation {
  offset-path: path('M0,0 Q100,100 200,0');
  offset-distance: 0%;
  transition: offset-distance 1s ease-in-out;
}

.path-animation.animate {
  offset-distance: 100%;
}

In this example, the .path-animation class defines a quadratic Bezier curve as the path using the offset-path property. By animating the offset-distance property, the element will smoothly move along the path when the .animate class is added. Keep in mind that the offset-path property currently has limited support across browsers, so make sure to check compatibility before using it in production.

Going Beyond Transitions: CSS Animations

While CSS transitions are a powerful tool for creating smooth animations between different states of an element, sometimes you may need more control over the animation or create an animation that doesn't rely on a state change. In these scenarios, CSS animations can be a great solution.

CSS animations use the @keyframes at-rule to define a set of keyframes between which the animation will occur. Combined with properties like animation-name, animation-duration, animation-timing-function, and others, this method offers more flexibility and control over your animations.

For example, let's create a pulse effect using CSS animations:

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.pulse {
  animation: pulse 2s infinite ease-in-out;
}

In this example, we define a pulse animation using the @keyframes at-rule. The .pulse class will apply the pulse animation, causing the element to scale smoothly between its initial and larger size.

When creating advanced animations or animating numerous elements simultaneously, CSS animations offer an added level of control and flexibility compared to CSS transitions.

Performance Optimization for CSS Transitions

Smooth and visually appealing animations not only provide a polished look for your website or web application but also ensure an optimized user experience. To achieve smooth animations, it's crucial to consider the performance implications of your CSS transitions. In this section, we will explore some performance optimization strategies and techniques for CSS transitions.

Optimize Paint and Layout Operations

Avoid animating properties that trigger paint or layout operations, as these can negatively impact performance. Properties like width, height, margin, and padding can cause layout recalculations, while properties like box-shadow, background-image, and border can invoke paint operations.

Instead, consider animating properties like opacity and transform, which trigger only composite operations and typically result in better performance.

Limit the Number of Animating Elements

Animating a large number of elements simultaneously can strain performance on low-powered devices or browsers. If possible, limit the number of elements being animated or use techniques like requestAnimationFrame to throttle animations, providing more control over when animations start and stop.

Use the Layer Model

To further optimize performance, consider leveraging layers or stacking contexts for animating elements. By promoting an element to its own composite layer, the browser can optimize rendering, resulting in improved animation performance. To create a new layer for an element, use the transform: translateZ(0); or will-change CSS property:

.layer {
  transform: translateZ(0);
}

Utilize Hardware Acceleration

Modern browsers can offload certain animations to the GPU, resulting in improved performance. To take advantage of hardware acceleration, use the transform property with 3D-like functions (e.g., translate3d(), rotate3d(), scale3d(), or perspective()). This technique forces the browser to use GPU acceleration for improved performance:

.accelerated {
  transform: translate3d(0, 0, 0);
  transition: transform 0.4s ease-in-out;
}

.accelerated:hover {
  transform: translate3d(50px, 0, 0);
}

Debugging CSS Transitions

When working with CSS transitions, you might encounter issues that need to be debugged, such as animations not behaving as expected or poor performance. In this section, we will explore some tips and techniques for debugging CSS transitions effectively.

Use DevTools for Inspection

Modern web browsers provide powerful DevTools for inspecting and debugging HTML, CSS, and JavaScript. Use the Elements panel in DevTools to inspect the properties of elements with transitions, verify that the correct transition properties are applied, and confirm that the expected properties are animating.

Check Timing Functions and Initial/End States

Ensure each animating property has a defined initial state and an end state. It's also important to make sure the durations, timing functions, and delay values are set accurately.

.transition {
  opacity: 1;
  transition: opacity 0.4s ease-in-out;
}

.transition.hidden {
  opacity: 0;
}

In this example, we've defined an initial state (opacity: 1) and an end state (opacity: 0) and set an appropriate duration, timing function, and delay value.

Assess Browser Support and Fallbacks

Verify that the CSS transition features you're using are supported in the targeted browsers. You can check the compatibility of specific properties and features using resources like Can I use or MDN Web Docs.

For unsupported features, provide fallbacks or alternative animations to ensure a consistent user experience across various browsers and devices.

Profile Performance and Optimize

To identify potential performance bottlenecks, use the Performance panel in DevTools to record and profile animations. Analyze the performance profiles to spot areas where the browser is expending excessive resources, leading to slow or stuttering animations. Apply the optimization techniques discussed earlier in this article to enhance performance and deliver smooth animations.

Conclusion

Creating smooth CSS animations between various states is essential in enhancing user experience and ensuring a polished and professional look for your websites or web applications. We've covered the fundamental aspects of creating smooth animations using CSS transitions and discussed best practices and tips for optimizing your transitions.

Remember the importance of using appropriate properties, easing functions, and durations, as well as providing fallback support for older browsers to ensure a great user experience regardless of the device or browser being used. With this knowledge in hand, you can take your web development projects to the next level by crafting engaging, smooth, and visually appealing animations using CSS transitions.

Frequently Asked Questions

How do I combine multiple transitions on the same element?

To apply multiple transitions to a single element, list each transition property, duration, timing function, and delay separated by commas. Here's an example of combining background-color and border-radius transitions:

.example {
  transition: background-color 0.4s ease-in-out, border-radius 0.4s ease-in-out;
}

In this example, both background-color and border-radius properties will smoothly transition with a duration of 0.4 seconds and an ease-in-out timing function.

How do I chain or sequence multiple transitions?

To create a sequence of transitions, use the transition-delay property to delay the start of successive transitions. Adjust the delay values so that each transition starts after the previous one ends or at a specific point during the preceding transition. For example, to chain a background-color and border-radius transition, you can set the transition-delay as follows:

.example {
  transition: background-color 0.3s ease-in-out, border-radius 0.3s ease-in-out 0.3s;
}

In this example, the border-radius transition begins after the background-color transition ends, resulting in a sequential chain of transitions.

Can I apply CSS transitions to pseudo-elements?

Yes, you can apply CSS transitions to both ::before and ::after pseudo-elements. The process is the same as applying transitions to any other element. For example, to create a smooth hover effect on a ::before pseudo-element, you can do the following:

.example::before {
  content: "";
  background-color: #007bff;
  width: 50px;
  height: 50px;
  transition: background-color 0.3s ease-in-out;
}

.example:hover::before {
  background-color: #0056b3;
}

How do I create transition effects on page load?

To create transition effects on page load, apply initial styles to the elements, and then use JavaScript to add a class that triggers the transitions after a specified delay. For example, consider a fadeIn effect on page load:

.fade {
  opacity: 0;
  transition: opacity 0.4s ease-in-out;
}

.fade.animate-on-load {
  opacity: 1;
}

Then, use JavaScript to trigger the fadeIn effect after a delay:

<script>
  window.addEventListener('DOMContentLoaded', function () {
    setTimeout(function () {
      var fadeElements = document.querySelectorAll('.fade');
      fadeElements.forEach(function (element) {
        element.classList.add('animate-on-load');
      });
    }, 500);
  });
</script>

In this example, the elements with the fade class have an initial opacity of 0. After 500 milliseconds from the DOMContentLoaded event, JavaScript applies the .animate-on-load class, triggering the fadeIn effect.

How can I create smooth animations on scroll?

To create smooth animations when the user scrolls, use JavaScript to detect the scroll position and apply classes to trigger CSS transitions. For a simple example, consider the following CSS for a fadeIn effect on scroll:

.fade-on-scroll {
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}

.fade-on-scroll.visible {
  opacity: 1;
}

Next, use JavaScript to detect the scroll position and apply the .visible class when an element comes into view:

<script>
  window.addEventListener('scroll', function () {
    var fadeElements = document.querySelectorAll('.fade-on-scroll');
    var windowHeight = window.innerHeight;
    fadeElements.forEach(function (element) {
      var elementPosition = element.getBoundingClientRect().top;
      if (elementPosition < windowHeight - 100) {
        element.classList.add('visible');
      }
    });
  });
</script>

In this example, the elements with the fade-on-scroll class will fadeIn when they come into view as the user scrolls the page.

Sign up for the Artisan Beta

Help us reimagine WordPress.

Whether you’re a smaller site seeking to optimize performance, or mid-market/enterprise buildinging out a secure WordPress architecture – we’ve got you covered. 

We care about the protection of your data. Read our Privacy Policy.