Ebbinghaus Illusion
See the Pen Ebbinghaus Illusion.
Tech & Dependencies
Features
- ✓ Optical Illusion
- ✓ Hover Reveal
- ✓ Single Div
- ✓ Responsive
Browser Support
Core
This is a Pure CSS Ebbinghaus Optical Illusion. It uses mathematically sized radial gradients on a single element to trick the brain into perceiving two identical circles as different sizes. Its function is to provide an interactive, visual “gotcha” moment, demonstrating how relative scale affects human perception, revealed instantly via a smooth hover transition.
Specs
- Weight: < 1 KB. Pure CSS without any HTML markup beyond the
bodytag. - Performance: High. It avoids rendering actual DOM nodes by drawing everything using
background-image: radial-gradient(). Movement is handled viatranslate, ensuring hardware acceleration. - Theming / Customization: Easily controlled via CSS custom properties (
--pfor the center circle,--sfor the surrounding circles). - Responsiveness: Fluid. Utilizes the modern CSS Media Query Range Syntax (
@media(aspect-ratio < 1)) to switch from a horizontal comparison to a vertical one on portrait screens. - Graceful Degradation: [!] Heavily reliant on native CSS nesting (
&) and Range Syntax. In browsers older than 2023, the styles will fail to parse, leaving a completely blank screen.
Anatomy
- HTML: Zero markup. The effect is painted directly onto the
<body>element. - CSS: The engine. The
body::beforeandbody::afterpseudo-elements each render one half of the illusion. They employ 9 layeredradial-gradientbackgrounds to draw the 8 surrounding circles and 1 central circle. Custom properties (--size2,--p1,--p2) dynamically calculate the exact placement of each gradient layer.
Logic
The standout feature is the procedural drawing mechanism inside the pseudo-elements, avoiding SVG or multiple HTML nodes.
background:
radial-gradient(farthest-side circle, var(--s) 99%, #0000 0) var(--p1) var(--p1) / var(--size2) var(--size2),
/* ... 7 more surrounding circles ... */
radial-gradient(farthest-side, var(--p) 99%, #0000 0) 50% 50% / var(--size) var(--size);
By defining the background size (var(--size2)) and position (var(--p1), --p2) dynamically based on CSS variables, the author creates a reusable drawing matrix. The ::before element sets --size2 to 1x, drawing tight, small surrounding circles. The ::after element scales --size2 to 2.5x and pushes the position values to the edges (0, 100%), drawing large, distant surrounding circles. The central orange circle remains exactly --size in both.
Feel
Intellectually satisfying. The initial state plays a perfect trick on the eye—the right circle looks undeniably larger. Hovering anywhere on the screen causes both clusters to translate and overlap directly in the center. The revelation is immediate and undeniable. The smooth 1-second transition makes the optical overlap feel like a deliberate, mechanical proof rather than a jarring glitch.


