Skip to content
tezvyn:

Create a staggered list fade-in using only CSS

Source: developer.mozilla.orgMediumHow cards are made

Create a staggered list fade-in using only CSS

Tests CSS animation orchestration via keyframes and delay strategies. Great answers use :nth-child or --index variables for scalable staggering, set fill-mode forwards, and honor prefers-reduced-motion.

What's really being asked

This question evaluates your understanding of CSS animation sequencing, selector efficiency, and performance-conscious rendering. The interviewer wants to see if you can coordinate multiple elements without JavaScript, use declarative timing controls, and respect accessibility and compositor constraints.

The full answer

First, define a reusable @keyframes rule such as fadeIn that animates opacity from 0 to 1 and optionally a subtle translateY for lift. Second, apply the animation to the list items with a base duration and set opacity to 0 initially so items are invisible before the animation runs. Third, stagger the start times. The scalable approach uses an inline custom property like --index on each item and a CSS calc expression for animation-delay, for example calc(var(--index) * 100ms). An acceptable fallback is :nth-child(n) with increasing delay values. Fourth, set animation-fill-mode to forwards so each item retains its visible state after the animation completes rather than snapping back to opacity 0. Fifth, keep the animation compositor-friendly by animating only opacity and transform, avoiding layout-triggering properties like height, width, or margin. Sixth, wrap the animation rules in a prefers-reduced-motion media query to disable or simplify motion for users who need it.

The mistakes people make

Proposing JavaScript loops or setTimeout immediately fails the only CSS constraint. Using transition instead of animation is a weaker answer because transitions require a state change trigger and are harder to sequence declaratively. Hardcoding a separate class for every list item to set its delay is unmaintainable. Forgetting animation-fill-mode forwards causes items to vanish after fading in. Animating properties that force layout or paint recalculations, such as top or margin, signals poor performance awareness.

What usually comes next

How would you handle an unknown number of items generated dynamically? The answer is to render an inline style with --index on each DOM node and let CSS calc derive the delay. What if the list is very long? You might cap the maximum delay or use a logarithmic stagger. How do you keep this accessible? You respect prefers-reduced-motion by setting animation-duration to 0s or removing the animation entirely. What about performance at scale? The rendering engine can skip frames for offscreen tabs, but animating only compositor properties keeps the main thread free.

A concrete example

For a list of five items, define @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }. Then set li { opacity: 0; animation: fadeIn 300ms ease forwards; } and li:nth-child(1) { animation-delay: 0ms; } li:nth-child(2) { animation-delay: 100ms; } through the fifth. Alternatively, set style="--index: 0" on each li in markup and use li { animation-delay: calc(var(--index) * 100ms); }.

Interview question

For a staggered CSS fade-in where the number of list items is determined at runtime, which approach best scales the delay calculation without JavaScript?

  • a.Hardcode a unique class for every possible item index
  • b.Use :nth-child selectors with preset delays up to a fixed maximum
  • c.Rely on transition-delay with hover states to trigger sequencing
  • d.Apply an inline --index custom property and use calc() for animation-delayCorrect
Why?

An inline --index with calc() lets the browser derive delays for any number of items declaratively. B is a workable fallback but cannot handle an arbitrary runtime count, while A is unmaintainable and D incorrectly uses transitions that require a state change trigger.

Just read this? Test yourself on what you have been reading.

Read the original → developer.mozilla.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on css — each one lists the topics its interview covers.

See open roles