# How to Use @starting‑style for CSS‑Only Entry Animations

> Master CSS only entry animations with @starting-style. Define initial states for smooth transitions without JavaScript. Learn this powerful CSS feature today.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: tutorial
- Published: 2026-07-30

---

**@starting‑style** is a CSS at‑rule that defines the initial visual state of an element before the browser paints the first frame, enabling smooth entrance animations without JavaScript.

The `emilkowalski/skills` repository documents this technique as the preferred method for static entry animations throughout the Instagit skillset. By declaring start states in CSS rather than React state, you eliminate `useEffect` hooks and avoid extra render passes while keeping motion definitions co‑located with your styles.

## What Is @starting‑style?

`@starting‑style` allows you to specify how an element looks before it appears on screen. When the page loads, the element renders with the properties inside the `@starting‑style` block; immediately after the first paint, the browser applies the element’s normal styles and transitions animate the change. This creates a seamless entrance effect without requiring JavaScript to toggle visibility.

In `skills/review‑animations/STANDARDS.md` (line 89), the rule is promoted as the standard for entry animations because it decouples motion logic from component mount cycles.

## Why Use @starting‑style for Entry Animations?

### Zero‑JavaScript Overhead

Traditional React patterns rely on `useEffect` to set a `data‑mounted` attribute or state variable after the first render. `@starting‑style` removes this boilerplate entirely. The browser computes the start state during layout, avoiding the extra render pass caused by mounting logic.

### GPU‑Friendly Performance

When you animate only `opacity` and `transform`, the animation runs on the compositor thread. The `@starting‑style` rule defines these properties as the initial state, and a `transition` animates them to the final values, keeping UI‑thread work minimal.

### Graceful Degradation

For browsers that do not support `@starting‑style` (older versions of Safari or Chrome), the repository provides a fallback strategy documented in [`STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/STANDARDS.md) (line 99). You can conditionally apply a `data‑mounted` attribute via JavaScript only when the CSS at‑rule is unsupported.

## Implementation Examples

### Basic Toast Entry Animation

The following snippet from `skills/review‑animations/STANDARDS.md` demonstrates a toast notification that slides up while fading in:

```css
.toast {
  /* Final state after entry */
  opacity: 1;
  transform: translateY(0);
  transition: opacity 400ms ease, transform 400ms ease;

  /* Initial state before the first paint */
  @starting-style {
    opacity: 0;
    transform: translateY(100%);
  }
}

```

The toast starts off‑screen and invisible. Once the page paints, the transition automatically animates to the final position.

### Fallback for Unsupported Browsers

When `@starting‑style` is unavailable, use the `data‑mounted` pattern as documented in [`STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/STANDARDS.md):

```css
/* Fallback for browsers without @starting-style support */
.toast[data-mounted] {
  opacity: 1;
  transform: translateY(0);
}

```

```javascript
// React component fallback
useEffect(() => {
  const el = ref.current;
  if (el) el.dataset.mounted = '';
}, []);

```

This achieves the same visual result while maintaining functionality in legacy environments.

### Respecting Reduced‑Motion Preferences

Accessibility is covered in the repository guidelines. Wrap the animation in a media query to disable transitions for users who prefer reduced motion:

```css
@media (prefers-reduced-motion: reduce) {
  .toast {
    transition: none;
    @starting-style {
      opacity: 1;
      transform: translateY(0);
    }
  }
}

```

The element appears instantly in its final state without animation.

### Staggered List Entry

Create cascading entrance effects by combining `@starting‑style` with custom properties:

```css
.list-item {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 300ms ease, transform 300ms ease;
  transition-delay: var(--delay);

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

```

Set individual `--delay` values (e.g., `0ms`, `50ms`, `100ms`) per item to achieve a sequential reveal without JavaScript timers.

## Key Files in the Repository

The following documents govern the usage of `@starting‑style` in the Instagit codebase:

- **`skills/review‑animations/STANDARDS.md`** – Core documentation defining the at‑rule syntax, example implementations, and fallback strategy (line 89).
- **`skills/review‑animations/SKILL.md`** – High‑level guide referencing the rule and explaining when to prefer CSS transitions over JavaScript (line 73).
- **`skills/improve‑animations/AUDIT.md`** – Auditing checklist that lists `@starting‑style` as the "entry without JS" pattern.
- **`skills/emil‑design‑eng/SKILL.md`** – Concrete component examples under the section "Animate enter states with @starting‑style".

## Summary

- **@starting‑style** defines an element’s initial state before the first paint, enabling CSS‑only entry animations.
- The technique eliminates `useEffect` hooks and `data‑mounted` attributes, reducing JavaScript overhead.
- Animations should target only `opacity` and `transform` to remain GPU‑friendly and performant.
- Use a `data‑mounted` fallback for browsers lacking support, as documented in [`STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/STANDARDS.md) line 99.
- Always wrap animations in `prefers‑reduced‑motion` media queries to respect accessibility preferences.

## Frequently Asked Questions

### What browsers support @starting‑style?

Modern versions of Chrome and Edge support `@starting‑style`, while older versions of Safari and legacy Chrome releases lack support. The `emilkowalski/skills` repository recommends implementing a `data‑mounted` fallback for these cases, ensuring animations degrade gracefully without breaking functionality.

### Can I use @starting‑style for exit animations?

No, `@starting‑style` applies only to entry states before the first paint. For exit animations, you must use JavaScript to add a class or attribute that triggers a transition, then remove the element from the DOM after the animation completes. The repository distinguishes between entry (CSS‑only) and exit (JS‑required) patterns in the animation standards.

### How does @starting‑style improve performance?

By defining the start state in CSS, the browser calculates the initial layout during the first paint without waiting for JavaScript execution. This avoids the layout shift and extra render pass typically caused by React `useEffect` hooks setting mount states. Combined with `transform` and `opacity` transitions, the animation runs entirely on the compositor thread.

### Is @starting‑style accessible for users with motion sensitivities?

Yes, when implemented correctly. You should wrap the `@starting‑style` block and its associated transitions in a `@media (prefers-reduced-motion: reduce)` query. This disables the animation for users who request reduced motion while ensuring the content appears immediately in its final state, maintaining usability without vestibular discomfort.