Cards
LiquidFrame
A soft ring of colour wobbles and flows round the card like liquid. Leave some space round it for the spill.
Download
- React
- Tailwind CSS v4
- motion
components/ui/liquid-frame.tsx
"use client";
import type { ReactNode } from "react";
import { motion, useReducedMotion } from "motion/react";
type LiquidFrameProps = {
children: ReactNode;
className?: string;
/** Colours of the liquid, they flow round the frame. */
colors?: string[];
/** How far the liquid spills past the card, in pixels. */
thickness?: number;
/** Seconds for one full wobble. */
duration?: number;
};
const SHAPES = [
"42% 58% 63% 37% / 41% 44% 56% 59%",
"58% 42% 38% 62% / 55% 38% 62% 45%",
"38% 62% 55% 45% / 62% 58% 42% 38%",
"42% 58% 63% 37% / 41% 44% 56% 59%",
];
/* LiquidFrame: a ring of colour wobbles and flows round the card like liquid. */
export function LiquidFrame({
children,
className = "rounded-2xl bg-[#120f22] p-6 text-white",
colors = ["#a78bfa", "#5eead4", "#f0abfc"],
thickness = 10,
duration = 8,
}: LiquidFrameProps) {
const reduce = useReducedMotion();
const gradient = `conic-gradient(from 0deg, ${[...colors, colors[0]].join(", ")})`;
return (
<div className="relative isolate">
<motion.div
aria-hidden
className="absolute -z-10 blur-[6px]"
style={{ inset: -thickness, background: gradient, borderRadius: SHAPES[0] }}
animate={reduce ? undefined : { borderRadius: SHAPES, rotate: [0, 360] }}
transition={{
borderRadius: { duration, repeat: Infinity, ease: "easeInOut" },
rotate: { duration: duration * 2, repeat: Infinity, ease: "linear" },
}}
/>
<div className={`relative ${className}`}>{children}</div>
</div>
);
}
1. Install the dependency.
npm i motion2. Paste the Code tab into
components/ui/liquid-frame.tsx. The styles are Tailwind CSS v4 classes.3. Use it. This is the preview above:
app/liquid-frame-demo.tsx
import { LiquidFrame } from "@/components/ui/liquid-frame"; export default function LiquidFrameExample() { return ( <div className="grid h-full place-items-center bg-[#0b0a14] p-10"> <div className="w-full max-w-[280px]"> <LiquidFrame> <p className="font-mono text-[11px] uppercase tracking-[0.2em] text-[#a78bfa]">Live now</p> <p className="mt-3 text-2xl font-semibold">Design jam #12</p> <p className="mt-2 text-sm text-white/60">The frame never sits still.</p> </LiquidFrame> </div> </div> ); }
Props
| Name | Type | Default | What it does |
|---|---|---|---|
| children | ReactNode | — | Card content. |
| colors | string[] | violet, teal, pink | Colours that flow round the frame. |
| thickness | number | 10 | How far the liquid spills past the card, in pixels. |
| duration | number | 8 | Seconds for one full wobble. |
| className | string | dark card | Look of the card inside. |