Designcember: A 31-day web calendar built with container queries and Astro

Designcember is a holiday-style advent calendar that highlights one piece of UI and design content each day throughout December. The final site includes 26 demo sites, tools, announcements, podcasts, videos, articles, and case studies — 31 pieces of content in total, each represented by a window in an illustrated apartment building.

The project, available at designcember.web.app, was built with a few goals in mind: keep the payload minimal, make the experience accessible and responsive, and demonstrate modern CSS APIs like container queries in a real production context.

From sketch to responsive grid

Working with illustrator Alice Lee, the team designed a whimsical apartment building whose windows rearrange themselves within the building frame as viewport space changes. Each window in the building maps to one day of content from the calendar.

The team first explored grid-auto-flow: dense for auto-placing windows inside the building grid. While aspect-ratio grids worked well for displaying the artwork, they quickly discovered a limitation: they didn't let individual windows flex into non-uniform spaces where they could grow and shrink unpredictably. That's where container queries took over, letting each window respond to its own turbulence — squeezing, stretching, or recomposing itself independently of its neighbors.

Window animation techniques

Several windows feature hand-drawn animations, created frame by frame in Photoshop. Individual frames were exported to a spritesheet via a spritesheet generator and then optimized with Squoosh. The CSS animation drives the sprite frames using background-position-x combined with animation-timing-function.

Some animations, like the piggy bank on day six, use step-based CSS instead. The technique is similar — sprite images advanced via steps() — but the keyframes animate CSS transform positions rather than background positions.

CSS masks for custom window shapes

Windows with unique shapes relied on masks and aspect-ratio to keep artwork scalable and properly framed. For day eight, the four-leaf clover shape inside the window frame was isolated and filled white in Photoshop — white content stays visible within a mask, while the surrounding area is hidden. The mask was feathered by 1px at export time to avoid aliasing artifacts and saved at the same dimensions as the window frame, so the frame and mask could layer cleanly.

The masking also enables dark mode styling. The same window can render with different gradients and glow filters applied to its contents without breaking the custom frame shape.

Optimization beyond defaults

The original artwork shipped at 3x pixel density to keep edges crisp on high-DPI screens. The plan was to serve compressed images through imgix, but manually optimizing with Squoosh turned out to be significantly more effective — often cutting file sizes by 50% or more. Post-Photoshop PNGs were re-exported at smaller PNG, WebP, and AVIF sizes. Given 200+ images and more than 50 needing custom experiments to find the right settings, the Squoosh CLI became a practical necessity, batch-processing entire folders at the found compression settings.

With optimized images committed to the repo, the team used a reusable Astro component to avoid repeating verbose image source markup. An example AVIF CLI command is demonstrated in the source project’s package.json scripts.

Accessibility: a narrated experience

Scale and whimsy don't mean much if the content is inaccessible. The team made a deliberate choice to mark embedded images with role="presentation" rather than providing individual alt text for each window. They reasoned that five to twelve fragmented descriptions per page would degrade the experience, so each window instead gets a single summary narration. That keeps screen reader navigation between windows narrative and consistent.

Keyboard interaction is orchestrated across Tab, Enter, Spacebar, and Escape keys to move focus in and out of window popups. ARIA attributes clarify ambiguous text like "one" or "two" so screen readers announce "Day one" and "Day two" instead.

Why Astro was the right fit

The site ran on Astro, a static-first component-driven generator. Astro's approach had clear advantages for the team: its component model felt familiar to developers coming from React or Angular, and scoped styles meant multiple developers could work on separate windows without colliding on class names.

Componentized days and build-time data

Each day on the calendar is an Astro component that pulls from a build-time data store, so template logic — like whether a day's tooltip should render — runs before HTML reaches the browser. A new day unlocks when the hourly builds occur past midnight, letting the site update itself without manual intervention.

Styling with props and caveats

Open Props provided responsive theme variables, and its normalize.css simplified typography, spacing, and adaptive light/dark themes. However, the team hit several snags with PostCSS while running as early Astro adopters and couldn't upgrade to the latest Astro version due to persistent build issues.

Container queries: solving what aspect ratios can't

The team used several windows that strictly preserve their art's aspect ratio and show growth and shrink behavior linearly with the viewport. But others showcase a more interesting capability: true container query support. Windows that scale down from wide to narrow — or grow from narrow to wide — need to dynamically reposition and resize their contents. Container queries let each window own its responsive sizing logic.

A short snippet shows the concept at a high level: size-dependent media adjustments (like altering text or media styles and position) driven by container-relative queries rather than by global media queries. That’s distinctly different from constantly maintaining an aspect ratio and provides more flexibility for creativity.

Block-direction query support also comes into play. The windows respond to both width issues but can adjust to changes in height as individual windows stretch vertically, showing how the CSS container query model naturally covers two dimensions.

Window nine is a demo where detail artifacts appear, vanish, and move as its container grows and shrinks, making those fine-grained changes without changing the source of truth for each window's layout logic.

Making the effect work everywhere

Because container queries are still an experimental technology, the team built a dedicated polyfill to bring the experience to a wider audience. Led by Surma, it depends on ResizeObserver, MutationObserver, and the CSS :is() function. That combination means support spans Chrome and Edge from version 88, Firefox from version 78, and Safari from version 14. With the polyfill, you can use any of these syntaxes:

/* These are all equivalent */
@container (min-width: 200px) {
  /* ... */
}
@container (width >= 200px) {
  /* ... */
}
@container size(width >= 200px) {
  /* ... */
}

A dark mode built on layering

Dark mode on Designcember was treated as a chance to let the artwork take an active role rather than simply swapping palette tokens. The background of each window is adjusted programmatically, and gradients are used as much as possible to make color values easy to tweak. The art is then layered on top of those adjustable backgrounds.

The light and dark mode versions of the Designcember site, side-by-side.

Details that add personality and function

A few flourishes give the site its character. A cast of characters drawn from the team adds personality, an old-school cursor appears on the inactive "windows," and the favicon gets its own seasonal variations.

Custom cursor styles and favicon options

On the functional side, a "Jump to Today" feature uses a bird perched on the building to scroll straight to the current day of the month. The site also ships a dedicated print stylesheet, rendering the calendar at a resolution suited for standard 8.5" x 11" paper so you can print a physical copy.

Poster-sized print of the calendar design.
Una holding a large print of the calendar.

Designcember is a lot of moving parts: art, interactivity, and a brand-new polyfill, all brought together to mark each day of December with a modern web experience.

Parts of the calendar with annotations and visual notes