Live lighting without JavaScript

The lamp in this room moves every frame and every surface answers it, yet the page runs no script. c3r writes the lighting as CSS, and the browser does the maths.

The light travels down the tree

Each group in the scene holds its transform in custom properties. The light's position starts at the root as a set of numbers, and every group passes it down after undoing its own transform in calc(). By the time it reaches a polygon, the light is in that polygon's own frame, where the maths is simple.

Keyframes move the lamp

The lamp's orbit is an ordinary CSS animation. The same keyframes move its sprite and animate the light's coordinates, which are registered with @property so the browser can interpolate them. Every frame, the new position flows down the tree and each polygon recomputes its brightness.

One shade per polygon

A flat polygon takes the light at its centre: the ambient level, plus the intensity times how squarely it faces the lamp, divided by the squared distance. It is a single calc(), painted as a grey layer that multiplies the content under it.

Exact falloff on a plane

A smooth polygon draws a radial-gradient centred where the lamp stands over its plane. Its size and colour stops follow the same falloff, so the pool of light is exact across the whole surface, and it slides as the lamp moves.

Shadows worked out in advance

CSS can't ask what stands between a surface and the light, so c3r works shadows out when it bakes the scene. Spheres, cylinders and boxes stand in for the casters, and each is projected through the light onto the surfaces that take shadows. When something moves, the shadow follows it: as a keyframed clip-path on the same timeline, or blended along a hover transition, so it pauses and plays with the motion.

The page stays a page

The lighting is a pseudo-element over the content and ignores the pointer. Underneath, this text is still text: you can select it, scroll it and find it with the browser's search, all while the light passes over.