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.

Fade In on Enter
<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.

Hover to Scale Up
<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.

Hover to Rotate
<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.

Hover to Slide Right
<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.

Hover to Float 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.

Hover to Expand Width
<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.

Hover to Grow Taller
<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.

Hover to Morph Shape
<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:

ClassMotion 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(, or hsl(. Named colors like red or blue are 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.

Hover to Change Color
<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:

ClassMotion 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).

ClassMotion 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.

Combined Hover Effect
<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.