Documentation
Basic Property Animations
Animate opacity, scale, rotation, translation, dimensions, border radius, colors, shadows, blur, clip path, position, spacing, typography, and more with simple Tailwind-like classes.
Motionwind lets you animate any CSS-compatible property using the familiar animate-{gesture}:{property}-{value} syntax. Each class is transformed at build time into the corresponding Motion prop -- zero runtime parsing, full type safety.
This page covers the foundational animatable properties you will use most often.
Opacity
Fade elements in and out by animating their opacity. Values are specified on a 0-100 scale where 0 is fully transparent and 100 is fully opaque.
The parser divides the number by 100, so opacity-0 becomes 0 and opacity-100 becomes 1.
<div className="animate-initial:opacity-0 animate-enter:opacity-100 animate-duration-1000">
I faded in
</div>Compiles to:
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1 }}
>
I faded in
</motion.div>Scale
Scale elements up or down. Values are specified as percentages where 100 equals the original size, 110 is 10% larger, and 50 is half the size.
The parser divides by 100, so scale-110 becomes 1.1.
<button className="animate-hover:scale-110 animate-spring">
Hover me
</button>Compiles to:
<motion.button
whileHover={{ scale: 1.1 }}
transition={{ type: "spring" }}
>
Hover me
</motion.button>Rotate
Rotate elements by a given number of degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
<div className="animate-hover:rotate-45 animate-spring">R</div>Compiles to:
<motion.div
whileHover={{ rotate: 45 }}
transition={{ type: "spring" }}
>
R
</motion.div>You can also use negative rotation with a - prefix:
<div className="animate-hover:-rotate-90">Spin back</div>This compiles to whileHover={{ rotate: -90 }}.
Translate X
Slide elements horizontally. The value is in pixels. Positive moves right, negative moves left.
<div className="animate-hover:x-20 animate-spring">Slide right</div>Compiles to:
<motion.div
whileHover={{ x: 20 }}
transition={{ type: "spring" }}
>
Slide right
</motion.div>For sliding left, use a negative value:
<div className="animate-hover:-x-40">Slide left</div>Translate Y
Slide elements vertically. Positive values move down, negative values move up.
<div className="animate-hover:-y-20 animate-spring">UP</div>Compiles to:
<motion.div
whileHover={{ y: -20 }}
transition={{ type: "spring" }}
>
UP
</motion.div>A common pattern is using y with initial and inview for scroll-reveal effects:
<div className="animate-initial:y-40 animate-inview:y-0 animate-once">
Slides up into view
</div>Width
Animate the width of an element. The value is in pixels by default.
<div className="w-[100px] animate-hover:w-200 animate-spring">Expand</div>Compiles to:
<motion.div
whileHover={{ width: 200 }}
transition={{ type: "spring" }}
>
Expand
</motion.div>Unit Values for Width
Width also supports unit suffixes: pct, px, vh, vw, rem, em, and the keyword auto.
<!-- Percentage -->
<div className="animate-hover:w-100pct">Full width</div>
<!-- Viewport width -->
<div className="animate-hover:w-50vw">Half viewport</div>
<!-- Auto -->
<div className="animate-hover:w-auto">Auto width</div>Compiles to:
// w-100pct
whileHover={{ width: "100%" }}
// w-50vw
whileHover={{ width: "50vw" }}
// w-auto
whileHover={{ width: "auto" }}Height
Animate the height of an element. The value is in pixels by default.
<div className="h-[48px] animate-hover:h-100 animate-spring">Grow</div>Compiles to:
<motion.div
whileHover={{ height: 100 }}
transition={{ type: "spring" }}
>
Grow
</motion.div>Unit Values for Height
Like width, height supports unit suffixes: pct, px, vh, vw, rem, em, and the keyword auto.
<!-- Percentage -->
<div className="animate-hover:h-100pct">Full height</div>
<!-- Viewport height -->
<div className="animate-enter:h-100vh">Full viewport height</div>
<!-- Auto -->
<div className="animate-hover:h-auto">Auto height</div>Compiles to:
// h-100pct
whileHover={{ height: "100%" }}
// h-100vh
animate={{ height: "100vh" }}
// h-auto
whileHover={{ height: "auto" }}Border Radius
Animate the border radius to morph between shapes. The value is in pixels.
<div className="rounded-lg animate-hover:rounded-40 animate-spring">Hi</div>Compiles to:
<motion.div
whileHover={{ borderRadius: 40 }}
transition={{ type: "spring" }}
>
Hi
</motion.div>This is a great way to smoothly transition a square into a circle (or vice versa) on interaction.
Colors
Motionwind provides shorthand classes for the most common color properties, as well as the general-purpose arbitrary value syntax for any CSS property.
Color Shorthand Classes
Use the bg-, text-, and border- prefixes followed by a literal color value to animate backgroundColor, color, and borderColor respectively.
<button className="animate-hover:bg-#c8ff2e animate-hover:text-#000000 animate-duration-300">
Hover for color
</button>Compiles to:
<motion.button
whileHover={{ backgroundColor: "#c8ff2e", color: "#000000" }}
transition={{ duration: 0.3 }}
>
Hover for color
</motion.button>The supported shorthand mappings are:
| Class | Motion Property |
|---|---|
bg-{color} | backgroundColor: color |
text-{color} | color: color |
border-{color} | borderColor: color |
<!-- Background color -->
<div className="animate-hover:bg-#c8ff2e">...</div>
<!-- Text color -->
<div className="animate-hover:text-#000000">...</div>
<!-- Border color -->
<div className="animate-hover:border-#ff6347">...</div>Note: Color shorthands only work with literal color values starting with
#,rgb(, orhsl(. Named colors likeredorblueare not supported -- use the hex or function form instead.
Arbitrary Value Syntax
For properties that don't have a dedicated shorthand -- like backgroundColor -- you can also use the arbitrary value syntax: [key=value].
The value inside the brackets is passed through directly. If it parses as a number, it becomes a number; otherwise it stays a string.
<button className="animate-hover:[backgroundColor=#c8ff2e] animate-hover:[color=#000000] animate-duration-300">
Hover for color
</button>Compiles to:
<motion.button
whileHover={{ backgroundColor: "#c8ff2e", color: "#000000" }}
transition={{ duration: 0.3 }}
>
Hover for color
</motion.button>You can use any valid CSS property name and value with the arbitrary syntax:
<!-- Animate padding -->
<div className="animate-hover:[padding=32]">...</div>
<!-- Animate letter spacing -->
<div className="animate-hover:[letterSpacing=4]">...</div>Box Shadow
Animate box shadows using the bracket syntax shadow-[value]. Since shadow values contain spaces, use underscores (_) in place of spaces within the bracket value.
<div className="animate-hover:shadow-[0_20px_60px_rgba(200,255,46,0.3)] animate-duration-300">
Glowing card
</div>Compiles to:
<motion.div
whileHover={{ boxShadow: "0 20px 60px rgba(200,255,46,0.3)" }}
transition={{ duration: 0.3 }}
>
Glowing card
</motion.div>Note: Spaces in shadow values need underscores. For more complex values, you can also use the arbitrary syntax
[boxShadow=0_20px_60px_rgba(200,255,46,0.3)].
You can also remove a shadow on hover by setting it to none:
<div className="animate-hover:shadow-[none]">
Remove shadow on hover
</div>Backdrop Blur
Animate the backdrop blur filter on an element. The value is in pixels and maps to backdropFilter: "blur(Npx)".
<div className="animate-hover:backdrop-blur-10 animate-duration-300">
Blur the background
</div>Compiles to:
<motion.div
whileHover={{ backdropFilter: "blur(10px)" }}
transition={{ duration: 0.3 }}
>
Blur the background
</motion.div>A common use is combining backdrop blur with a semi-transparent background for frosted-glass effects:
<div className="bg-[var(--color-surface-elevated)] animate-hover:backdrop-blur-20 animate-duration-500">
Frosted glass on hover
</div>Clip Path
Animate the clipPath property using the bracket syntax clip-[value]. This is useful for reveal effects and creative shape transitions.
<div className="animate-initial:clip-[circle(0%)] animate-enter:clip-[circle(50%)] animate-duration-800">
Reveal with clip path
</div>Compiles to:
<motion.div
initial={{ clipPath: "circle(0%)" }}
animate={{ clipPath: "circle(50%)" }}
transition={{ duration: 0.8 }}
>
Reveal with clip path
</motion.div>You can use any valid clip-path value inside the brackets:
<!-- Polygon -->
<div className="animate-hover:clip-[polygon(50%_0%,100%_100%,0%_100%)]">...</div>
<!-- Inset -->
<div className="animate-hover:clip-[inset(10%)]">...</div>Position Properties
Animate the CSS position offsets top, left, right, and bottom. Values are in pixels by default, and support unit suffixes (pct, px, vh, vw, rem, em) as well as the keyword auto.
<div className="relative animate-initial:top-100 animate-enter:top-0 animate-duration-500">
Slides down from 100px to 0
</div>Compiles to:
<motion.div
initial={{ top: 100 }}
animate={{ top: 0 }}
transition={{ duration: 0.5 }}
>
Slides down from 100px to 0
</motion.div>All four directions are supported:
<!-- Left with percentage -->
<div className="animate-enter:left-50pct">...</div>
<!-- Right -->
<div className="animate-hover:right-20">...</div>
<!-- Bottom with viewport units -->
<div className="animate-hover:bottom-10vh">...</div>Compiles to:
// left-50pct
animate={{ left: "50%" }}
// right-20
whileHover={{ right: 20 }}
// bottom-10vh
whileHover={{ bottom: "10vh" }}Spacing
Animate padding, margin, and gap. Values are numeric by default, and support unit suffixes (pct, px, rem, em).
<div className="animate-hover:p-32 animate-spring">
Expand padding on hover
</div>Compiles to:
<motion.div
whileHover={{ padding: 32 }}
transition={{ type: "spring" }}
>
Expand padding on hover
</motion.div>The supported shorthand mappings are:
| Class | Motion Property |
|---|---|
p-{n} | padding: n |
m-{n} | margin: n |
gap-{n} | gap: n |
<!-- Margin -->
<div className="animate-hover:m-16">...</div>
<!-- Gap -->
<div className="animate-hover:gap-24">...</div>
<!-- Padding with rem units -->
<div className="animate-hover:p-2rem">...</div>Compiles to:
// m-16
whileHover={{ margin: 16 }}
// gap-24
whileHover={{ gap: 24 }}
// p-2rem
whileHover={{ padding: "2rem" }}Typography
Animate font size, letter spacing, and line height. Values are numeric by default, and support unit suffixes (pct, px, rem, em).
| Class | Motion Property |
|---|---|
text-size-{n} | fontSize: n |
tracking-{n} | letterSpacing: n |
leading-{n} | lineHeight: n |
<div className="animate-hover:text-size-24 animate-hover:tracking-2 animate-duration-300">
Larger text on hover
</div>Compiles to:
<motion.div
whileHover={{ fontSize: 24, letterSpacing: 2 }}
transition={{ duration: 0.3 }}
>
Larger text on hover
</motion.div>Line height works the same way:
<div className="animate-hover:leading-32">...</div>Compiles to:
<motion.div whileHover={{ lineHeight: 32 }}>...</motion.div>Border Width
Animate the border width of an element. The value is in pixels.
<div className="animate-hover:border-w-2 animate-duration-300">
Border appears on hover
</div>Compiles to:
<motion.div
whileHover={{ borderWidth: 2 }}
transition={{ duration: 0.3 }}
>
Border appears on hover
</motion.div>This pairs well with the border-{color} shorthand:
<div className="animate-hover:border-w-2 animate-hover:border-#c8ff2e animate-duration-300">
Colored border on hover
</div>Compiles to:
<motion.div
whileHover={{ borderWidth: 2, borderColor: "#c8ff2e" }}
transition={{ duration: 0.3 }}
>
Colored border on hover
</motion.div>Combining Multiple Properties
You can animate multiple properties on the same gesture by stacking classes. Each gesture collects all its property-value pairs into a single object.
<div className="animate-hover:scale-105 animate-hover:-y-4 animate-hover:rounded-20 animate-hover:[backgroundColor=#c8ff2e] animate-hover:[color=#000000] animate-spring">
Everything at once
</div>Compiles to:
<motion.div
whileHover={{
scale: 1.05,
y: -4,
borderRadius: 20,
backgroundColor: "#c8ff2e",
color: "#000000",
}}
transition={{ type: "spring" }}
>
Everything at once
</motion.div>All property classes sharing the same gesture prefix are merged into a single Motion prop object at build time.