DEV Community

Cover image for Introducing Popkorn: a portable, CSS-based format for interactive motion graphics
ayaz
ayaz

Posted on

Introducing Popkorn: a portable, CSS-based format for interactive motion graphics

CSS is capable of expressing a lot when it comes to graphics, especially animation. Popkorn takes that idea and runs with it: a portable format + runtime for motion graphics, where you write a scene in syntax you already know and run the same file on the web and on native mobile.

It renders some genuinely complex stuff, and it brings in almost any Lottie file without breaking anything, usually at a lower file size than the source. And it isn't just playback: scenes can be genuinely interactive, with :hover and :active states, state machines, and live inputs, all without a line of scripting. It started as a personal what-if and turned into a proof of concept that went further than I expected. It's still very early, but the idea clearly works.

A complete scene

Here's an entire Popkorn scene: a ball, falling and bouncing, that warms in color when you point at it.

:root {
  width: 400px;
  height: 400px;
  background: #1a1a2e;
}

@keyframes bounce {
  0% {
    transform: translateY(0);
    animation-timing-function: cubic-bezier(0.33, 0, 1, 1);
  }
  50% {
    transform: translateY(180px);
    animation-timing-function: cubic-bezier(0, 0, 0.67, 1);
  }
  100% {
    transform: translateY(0);
  }
}

#ball {
  type: circle;
  cx: 200px;
  cy: 80px;
  r: 36px;
  fill: #ff6b6b;
  animation: bounce 1.2s linear infinite;
  transition: fill 250ms ease;
  &:hover {
    fill: #ffd166;
  }
}
Enter fullscreen mode Exit fullscreen mode

If you've written CSS, you can already read every line. Point at the ball and the transition warms its color while the bounce never pauses or restarts. That's one of the nicer surprises: interactive states like :hover compose on top of a running animation instead of fighting it, because the whole scene plays on one continuous timeline.

Why CSS

This is the whole idea, not a shortcut. Popkorn holds itself to one rule: if CSS already has a way to express something, use it, with its real semantics. Motion paths are offset-path. Holds are step-end. Staggering is a negative animation-delay. Layering is z-index. It never invents syntax CSS already has. (It isn't exactly CSS. It's a close dialect, kept as near to the real thing as possible, and maybe some good parts go upstream one day 🤞)

Staying this close buys something rare: one format two very different audiences already read.

  • People already speak it. There's a vibrant community making genuinely beautiful art in hand-written CSS. Popkorn meets them where they are, with no new mental model.
  • Language models already speak it too, for free. Because the format is CSS-shaped, a model writes valid Popkorn from its existing training data with minimal guidance. No fine-tuned model, no bespoke format to teach. The playground's example gallery is itself entirely LLM-generated.

The payoff is a format that's hand-authorable, diffable in a pull request, and generatable by an LLM, all at once. And because scenes are just .css, you get syntax highlighting free on GitHub and in every editor.

Bring your own Lottie, then just ask for changes

Here's the part I find most fun. Drop an existing Lottie file (or an SVG) into the playground and it converts, unchanged, into a readable Popkorn scene that plays back faithfully. No re-authoring, no cleanup pass. But now it's plain, CSS-shaped text, so you can keep going: ask the Copilot to recolor it, slow the timing, change the motion, or wire in a :hover state, all in natural language, on a file you can also open and edit by hand. An opaque Lottie JSON blob becomes something you can actually converse with.

What it can do today

It already renders vector shapes, gradients, masks, motion paths, and path morphing, with @keyframes animation, per-keyframe easing, and holds. It goes beyond playback too: :hover and :active just work, and hand-written state machines drive toggles, taps, and app-state behavior with no scripting. It even imports real Lottie files and SVGs into readable scenes you can tweak on the spot, often coming out a touch smaller than the source they came from.

In the browser it works well, with two renderers behind it (Canvas2D and SVG). The same scenes run on mobile through a React Native + Skia renderer. It's early: the surface is still growing and the clearest frontier is performance work. But the idea, that a CSS animation can be a portable artifact, is looking promising.

Try it

No install, it runs in your browser: ayarse.github.io/popkorn. Edit the example scenes live, prompt the built-in Copilot to build one from a description, or drop in a Lottie or SVG and watch it convert. The code lives on GitHub under MIT.

What's next, and getting involved

The near-term focus is performance: deeper optimization and benchmarking, and hardening the native renderer. Longer term, the interesting questions are about the format itself, how far a close CSS dialect can stretch before it needs to invent something new, and which of those good parts might belong in real CSS one day.

This is a what-if that turned out to work, shared in case the idea is as interesting to you as it was to build. If you make something with it, break it, or just have a strong opinion about the syntax, I'd love to hear it. Feedback and curiosity welcome.

Top comments (0)