Subchapter 1.13
references/features-micro-interactions.mdMarkdown5 KBView on GitHub
Great interfaces are a stack of small details. These are framework-agnostic; the class names use UnoCSS, but the principles apply to any stack.
Add these when a project needs the polish layer. They are additive; do not force them onto dense devtools surfaces that intentionally stay flat.
export default defineConfig({
theme: {
boxShadow: {
// Layered, background-tinted elevation for floating or marketing surfaces.
card: '0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px rgb(0 0 0 / 0.08)',
},
},
shortcuts: [
{
// Subtle image edge. Pure black in light, pure white in dark, never a tinted neutral.
'img-outline': 'outline outline-1 outline-black/10 dark:outline-white/10 outline-offset-[-1px]',
// Tactile press feedback.
'tap-scale': 'transition-transform active:scale-[0.96]',
},
],
})antfu tooling UIs are deliberately flat and border-driven. Marketing and floating surfaces read better with layered shadows.
border-base hairlines. Flat is correct here.shadow-card (layered, transparent, background-tinted), not a hard 1px border. Shadows adapt to any background; solid borders do not.box-shadow for hover depth on large lists; swap opacity or use a pseudo-element.Outer radius = inner radius + padding. Mismatched nested radii is the most common reason a card feels off. A rounded-2xl card with p-2 should hold a rounded-lg child, not another rounded-2xl.
When geometric centering looks off, align optically. Play triangles, single icons in round buttons, and asymmetric glyphs usually need a 1px nudge (pl-px) or a fix to the SVG viewBox.
transition: all: specify exact properties (transition-property: opacity, transform). UnoCSS transition-transform already covers transform, translate, scale, and rotate.animation-delay: calc(var(--i) * 100ms) or a stagger in a motion library).translateY and a fade, softer than the enter.initial={false}).0.25 to 1, opacity 0 to 1, blur 4px to 0. With a motion library use a spring with bounce: 0; without one, keep both icons in the DOM (one absolutely positioned) and cross-fade with cubic-bezier(0.2, 0, 0, 1).tap-scale gives scale(0.96) on press. Never go below 0.95; it looks exaggerated. Offer a way to disable it where motion would distract.prefers-reduced-motion.tabular-nums to prevent layout shift. antfu already pairs this with font-mono for technical values.text-balance on headings. Body wrap: text-pretty to avoid orphans. These map to text-wrap: balance and text-wrap: pretty.antialiased to the root on macOS for crisper text.img-outline. The outline color must be pure black in light mode and pure white in dark mode at low opacity, never a tinted neutral, which reads as dirt on the edge.will-change sparingly: only on elements that actually animate, and only for transform, opacity, filter. Never will-change: all. Add it only when you see first-frame stutter.transform and opacity for movement. Never animate top, left, width, or height.