A CPU in 10,000 Lines of CSS
Someone wrote an x86 CPU emulator in CSS. Not as a joke, not as a proof-of-concept buried in a GitHub gist, but as a fully functional, Turing-complete system that interprets machine code using nothing but cascading style rules. The project, dubbed x86CSS, leverages CSS’s selector logic and property inheritance to simulate registers, memory addressing, and instruction execution. It doesn’t run fast—rendering a single instruction can take seconds—but it runs. And that’s the point. This isn’t about performance. It’s a radical reimagining of what a computing substrate can be, pushing the boundaries of browser-based computation into surreal territory.
How It Works (And Why It Shouldn’t)
CSS wasn’t designed for computation. It’s a declarative language meant to describe visual presentation. Yet x86CSS treats the browser’s rendering engine like a bizarrely constrained virtual machine. The emulator encodes CPU state—registers, flags, memory—as CSS class names applied to HTML elements. Each instruction is represented by a combination of selectors that trigger style changes, which in turn modify the DOM structure. These changes cascade through nested elements, mimicking data flow in a real processor. A MOV instruction, for example, becomes a chain of :hover and :checked pseudo-classes that propagate values across sibling and child nodes. The browser’s repaint cycle acts as the clock pulse. It’s computationally grotesque, but technically coherent.
The implementation relies heavily on CSS custom properties (variables) and the cascade’s ability to propagate values downward. Memory is modeled as a grid of divs, each holding a byte via a data attribute. Arithmetic operations are reduced to conditional styling—adding two numbers means applying classes that increment a counter variable through layered selectors. Branching uses :target or :focus states to redirect execution flow. Even interrupts are simulated through timed animations that trigger state resets. Every layer of abstraction is a hack, but together, they form a fragile, functioning emulator.
The Browser as an Accidental Computer
x86CSS exposes a deeper truth: modern browsers are overpowered sandboxes capable of hosting entire operating systems, game engines, and now, CPU architectures—all through unintended use of their rendering pipelines. The web platform was never meant to be a general-purpose computing environment, yet it has evolved into one through sheer developer ingenuity. JavaScript gets the credit, but CSS and HTML have quietly become Turing-complete in their own right. Projects like this aren’t just curiosities; they’re symptoms of a platform stretched far beyond its original design.
Consider the implications. If you can emulate an x86 CPU in CSS, you can theoretically run legacy software, boot an OS, or even simulate another emulator—all without a single line of JavaScript. That’s not practical, but it’s possible. It speaks to the latent computational power buried in everyday web technologies. The browser’s rendering engine, optimized for speed and compatibility, becomes an unwitting co-processor for absurd computational tasks. x86CSS doesn’t just push CSS to its limits—it reveals how much latent functionality exists in systems never designed for such use.
Why This Matters Beyond the Meme
At first glance, x86CSS is a stunt. A clever hack meant to impress at conference talks or win internet points. But beneath the absurdity lies a serious commentary on software abstraction and the elasticity of programming paradigms. When a style sheet can emulate a microprocessor, the line between presentation and computation blurs. It challenges the assumption that certain tasks require specific tools. Why write a CPU emulator in C or Rust when you can do it in a language meant for fonts and colors?
More importantly, x86CSS highlights the unintended consequences of platform evolution. The web was built for documents, not applications. Yet decades of feature additions—CSS variables, flexbox, grid, animations—have turned it into a full-stack runtime. Each new capability expands the attack surface for creative misuse. x86CSS isn’t malware, but it demonstrates how easily browser features can be repurposed for tasks far removed from their intent. This has security and performance implications. If CSS can simulate a CPU, could it also be used for covert computation, data exfiltration, or denial-of-service attacks through infinite style loops?
There’s also a philosophical angle. x86CSS treats computation as a form of styling—transforming state through rules and conditions. It reframes the CPU not as a physical chip, but as a pattern of behavior emerging from declarative instructions. In that sense, it aligns with functional programming ideals: computation as transformation, not mutation. The emulator doesn’t “execute” code so much as it “renders” it into existence through cascading effects. It’s a poetic, if inefficient, vision of how machines might think.
And yet, for all its brilliance, x86CSS is a dead end. No one will build production systems on CSS emulation. The performance is abysmal, the debugging nearly impossible, and the maintenance a nightmare. But that’s not the point. Like the first computer made from relays or the first game rendered in Minecraft redstone, x86CSS is a boundary-pushing artifact. It reminds us that computation isn’t bound by hardware or syntax—it’s a mindset. The tools we use shape how we think, but they don’t limit what we can imagine.
In an era obsessed with efficiency and optimization, x86CSS is a deliberate act of inefficiency. It’s a reminder that sometimes, the most important innovations come not from doing things better, but from doing them differently—even if that means running machine code through a style sheet.