"You are not a drop in the ocean; you are the entire ocean in a drop."
— Rumi, 13th Century Persian Poet
An exercise in recreating this Drip Drop Animation.
Here's how some of the CSS animation techniques used to recreate the original function:
Keyframes define the stages of an animation sequence. Think of them as snapshots of what your element should look like at different points in time.
@keyframes drip {
to {
top: 190px;
}
}How it works:
@keyframes dripcreates an animation named "drip"to(or100%) defines the end state- The browser automatically interpolates between the starting position and
top: 190px - Apply it with
animation-name: drip
Key Takeways:
- Use
fromandtofor simple animations - Use percentages (
0%,50%,100%) for complex multi-stage animations - The browser calculates all the in-between frames automatically
Radial gradient creates circular or elliptical color transitions, perfect for realistic lighting effects on 3D-looking objects.
background: radial-gradient(
circle at 30% 30%,
#ffffff 20%,
#87cefa 70%,
#4fc3f7 100%
);Breaking it down:
circle at 30% 30%- Creates a circular gradient with its center at 30% from left, 30% from top#ffffff 20%- White color starts at the center and goes to 20% of the radius#87cefa 70%- Light blue from 20% to 70% of the radius#4fc3f7 100%- Darker blue from 70% to the edge (100%)
Visual Effect: This creates a highlight effect that makes flat elements appear three-dimensional, like light hitting a water droplet.
Cubic Bezier has a lot of math behind the scenes, but the basic idea is that it controls the acceleration and deceleration of animations, making them feel more natural and physics-based.
animation-timing-function: cubic-bezier(1, 0, 0.91, 0.19);Understand the parameters:
- Four numbers represent two control points:
(x1, y1, x2, y2) (1, 0)- First control point: starts fast(0.91, 0.19)- Second control point: slows down gradually- This creates a "gravity-like" effect where the drop accelerates as it falls
Common patterns to follow:
ease-in: slow start, fast endease-out: fast start, slow endease-in-out: slow start and end, fast middle- Custom curves let you simulate real physics
Cuts shapes out of elements by defining a polygon with coordinate points.
clip-path: polygon(50% 0%, 0% 90%, 100% 80%);How coordinates work:
50% 0%- Point at horizontal center, top edge (tip of teardrop)0% 90%- Point at left edge, 90% down from top100% 80%- Point at right edge, 80% down from top- Browser connects these points to create the shape
Coordinate system:
0% 0%= top-left corner100% 0%= top-right corner0% 100%= bottom-left corner100% 100%= bottom-right corner
Pro tip: Use online polygon generators to visualize your shapes before coding!
The water droplet effect combines all these techniques:
- Keyframes animate the falling motion
- Cubic bezier makes the fall feel natural with gravity
- Clip path shapes the teardrop tail
Each technique serves a specific purpose in creating the illusion and creating the ripple effect of water.
This project uses LiquidJS to render templates locally into a static dist/index.html and a lightweight dev toolchain for local iteration.
CSS is processed via PostCSS with autoprefixer and postcss-preset-env and output to dist/style.css.
- Main page template:
templates/page.drip.liquidwraps a complete HTML document and includes the section. - Section:
sections/drip.liquidrenders the droplet/ripple and defines CSS variables in a:rootblock from section settings.- In the local build,
asset_urlandstylesheet_tagare emulated by the build script.
- In the local build,
- Section settings are loaded at build time from
scripts/data/sections/drip.json. - Shopify-only
{% schema %}...{% endschema %}blocks in the section are ignored during local rendering.
bg_color— Background colordroplet_light— Droplet highlight (light)droplet_mid— Droplet mid tonedroplet_dark— Droplet shadow (dark)ocean_color— Ripple (ocean) coloranim_duration— Animation duration in secondsshow_droplet— Toggle droplet visibilityshow_ripple— Toggle ripple visibility
-
Build once:
npm run build(outputsdist/index.htmlanddist/style.css) -
Dev server with auto-rebuild and live reload:
npm run devthen open http://localhost:3000
Build and serve the Liquid templates locally using the provided Node pipeline (BrowserSync + nodemon + concurrently + PostCSS):
- Install dependencies:
npm install
- Build once:
npm run build(outputsdist/index.htmlanddist/style.css)
- Dev server (auto rebuild + live reload + serve):
npm run devand open http://localhost:3000- The dev setup runs two watchers in parallel:
nodemonwatchestemplates/,sections/, andscripts/build.jsand runsnpm run build:htmlon changes (rendersdist/index.html).postcss-cliwatchesstyle.cssand writesdist/style.csson changes.
browser-syncservesdist/with live reload.
npm run build— Builds HTML (Liquid) and CSS (PostCSS) intodist/npm run build:html— Builds only HTML intodist/index.htmlnpm run css— Processes CSS once via PostCSS intodist/style.cssnpm run watch— Watches templates/sections/build.js and rebuilds HTML onlynpm run watch:css— Watchesstyle.cssand rebuilds CSS onlynpm run dev— Runs an initial build, thenwatch,watch:css, andservein parallel
- Config:
postcss.config.cjswithpostcss-preset-env(stage 1, includes nesting) andautoprefixer - CLI:
postcss style.css -o dist/style.css(run vianpm run css, invoked bynpm run build) - Targets: controlled by
browserslistinpackage.json
Edit the local section settings file at scripts/data/sections/drip.json:
{
"bg_color": "#ffffff",
"droplet_light": "#ffffff",
"droplet_mid": "#6b6b6b",
"droplet_dark": "#2c2c2c",
"ocean_color": "#2c2c2c",
"anim_duration": 2,
"show_droplet": true,
"show_ripple": true
}These map to CSS variables in the rendered HTML and are consumed by style.css.