Stage 2 — CSS and Game Styling
In Stage 2 you write all the CSS for the game. There is no game logic yet — this stage is entirely visual. By the end you will have the dark gradient canvas, the HUD positioned at the top, and the Start screen looking like it belongs.
What you will build
Section titled “What you will build”- The complete
style.cssfor the game
Checkpoint: open index.html — the canvas should show a deep blue-to-purple gradient, the “Bubble Pop” title should appear in a violet gradient, and the Play button should be styled.
Step 1 — Reset and base styles
Section titled “Step 1 — Reset and base styles”Every browser applies default margins, padding, and box-sizing rules that will interfere with a full-viewport game. Start with a reset:
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0;}
body { background: #0a0a1a; display: flex; justify-content: center; align-items: center; min-height: 100vh; font-family: 'Segoe UI', system-ui, sans-serif; color: #fff; overflow: hidden;}box-sizing: border-box— padding and borders are included in element dimensions, not added on top.display: flexonbody— centres the game container both horizontally and vertically on any screen.overflow: hidden— prevents scrollbars from appearing when a bubble reaches the edge.
Step 2 — Game container and canvas
Section titled “Step 2 — Game container and canvas”The container is a fixed-size rectangle. The canvas fills it completely.
#game-container { position: relative; width: 480px; height: 640px;}
#game-canvas { display: block; width: 100%; height: 100%; border-radius: 12px; background: linear-gradient(180deg, #0d1b4b 0%, #1a0d3b 100%); box-shadow: 0 0 40px rgba(100, 60, 220, 0.4);}position: relativeon the container — establishes a positioning context for the HUD and screens, which will beposition: absolute.width: 100%on the canvas — stretches the canvas CSS display to fill the container. The actual pixel grid (canvas.width/canvas.height) was set in JS at 480 × 640. CSS stretches or shrinks the displayed result without changing the pixel grid.backgroundon the canvas — visible before the first JS draw call and between frames while the canvas is cleared.
Step 3 — HUD
Section titled “Step 3 — HUD”The HUD shows score, level, and lives across the top of the canvas.
#hud { position: absolute; top: 12px; left: 0; width: 100%; display: flex; justify-content: space-between; padding: 0 16px; font-size: 14px; font-weight: 600; letter-spacing: 0.04em; text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6); pointer-events: none;}position: absolute— floats the HUD on top of the canvas. It is positioned relative to#game-container(the nearest positioned ancestor).pointer-events: none— allows clicks to pass through the HUD to the canvas underneath, so clicking a bubble near the HUD still registers.
Step 4 — Screens
Section titled “Step 4 — Screens”Both overlay screens share a .screen class. The game-over screen also starts with .hidden.
.screen { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 16px; border-radius: 12px; background: rgba(10, 10, 26, 0.85); backdrop-filter: blur(4px); text-align: center; padding: 32px;}
.screen.hidden { display: none;}inset: 0— shorthand fortop: 0; right: 0; bottom: 0; left: 0. Stretches the screen to fill the container.backdrop-filter: blur(4px)— blurs what is behind the overlay, giving a frosted-glass effect..screen.hidden { display: none }— toggled by JS to show and hide screens. When a screen is hidden, it is completely removed from layout and not interactive.
Step 5 — Screen headings and text
Section titled “Step 5 — Screen headings and text”.screen h1 { font-size: 56px; font-weight: 800; letter-spacing: -0.02em; background: linear-gradient(135deg, #a78bfa, #60a5fa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; line-height: 1;}
.screen h2 { font-size: 42px; font-weight: 800; background: linear-gradient(135deg, #f87171, #fb923c); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;}
#high-score-display,#final-score { font-size: 20px; color: #c4b5fd;}
#new-high-score { font-size: 18px; font-weight: 700; color: #fbbf24; animation: pulse 0.8s ease-in-out infinite alternate;}
#new-high-score.hidden { display: none;}
.instructions { font-size: 15px; color: #94a3b8; max-width: 280px;}The gradient text technique clips the gradient to the text shape using background-clip: text and makes the text itself transparent with -webkit-text-fill-color: transparent. It requires both the prefixed and unprefixed versions for browser compatibility.
Step 6 — Button
Section titled “Step 6 — Button”button { margin-top: 8px; padding: 14px 48px; font-size: 18px; font-weight: 700; border: none; border-radius: 50px; cursor: pointer; background: linear-gradient(135deg, #7c3aed, #2563eb); color: #fff; box-shadow: 0 4px 20px rgba(124, 58, 237, 0.5); transition: transform 0.1s, box-shadow 0.1s;}
button:hover { transform: translateY(-2px); box-shadow: 0 6px 28px rgba(124, 58, 237, 0.65);}
button:active { transform: translateY(0);}The border-radius: 50px on a wide button creates a pill shape. The transform: translateY(-2px) on hover gives a subtle lift effect.
Step 7 — Pulse animation
Section titled “Step 7 — Pulse animation”The “New High Score!” message uses a keyframe animation:
@keyframes pulse { from { opacity: 0.7; } to { opacity: 1; }}Checkpoint
Section titled “Checkpoint”Open index.html. You should see:
- A dark blue-to-purple gradient canvas with a soft purple glow
- The “Bubble Pop” title in a violet-to-blue gradient
- “Best: 0” in light purple below the title
- Instructions text in muted grey
- A purple-to-blue pill button labelled “Play”
The HUD at the top shows “Score: 0 Level: 1 Lives: 3” but there is no layout yet — it overlaps the start screen. That is fine. Once the game starts (Stage 3), the start screen will be hidden and the HUD will be visible on its own.
What’s next
Section titled “What’s next”In Stage 3 you will implement the game loop using requestAnimationFrame, populate the POP.config object with all game settings, and write the Bubble class that draws gradient bubbles on the canvas.