Simplifying Entry Animations with @starting-style

Jan 12, 20253 MIN READ
Simplifying Entry Animations with @starting-style

Entry animations can be tricky—between handling DOM load times and animating from display: none, it's easy to get stuck. The @starting-style rule simplifies this by letting you explicitly set starting values for CSS properties when an element first loads, creating smoother transitions right from the get-go.


The Basics

@starting-style defines the starting point for your CSS properties before the element is visible. Think of it as the "before" state. The "after" state gets defined in your usual CSS rules. Here's how it works:

element { transition: opacity 0.5s ease-in; opacity: 1; @starting-style { opacity: 0; } }

When the element first loads, @starting-style defines its initial state, opacity: 0 in this case. It then transitions to the default state (or an explicitly defined one) which is opacity: 1 here. These styles also apply when an element changes from display: none to a visible state, making them ideal for animating toggled elements as well.

Nesting

You can use @starting-style in two ways: either nest it inside an element's ruleset (no selector needed) or define it separately with a selector.

However, note: nesting @starting-style within a pseudo-element (like ::before or ::after) won’t work because the styles will apply to the main element itself, not the pseudo-element.

/* Standalone */ @starting-style { element { opacity: 0; } } element { opacity: 1; transition: opacity 0.5s ease-in; } /* Nested */ element { opacity: 1; transition: opacity 0.5s ease-in; @starting-style { opacity: 0; } }

Pro Tip: The @starting-style at-rule and the "original rule" have the same specificity. To ensure that starting styles are applied correctly, always place the @starting-style at-rule after the "original rule."

Examples

A useful application of @starting-style is in creating entry effects or transitions on a webpage. For instance, fading in text on page load or animating popups and dialogs. A few of these are discussed below.

Animations from display: none

The main advantage of the @starting-style rule is the ability to create smooth entry transitions for elements that are initially hidden, especially when transitioning from display: none to a visible state. Without @starting-style, it would be difficult to transition from display: none, since there is no starting state from which to transition. @starting-style overcomes this limitation by defining an initial state for elements once they become visible.

A great way to visualize this is using the dialog element. The dialog's body switches between display: none and display: block as it is toggled. Normally, animating this transition would be impossible due to the display property change, but @starting-style makes it possible to animate the element's entry.

Fading and Sliding on Page Load

In the above code, @starting-style is used to set the "before" state for both elements. In the fade section, the opacity is set to 0, while in the slide section, the element is translated to the left.

I know these can be annoying for users, but there are legitimate use cases, such as cookie consent popups. Animating these on page render is made easier using @starting-style.

The logic here is the same, with two different effects applied on page load.


Thanks for reading! You may have noticed the lack of discussion on exit effects—that's because they fall outside the scope of @starting-style, as the name suggests. For handling exit effects, you'll need to use transition-behavior, which is a separate topic for a future article.

Logo
© 2024 Saleh Mubashar