A cinematic web experience that lets users capture memories as digital polaroid photographs. Built with vanilla web technologies, it recreates the tactile nostalgia of instant film photography through interaction design and animation.
Digital Polaroid treats memory capture as a deliberate, meaningful ritual rather than a quick snapshot. The user is guided through a three-step process: writing their memory, selecting its emotional tone, and optionally attaching a photograph. Each completed entry develops on screen like physical instant film, gradually revealing the image and caption through a carefully timed animation sequence.
The aesthetic draws from vintage digicam interfaces, darkroom culture, and the physicality of the polaroid format — dark surfaces, amber tones, film grain, and the unmistakable white border of an instant print.
The application opens with a camera initialization animation including a viewfinder graphic, sequential status messages, and a title reveal. This sequence establishes the camera metaphor before any interaction begins.
Three sequential steps guide the user through the capture process:
- Memory Text — A textarea for writing the memory description, with a live character counter and a 240-character limit. Pressing Enter advances to the next step; Shift-Enter inserts a newline.
- Mood Selection — Six mood tones (Warm, Nostalgic, Dreamy, Quiet, Bright, Midnight) that simultaneously change the background atmosphere of the entire interface.
- Image Upload — An optional file upload step using the FileReader API. Supports JPG, PNG, WEBP, and GIF. Drag-and-drop is also supported. If no image is uploaded, a styled text-only polaroid is generated instead.
Before a polaroid is created, a brief autofocus overlay appears with corner brackets and an AF indicator, followed by a full-screen white flash simulating a camera shutter.
Each new polaroid begins nearly black and develops over approximately 3.5 seconds using CSS filter animations on brightness, contrast, and saturation. The caption and timestamp fade in after development completes.
All captured polaroids remain on screen permanently in a stacked wall layout. Cards are rendered with slight random tilts for a physical, scattered-on-a-table appearance. The most recently captured memory always appears first. Memories accumulate across multiple captures within the same session.
A dedicated control bar appears after the first memory is captured and remains visible at all times. It contains three buttons:
- Capture Another Memory — returns the step wizard to step 1 without clearing the existing memory wall.
- Download Latest PNG — exports the most recently developed polaroid as a high-quality PNG using the Canvas API.
- SFX OFF / SFX ON — toggles the ambient shutter sound on or off.
After completing a capture, the step wizard is hidden but the memory wall remains visible. Clicking "Capture Another Memory" (either in the action panel or the stack header) slides the wizard back into view above the wall. No page reload occurs and no existing polaroids are removed.
The background atmosphere responds to the selected mood using CSS custom property transitions and radial gradients, creating a different environmental feel for each of the six tones. The atmosphere persists and continues to reflect the last selected mood between captures.
Hovering over any polaroid card straightens its tilt, slightly scales it up, and elevates it with a deeper shadow, simulating the act of picking up a physical print.
Each polaroid card includes a Save PNG button that appears on hover, and the action panel includes a persistent Download Latest PNG button. Both use the Canvas API to render a high-quality (440x540px) version of the polaroid for download, including the photo or text, mood tint, caption, and timestamp.
A manual sound toggle is available both in the header and in the persistent action panel. Activating it initializes the Web Audio API context and enables a synthesized shutter click sound on each capture. Sound is never activated automatically; it requires explicit user action. Both toggle controls remain synchronized at all times.
digital-polaroid/
|-- index.html Main HTML document with all semantic structure and meta tags
|-- style.css All visual styling including animations, layout, and mood themes
|-- polaroid.js Polaroid rendering module: DOM card builder and Canvas exporter
|-- script.js Main application controller: state, events, boot sequence, wizard
|-- README.md This document
|-- LICENSE MIT License
index.html Declares the full DOM structure including the boot overlay, flash overlay, three-step wizard, autofocus animation, and memory stack. Includes Open Graph meta tags and a favicon reference.
style.css Implements the visual system using CSS custom properties for theming. Contains the film grain overlay (SVG-based noise), vignette, boot sequence animations, step wizard layout, mood atmosphere transitions, polaroid card styling, and the film development keyframe animation.
polaroid.js
Exported as window.PolaroidModule. The buildPolaroidCard function constructs a complete polaroid DOM element from a memory object. The downloadPolaroid function uses the Canvas 2D API to render a standalone PNG image of the polaroid, handling both image and text-only modes with cover-fit image scaling and text wrapping.
script.js
Orchestrates the full application. Manages state in a single state object. Runs the boot sequence with timed status messages. Controls step navigation, mood selection with body class switching, image upload via FileReader, the capture sequence timing (autofocus delay, flash, polaroid creation), and optional Web Audio synthesis for the shutter sound.
Digital Polaroid requires no build tools, package manager, or server-side runtime. It runs entirely in the browser.
Option 1: Direct file access
- Download or clone the repository.
- Open
index.htmlin any modern browser (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+).
Option 2: Local development server (recommended) Using Python:
python3 -m http.server 8080Then open http://localhost:8080 in your browser.
Using Node.js (npx serve):
npx serve .Option 3: Static hosting deployment The project is deployment-ready for any static hosting platform:
- Netlify: Drag the project folder into the Netlify dashboard
- Vercel: Run
vercel deployfrom the project directory - GitHub Pages: Push to a repository and enable Pages from the repository settings
No environment variables, configuration files, or build steps are required.
| Feature | Requirement |
|---|---|
| CSS Custom Properties | Chrome 49+, Firefox 31+, Safari 9.1+ |
| Canvas API | All modern browsers |
| FileReader API | All modern browsers |
| Web Audio API | All modern browsers (sound feature only) |
CSS aspect-ratio |
Chrome 88+, Firefox 89+, Safari 15+ |
The following enhancements would extend the experience without compromising its current simplicity:
- Persistent storage — Use
localStorageorIndexedDBto retain the memory stack across browser sessions. - Polaroid string/board layout — Display memories hanging from a clothesline or pinned to a corkboard with CSS 3D transforms.
- Custom filters — Allow users to apply additional photographic filters (overexposed, faded, cyanotype) to uploaded images via canvas pixel manipulation.
- Memory export pack — A single-click option to download all polaroids as a ZIP archive.
- Handwriting font option — Replace the default caption font with a cursive or handwriting typeface for a more personal feel.
- Animated film roll transition — A horizontal film-strip scroll animation when moving from capture to the memory stack.
- Share link generation — Encode a single memory into a URL hash for sharing.
- Accessibility improvements — Full keyboard navigation for all interactive elements and ARIA live regions for animation state announcements.
Anshika Mittal
MIT License. See LICENSE for full terms.