I kept rebuilding the same web effects for different projects. Eventually, I stopped rebuilding them and started building a library.
There is a folder on my machine where most of my motion experiments go to die.
Magnetic buttons.
Distorted images.
Liquid text.
Particle fields.
Scroll effects.
Shader experiments.
Some were useful. Some were terrible. Some looked impressive for about five minutes.
And some made me realize something:
Animations play. Interactions respond.
That distinction became the foundation for LIQUID REALITY.
Instead of building another collection of fade-ins, slide-ups and hover animations, I wanted to explore interactions that actually react to the person using the website.
Move the cursor and something changes.
Scroll faster and the interface responds differently.
Touch an image and it distorts.
Move toward a button and it pulls back.
Drag an object and it behaves like something with weight.
The interface isn't simply performing an animation.
It is reacting to you.
The problem with most "premium" animation
Modern websites have become very good at motion.
Almost too good.
You can add a scroll library, write a few GSAP timelines and suddenly everything moves.
Elements fade in.
Headlines slide upward.
Cards scale slightly.
Images reveal themselves.
The problem isn't that these techniques are bad.
They're useful.
They're just predictable.
After seeing hundreds of websites using the same patterns, users stop consciously noticing them.
I wanted to build interactions that were harder to ignore.
Not because they were louder.
Because they were responsive.
1. Input is easy. Making it perceptible is the hard part.
A pointer position is easy to capture.
const x = event.clientX;
const y = event.clientY;
That's not interesting.
What happens with that information is where the interaction begins.
For example, pointer velocity can control multiple properties simultaneously.
A fast movement can increase distortion while also increasing the intensity of a visual effect.
A slow movement can make the same interface settle back into a calmer state.
The code isn't necessarily complicated.
The important part is the relationship between the input and the visual response.
That relationship is what makes an interface feel intelligent.
2. Magnetic buttons need more than translate()
Magnetic buttons are everywhere.
Most implementations are essentially:
transform: translate(pointerX * 0.3, pointerY * 0.3);
It works.
But it doesn't necessarily feel good.
The difference comes from introducing different physical behaviours.
The button shell can respond quickly.
The label can follow more slowly.
The two can settle at different speeds.
Now the button doesn't just move.
It has weight.
const shell = new Spring2(210, 17);
const text = new Spring2(90, 12);
shell.to(x * strength, y * strength);
text.to(x * strength * 0.55, y * strength * 0.55);
Add a little skew based on movement and the interaction starts feeling less like CSS and more like a physical object.
That's the type of detail I wanted throughout the library.
3. The cursor should be an input system, not an animation trigger
Once you start building interactive effects, you quickly run into a problem.
Every component wants to listen to the cursor.
The hero wants it.
The button wants it.
The image wants it.
The particle field wants it.
The shader wants it.
You can easily end up with dozens of listeners and animation loops doing almost the same work.
So I started treating pointer data as a shared input system.
One pointer listener.
One animation loop.
Shared mutable values.
Effects consume the data they need.
That means the interaction architecture can stay simple even when the page becomes visually complex.
The same pointer can drive:
- Position
- Velocity
- Distance
- Direction
- Distortion
- Magnetic force
- Particle movement
- Shader uniforms
One input.
Multiple responses.
4. One shader can become many experiences
One of my favourite parts of building LIQUID REALITY was experimenting with shaders.
A basic image distortion effect doesn't need an enormous rendering system.
You can start with a texture, a plane and a fragment shader.
Then expose a few useful parameters:
uTexture
uPointer
uVelocity
uProgress
uIntensity
uRadius
uDetail
uChroma
From there, completely different experiences can emerge.
Liquid distortion.
Ripple.
Melt.
Chromatic displacement.
Refraction.
Fragmentation.
Glass-like distortion.
The interesting part isn't using GLSL because GLSL sounds impressive.
The interesting part is using the GPU to create behaviour that would be difficult or expensive to reproduce with ordinary DOM animation.
That's the rule I kept coming back to:
If the shader can only be described by the technique used to build it, it probably isn't interesting enough.
"Voronoi experiment" isn't a product feature.
"Image fragmentation" is.
The technology is underneath.
The interaction is what the user experiences.
5. Motion should never become a usability requirement
There is a trap with interactive websites.
You can become so focused on the visual experience that you forget the website still has to work.
That's why reduced motion became part of the design process rather than something added at the end.
If a user prefers reduced motion, the page should not simply stop halfway through an animation.
The interface should resolve into its usable state.
Motion can disappear.
Content shouldn't.
For example:
const intensity = reducedMotion ? 0 : config.intensity;
And instead of leaving an element hidden because its reveal animation never happened, its final state should be applied directly.
The principle is simple:
Motion enhances the interface. Motion should never be the interface.
6. Mobile isn't desktop with less space
Interactive effects become particularly interesting on mobile.
A cursor doesn't exist.
Hover doesn't work in the same way.
Performance constraints are different.
So instead of treating mobile as a smaller desktop, I started thinking about different inputs.
Touch can replace pointer interaction.
Device orientation can become an input.
An effect can automatically drift when the user isn't interacting.
For example, a background can react to device movement instead of cursor movement.
The goal isn't to perfectly reproduce desktop.
The goal is to preserve the feeling of interaction.
7. Performance is part of the interaction
A beautiful effect that destroys the user's laptop isn't a premium interaction.
It's a benchmark.
That meant being deliberate about how the effects run.
Avoid unnecessary layout reads inside animation loops.
Measure elements when their dimensions change rather than repeatedly calling:
getBoundingClientRect();
during every frame.
Cache what can be cached.
Use transforms where possible.
Pause expensive work when the effect isn't visible.
Use IntersectionObserver.
Limit pixel density when necessary.
Clean up animation loops, listeners, textures and WebGL resources.
And most importantly:
Don't animate something just because you can.
Performance is part of the design.
What I actually wanted to build
After enough experiments, I realized I didn't want to make a giant animation framework.
I wanted something closer to a box of interaction ideas.
Something a frontend developer could open when a normal implementation felt too ordinary.
Need an image that reacts to the cursor?
There's an interaction for that.
Need a magnetic CTA?
There's an interaction for that.
Want a liquid visual?
There's an interaction for that.
Want a shader-based distortion?
There's an interaction for that.
Want to experiment with particles, scroll velocity, typography or WebGL?
Same idea.
Pick the interaction.
Open the source.
Understand it.
Change it.
Use it.
Why I called it LIQUID REALITY
The name came from the feeling I was trying to create.
Interfaces are normally rigid.
Boxes.
Cards.
Buttons.
Images.
Text.
Grids.
LIQUID REALITY asks:
What if these things behaved less like pixels on a screen and more like physical materials?
What if an image could ripple?
What if typography could bend?
What if a button could feel magnetic?
What if a cursor could affect an entire visual field?
What if scrolling changed the physical behaviour of the page?
The goal isn't to make websites complicated.
It's to make them responsive in unexpected ways.
The result
I packaged the experiments into a downloadable source product for developers.
The focus is not on giving you another dependency-heavy animation package.
It's on giving you reusable interaction implementations that you can inspect, modify and integrate into real projects.
React. TypeScript. GSAP. WebGL. GLSL. Canvas.
Use one effect.
Combine several.
Change the parameters.
Replace the assets.
Rewrite the shader.
Take the idea somewhere completely different.
That's the whole point.
If I were building a website today
I wouldn't start by asking:
"What animation should this section have?"
I'd ask:
"What should this section respond to?"
Cursor?
Scroll?
Velocity?
Touch?
Proximity?
Drag?
Time?
Once you define the input, the animation becomes much more interesting.
That's the shift I'm interested in.
From:
Animation → Interaction
From:
Timeline → Response
From:
Element moves → Element reacts
And ultimately:
A website shouldn't just show motion. It should feel like it is listening.
LIQUID REALITY
I built LIQUID REALITY as a collection of these experiments — interactive effects designed for developers who want their websites to feel less static and more alive.
You can explore the live demo here:
https://liquid-reality.vercel.app/
And if you want the source and want to experiment with the interactions yourself:
LIQUID REALITY is available on Gumroad.
https://boukataya.gumroad.com/l/ygshkz
Build something interesting with it.
Then break it and make it better.




Top comments (0)