Skip to content
CoDdleCoDoodle home
Canvas ScenesAdvancedHTML + CSS

Rainy Window

A looping weather scene — rain, cloud, and window bars, all CSS.

← you, in 45 minutes.

what you'll build

Here's the plan

A tiny looping weather scene — a cloud, five raindrops falling at slightly different times, and a window frame with bars on top. All CSS, no canvas, no JS.

You’ll learn

  • Faking a second shape for free with a ::before pseudo-element
  • Staggering identical animations with per-element animation-delay so nothing feels synced
  • Using overflow: hidden on a container to crop a whole scene like a window
  • Relying on source order (not z-index) to control what paints on top
Skill level
Advanced
Time
~45 min
Tools
Just a browser
Code type
HTML + CSS
Lines
~70

the steps

Build it, one change at a time

  1. Build the window frame

    A rounded, bordered box with overflow: hidden becomes a window the moment anything sits inside it — cropping does most of the scene-setting work here, before a single cloud or drop exists.

    <div class="window">
      <div class="sky">
        <div class="cloud"></div>
        <div class="drop d1"></div>
        <div class="drop d2"></div>
        <div class="drop d3"></div>
        <div class="drop d4"></div>
        <div class="drop d5"></div>
      </div>
      <div class="bar bar-v"></div>
      <div class="bar bar-h"></div>
    </div>
    
    .window {
      position: relative;
      width: 200px;
      height: 180px;
      border: 8px solid #2B3A55;
      border-radius: 18px;
      overflow: hidden;
      background: #E6EFFF;
    }
    .sky { position: absolute; inset: 0; }
    

    an empty window looking out at a flat blue sky.

  2. Hang a cloud

    A ::before pseudo-element lets one div draw two shapes — a wide rounded rectangle plus a smaller rounded bump stacked on top, no extra markup needed.

    .cloud {
      position: absolute;
      top: 18px;
      left: 30px;
      width: 76px;
      height: 26px;
      background: #FFFDF7;
      border: 5px solid #2B3A55;
      border-radius: 20px;
    }
    .cloud::before {
      content: "";
      position: absolute;
      top: -18px;
      left: 16px;
      width: 34px;
      height: 26px;
      background: #FFFDF7;
      border: 5px solid #2B3A55;
      border-bottom: none;
      border-radius: 20px 20px 0 0;
    }
    

    one small cloud, doing its best.

  3. Make it rain, unevenly

    Five identical drops with five different animation-delay values fall the same way at different moments — the staggering is the entire trick that makes rain read as rain instead of a repeating pattern.

    .drop {
      position: absolute;
      top: -14px;
      width: 7px;
      height: 14px;
      background: #6FA8FF;
      border-radius: 50% 50% 60% 60%;
      animation: fall 1.6s linear infinite;
    }
    .d1 { left: 18%; animation-delay: 0s; }
    .d2 { left: 36%; animation-delay: 0.6s; }
    .d3 { left: 54%; animation-delay: 0.25s; }
    .d4 { left: 70%; animation-delay: 0.95s; }
    .d5 { left: 85%; animation-delay: 0.45s; }
    @keyframes fall {
      to { transform: translateY(200px); }
    }
    

    rain! Five drops, five different delays, so it never looks synced.

  4. Add the window bars on top

    The bars sit on top of the weather because they come later in the HTML, not because of any z-index — a good reminder that source order controls stacking before you reach for it.

    /* the window bars sit on top of the weather */
    .bar { position: absolute; background: #2B3A55; }
    .bar-v { top: 0; bottom: 0; left: 50%; width: 8px; margin-left: -4px; }
    .bar-h { left: 0; right: 0; top: 50%; height: 8px; margin-top: -4px; }
    

    the finished rainy window, bars and all.

the complete code

Everything, in one place

Skipped straight to the end? Welcome. Copy the whole thing, download it, or open it in the Playground to start remixing.

<div class="window">
  <div class="sky">
    <div class="cloud"></div>
    <div class="drop d1"></div>
    <div class="drop d2"></div>
    <div class="drop d3"></div>
    <div class="drop d4"></div>
    <div class="drop d5"></div>
  </div>
  <div class="bar bar-v"></div>
  <div class="bar bar-h"></div>
</div>
Open in Playground

tips & gotchas

Mistakes we actually made

If the rain looks like it's falling in lockstep, check every .dN has its own animation-delay — one shared value defeats the whole trick.

overflow: hidden on .window is what turns "a cloud floating in space" into "a cloud you can see through a window" — cropping is doing a lot of the work.

The bars sit on top because they come later in the HTML, not because of any z-index. Simpler is usually available before you reach for stacking contexts.

make it yours

Remix it

  • Night raineasy

    Darken the sky background and drop colors for a nighttime storm.

  • Snow insteadeasy

    Swap the drop shape for small circles and slow the fall duration way down.

  • Lightningmedium

    A full-screen white ::after that flashes opacity briefly on a long, irregular timer.

  • More weathermedium

    Add a second, smaller cloud drifting slowly left to right with translateX.

challenge extension

Same staggering trick, new scene: draw a night sky where five stars twinkle (opacity, not position) each on its own delay.