Skip to main content
Prakriti Bista

Project dossier / Creative Engineering

Polaroid Camera

A fun, interactive polaroid camera in the browser. Click, capture, and watch your shot develop in real time.

Role

Sole engineer and designer. Designed the camera UI in CSS, built the capture and develop animation in JavaScript, shipped with zero dependencies.

2 weeks · 2025

Result signals

  • Zero dependencies
  • Real-time capture
  • Polaroid develop animation
  • Pure vanilla JS

Evidence board

A fun, interactive polaroid camera in the browser. Click, capture, and watch your shot develop in real time.

2 weeks · 2025Creative Engineering

Question

What was the hard part?

A fun, interactive polaroid camera in the browser.

System

Creative Engineering

HTML5 / CSS3 / JavaScript

Evidence

Zero dependencies

The develop animation convincingly mimics the physical Polaroid experience.

Decision

Constraint shaped the interface

Zero dependencies, zero build tools.

Artifacts linked above

Polaroid Camera
Primary artifact · interact with the real thing ↗

Because browsers should be fun

This one started with a simple question: can you build a polaroid camera in a browser, with no libraries, no canvas hacks, and no dependencies at all?

The answer is yes. It took about a weekend.

The idea

Polaroid cameras have a specific ritual. You point, you click, the shot ejects slowly, and then you wait. The image develops from nothing, detail by detail. That delay is the whole experience. It's not a bug. It's the point.

Most digital photo effects skip the development part. They apply a filter instantly and call it done. I wanted to actually simulate the wait, the slow reveal from a washed-out white to a developed image, because that tension is what makes it feel like a polaroid rather than an Instagram filter.

Building it without frameworks

The camera UI is pure CSS. The lens, the body, the viewfinder, the shutter button: all box model and border-radius, no images, no SVGs. It's a fun constraint. CSS is surprisingly capable of mimicking physical objects when you lean into it.

The capture flow works in three steps. First, the browser grabs a frame from the webcam stream. Second, it draws that frame onto a hidden canvas element to get the pixel data. Third, it ejects an animated polaroid card and runs the development sequence: a CSS transition that fades the image in from white over a few seconds, timed to feel like the real thing.

Capture pipeline · hand-written JS

getUserMedia

Live webcam, 1080² ideal

MediaStream into a <video>, lifecycle handled by hand

canvas · toDataURL

Freeze the frame

One of four CSS filter grades re-applied via ctx.filter on export

CSS transition · 14s

Develop, white → image

A long filter + opacity ease — the wait is the whole experience

No image libraries. Just getUserMedia, a hidden canvas, and CSS. The develop is a 14-second filter-and-opacity transition, slow on purpose, and the shutter and whir are synthesized live with the Web Audio API.

The development animation was the part I tuned most. Too fast and it feels like a filter. Too slow and you lose interest. The transition itself runs about fourteen seconds, but it's eased so the image rushes up over the first few seconds and then finishes slowly, the way a real photo settles. That front-loaded curve is what sells it: you read the picture quickly, but the slow tail keeps the whole thing feeling like it's developing rather than just loading.

What vanilla JS taught me here

Working without a framework means managing the webcam stream lifecycle manually. Starting it, pausing it, cleaning it up when the tab loses focus. None of that is complicated, but doing it by hand makes you understand what the browser is actually doing. The getUserMedia API, the MediaStream object, the track lifecycle: you don't have to think about any of this in a framework because it abstracts it away. Writing it directly made me much more comfortable with browser APIs generally.

The canvas capture is similarly instructive. Drawing a video frame to canvas, reading back the pixel data, applying the polaroid color grade as a series of pixel-level operations: this is the kind of thing that's usually hidden behind an image processing library. Doing it manually is slower to write but faster to understand.

Just a fun thing

Not everything needs to be a production system. Sometimes the whole point is making something that makes people smile when they use it. This does that.

What Worked

  • The develop animation convincingly mimics the physical Polaroid experience. The slowdown at the end is the detail that makes it feel real.
  • Zero-dependency approach means instant load: no bundle, no parse time, nothing between the user and the camera
  • Camera UI entirely in CSS is a genuine flex; it looks like a camera because the layout is doing the work

What Didn't

  • WebRTC camera access requires HTTPS and explicit user permission; some browsers add friction here
  • No save functionality; the photo disappears on refresh, which is in-character for Polaroid but frustrates users who want to keep shots

Built with

HTML5CSS3JavaScript