← Blog 5 min read

CSS @starting-style: Entry Animations Without JavaScript

CSS @starting-style: Entry Animations Without JavaScript

Most interface animations begin after an element already exists on the page. That sounds simple, but it creates a stubborn gap: how do you animate an element from the moment it first appears? For years, developers reached for JavaScript, forced a style calculation, or kept hidden placeholder elements in the DOM. CSS @starting-style gives the browser a cleaner answer.

The rule defines the styles an element should have before its first rendered frame. The browser can then transition from that starting state to the element’s normal state. The result is a native entry animation that works with newly inserted elements, popovers, dialogs, and other UI that changes from not rendered to rendered.

Why entry transitions used to be awkward

CSS transitions compare an old computed style with a new one. A newly created element has no previous rendered style, so there is normally nothing to interpolate from. Developers often solved this by adding a class in a later animation frame, using a timer, or animating keyframes instead of transitions. Each workaround added timing code and made component behavior harder to reason about.

@starting-style supplies that missing first state. It lets the browser treat a newly rendered element as though it began with a defined opacity, transform, or other transitionable value. This keeps presentation logic in CSS and reduces coordination between scripts and styles.

A basic @starting-style example

.notice {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 240ms ease, transform 240ms ease;
}

@starting-style {
  .notice {
    opacity: 0;
    transform: translateY(12px);
  }
}

When .notice begins rendering, the browser starts it slightly lower and transparent, then transitions it into its declared resting state. The same rule can also be nested inside a style rule in modern CSS:

.notice {
  opacity: 1;
  transform: translateY(0);
  transition: 240ms ease;

  @starting-style {
    opacity: 0;
    transform: translateY(12px);
  }
}

The nested form is useful inside component styles because the starting state stays beside the final state.

Dialogs, popovers, and discrete properties

Entry effects become especially valuable for interface elements that enter and leave the top layer. A dialog or popover may switch between display: none and a rendered state. To transition those discrete changes, combine @starting-style with transition-behavior: allow-discrete.

[popover] {
  opacity: 1;
  transform: scale(1);
  transition:
    opacity 180ms ease,
    transform 180ms ease,
    display 180ms allow-discrete;
}

@starting-style {
  [popover]:popover-open {
    opacity: 0;
    transform: scale(.96);
  }
}

This pattern pairs naturally with the native Popover API. The browser manages focus and top-layer placement while CSS controls the visual entrance. For page-level continuity, compare it with the View Transition API; for motion tied to scrolling, see our guide to CSS scroll-driven animations.

Respect reduced-motion preferences

An entry animation should explain change, not delay access. Keep motion brief, avoid large travel distances, and honor the user’s operating-system preference.

@media (prefers-reduced-motion: reduce) {
  .notice,
  [popover] {
    transition-duration: 0.01ms;
  }
}

Opacity-only changes are often gentler than zooming or sweeping movements, but even opacity transitions can be unnecessary. Test the interface with animation disabled and make sure no information depends on motion.

Progressive enhancement and browser support

Browsers that do not understand @starting-style ignore it. The element still appears in its final state, which makes the feature a strong progressive enhancement. Your content and controls should remain fully usable without the entry effect.

For precise syntax and current compatibility, consult the MDN @starting-style reference and the CSS Transitions Level 2 specification. Check support for the particular combination you use, especially when animating top-layer elements and discrete properties.

Practical design rules

  • Define a stable final state. The ordinary rule should describe the component after the transition completes.
  • Use small differences. A few pixels of movement and a short fade usually communicate arrival without distraction.
  • Avoid layout-heavy animation. Prefer opacity and transforms over properties that repeatedly trigger layout.
  • Test rapid toggles. Popovers and dialogs may open and close quickly, so confirm interrupted transitions remain predictable.
  • Keep behavior semantic. CSS should polish the entrance; HTML and browser APIs should still control meaning, focus, and activation.

A cleaner browser-native pattern

@starting-style is a small feature with an important effect: it removes a common reason to coordinate animation timing in JavaScript. Components become easier to reuse because their first visual state lives with the rest of their CSS. Combined with native dialogs, popovers, and careful reduced-motion handling, it helps interfaces feel polished without hiding their structure behind extra scripts.

Where this helps most

Use entry transitions where appearance itself carries meaning: a validation message arriving after a form check, a command palette opening, a newly added list item, or a contextual help panel. These are moments when a subtle visual cue helps users locate the change. Avoid applying the same animation to every element on a busy page. Repetition quickly turns useful motion into noise.

Component authors should also remember that starting styles apply when an element begins participating in rendering, not every time any class changes. If you need a repeated state-to-state animation, an ordinary transition or keyframe animation may still be the better tool. Choose the smallest browser feature that accurately matches the interaction.

Browse with calm, clarity, and purpose

Download Noorani Browser for a focused browsing experience with thoughtful privacy tools and useful everyday features.

Download Noorani Browser