Making Magic with CSS — Starfield Backgrounds and 3D Card Flips

 


A Tarot App Without Animation Is a Card That Never Flips

The most dramatic moment in a tarot reading is when the card flips. The tension as a card slowly turns in your hand. The thrill when the face is revealed. If you implement this on the web as "click and the image swaps," all of that emotion evaporates.

So I decided to invest seriously in animation. From the background to card interactions, the goal was to see how far CSS and Framer Motion alone could take the experience. The verdict: much further than I expected.

A Starfield Background: Triple-Layered radial-gradient

The navy background (#0a0a1a) is beautiful on its own, but by itself, it is flat. A night sky without stars is just a dark ceiling. There are many ways to create a starfield — Canvas API, SVG animations, even a static star image. But the lightest and most elegant method turned out to be layering CSS radial-gradient.

The core idea is simple. Extremely small radial gradients repeated across the background look like stars. Split them into three layers of different sizes, and you get depth. Make the smallest stars drift fastest, the medium ones at normal speed, and the largest ones slowly, and you achieve a parallax effect.

The first layer consists of tiny 1px stars scattered densely across the screen, resembling a distant galaxy. The second layer uses 2px stars — a bit brighter, a bit more sparse. The third layer uses 3px stars — the brightest and most scattered. All three layers are chained together in a single background property using commas.

Add CSS animations that move each layer's background-position at different speeds, and the stars gently drift across the screen. The smallest stars cycle every 60 seconds, the medium ones every 90, and the large ones every 120. These subtle speed differences create a remarkable sense of depth on a flat screen.

The 3D Card Flip: The Aesthetics of 0.8 Seconds

The card flip animation was one of the most time-intensive parts of the project. The basic principle of CSS 3D transforms is straightforward. Stack a front face and a back face on top of each other, then rotate the parent 180 degrees on the Y axis. Apply backface-visibility: hidden to the back face, and it disappears automatically when flipped.

But there is a vast gap between "technically works" and "feels good." Initially, I set the transition duration to 0.3 seconds — the standard for typical UI interactions. It was too fast. The card did not "flip" — it "switched." There was no tension.

I tested 0.5s, 0.6s, 0.8s, 1.0s, and 1.2s. The winner was 0.8 seconds. The card starts flipping slowly, accelerates through the middle, and decelerates slightly as the face is revealed. This "weight" most closely mimicked the physical sensation of flipping a real card with your hand.

The secret ingredient is the easing function cubic-bezier(0.4, 0, 0.2, 1). It is Google Material Design's "standard easing" curve, known for its natural deceleration. It is especially effective when mimicking the motion of physical objects, like cards.

What Framer Motion Adds

CSS 3D transforms alone can handle a card flip. So why add Framer Motion? Two reasons. First, to seamlessly connect React state changes with animations. With CSS alone, synchronizing "the card is flipped" and "the card is not yet flipped" with React state is tricky.

Second, sequential card reveals were needed. In a three-card spread, having all three cards flip simultaneously is anticlimactic. The first card flips, then 0.3 seconds later the second, then 0.3 seconds later the third — this stagger effect is far more dramatic. Framer Motion's staggerChildren accomplishes this in a single line.

The final implementation combines Framer Motion's animate prop for controlling rotateY values with CSS's perspective property for 3D depth. Perspective was set to 1000px — too small and the card warps excessively, too large and the 3D effect fades.

Reversed Cards: Subtle Handling After the Flip

Tarot includes the concept of reversed (inverted) cards. When a card appears upside down, it carries a different meaning from the upright position. Reflecting this in animation was a tricky problem.

My first attempt was to pre-rotate the card 180 degrees before the flip, so it would appear upside down when revealed. But this also made the back face appear upside down — a subtle but potentially unsettling visual glitch.

The final solution applied the reversal rotation after the Y-axis flip was fully complete. Once the flip finishes and the face is visible, a 180-degree rotation is immediately added. This second rotation happens quickly (0.2 seconds), making it feel like a natural extension of the flip animation rather than a separate action.

Card Backs: The Power of Restraint

I put thought into the card back design as well. Initially, I planned an elaborate pattern. But through discussion with AI, I reached a different conclusion. If the back is visually busy, it diminishes the impact when the face is revealed.

The final design is restrained: the navy background with a gold border, and a single small star motif in the center. This transition from "simple back" to "vivid face" maximizes the dramatic effect of the flip animation. Like a card glowing as it emerges from darkness.

This is a design principle that is often overlooked. To make something stand out, you must suppress its surroundings. AI understood this principle well, and the fact that it proactively suggested simplifying the back design was impressive.

The Potential of CSS Without Libraries

What this work confirmed is that CSS remains remarkably powerful. Without Three.js or WebGL, the combination of pure CSS properties alone can produce a striking visual experience. The starfield uses not a single image file. The card flip relies on basic CSS 3D transform features.

There are limitations, of course. Scaling to hundreds of stars can affect performance, and complex particle effects are beyond what CSS can handle alone. But for the goal of "creating atmosphere," CSS proved sufficient. The ability to significantly enhance user experience without inflating bundle size makes CSS's value-for-effort ratio hard to beat.

AI collaboration was especially productive for CSS-related questions. "I want to create this effect — is it possible with CSS?" almost always led to a viable solution. When it was not possible, alternatives were suggested, and those judgments were nearly always accurate.

Next Up

The screen is coming together. Stars drift across the background. Cards flip beautifully. But one fundamental problem remains unsolved: where do I get the images for 78 tarot cards? In the next part, I will share the story of scouring the internet for free images, stumbling into copyright traps, and the embarrassing moment when AI-suggested URLs turned out not to exist.

댓글

이 블로그의 인기 게시물

사랑을 직접 올리지 않는 설계

감정을 변수로 옮기다 — 3계층 감정 모델

시작의 충동 — "타로 웹앱을 만들어볼까?"