# Hyprland Spring Animation Configuration: A Complete Guide to Physics-Based Motion

> Master Hyprland spring animation configuration. Learn to create physics-based motion with hl.curve mass, stiffness, and dampening for dynamic window effects. Get the complete guide now.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Configure physics-based spring animations in Hyprland using the `hl.curve()` API with `mass`, `stiffness`, and `dampening` parameters, then reference them via the `spring` field in any animation definition.**

Hyprland spring animation configuration allows you to replace traditional easing curves with physical simulations that follow Hooke's law. The compositor supports two curve types—classic **bezier** curves and **spring**-based curves—with the latter providing natural, inertia-based motion for windows, workspaces, and UI transitions by solving differential equations at runtime.

## How Spring Physics Work in Hyprland

Unlike static bezier curves, spring animations simulate a virtual mass attached to a spring. The animation manager calculates motion frame-by-frame using three tunable physical constants:

| Parameter | Description | Typical Range |
|-----------|-------------|---------------|
| **mass** | Inertia of the virtual mass; larger values delay acceleration | 0.1 – 5.0 |
| **stiffness** | Restoring force of the spring; higher values create snappier motion | 100 – 400 |
| **dampening** | Damping factor controlling oscillation; higher values reduce bounce | 10 – 30 |

When you reference a spring in an animation, Hyprland delegates timing calculations to the spring solver rather than a predefined curve lookup. This produces organic deceleration and optional overshoot based on the damping ratio derived from your parameters.

## Defining Spring Curves in Configuration

### The hl.curve() Syntax

Springs are declared globally using the `hl.curve()` function with `type = "spring"`. According to the source code in [`src/config/lua/bindings/LuaBindingsConfigRules.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/lua/bindings/LuaBindingsConfigRules.cpp) (lines 447-448), the engine validates that referenced spring names exist at configuration load time—missing definitions trigger immediate startup errors.

Define a custom spring in your [`hyprland.lua`](https://github.com/hyprwm/Hyprland/blob/main/hyprland.lua):

```lua
-- Define a spring named "soft" with gentle, bouncy motion
hl.curve("soft", { 
    type = "spring", 
    mass = 1.5, 
    stiffness = 180, 
    dampening = 20 
})

```

The `Config::animationTree()` stores these definitions, making them available to the animation factory at `Animation::mgr()->createAnimation`.

### Parameter Tuning Guidelines

Use **lower stiffness** (100-150) for relaxed, floating movements suitable for workspace transitions. Increase **mass** (2.0+) to create heavy, luxurious window movements, or decrease it below 1.0 for twitchy, responsive feedback. Adjust **dampening** above 25 to eliminate overshoot entirely, or keep it between 10-15 for iOS-style elastic snap-back effects.

## Applying Springs to Animations

Once defined, reference your spring in any animation block using the `spring` key. The `AnimationManager` (implemented in [`src/managers/AnimationManager.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/managers/AnimationManager.cpp)) automatically instantiates the physics solver when it detects a spring reference instead of a bezier curve.

### Window Open and Close Animations

Target window lifecycle events via entries processed by [`src/desktop/view/animationControllers/WindowAnimationController.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/view/animationControllers/WindowAnimationController.cpp):

```lua
hl.animation({
    leaf    = "windowsIn",
    enabled = true,
    speed   = 4.2,
    spring  = "soft",
    style   = "popin 85%"
})

```

This configuration replaces the default easing with your physics-based curve when windows spawn.

### Workspace Transitions

Control workspace sliding and fading through [`src/state/WorkspacePlacementController.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/state/WorkspacePlacementController.cpp):

```lua
hl.animation({
    leaf    = "workspace",
    enabled = true,
    speed   = 5.0,
    spring  = "soft"
})

```

Workspace animations benefit from springs with **higher stiffness** (300+) to ensure the desktop feels anchored and responsive during rapid switching.

### Mixing Curve Types

Hyprland allows simultaneous use of bezier and spring curves. Maintain legacy easing for subtle fades while using springs for dramatic motion:

```lua
-- Retain bezier for opacity changes
hl.curve("default", { 
    type = "bezier", 
    points = {0.25, 0.1, 0.25, 1.0} 
})

-- Use spring for spatial movement
hl.curve("dynamic", { 
    type = "spring", 
    mass = 0.8, 
    stiffness = 250, 
    dampening = 22 
})

```

## Source Code Implementation Details

The spring system integrates at multiple layers of the Hyprland codebase:

- **Validation**: [`LuaBindingsConfigRules.cpp`](https://github.com/hyprwm/Hyprland/blob/main/LuaBindingsConfigRules.cpp) parses `hl.curve()` declarations and validates spring references in `hl.animation()` blocks, emitting configuration errors if names are undefined (lines 447-448).
- **Storage**: Curve definitions reside in the configuration tree accessed via `Config::animationTree()`.
- **Instantiation**: [`AnimationManager.cpp`](https://github.com/hyprwm/Hyprland/blob/main/AnimationManager.cpp) handles the creation of animation objects, selecting between bezier interpolation and spring physics based on the presence of the `spring` field.
- **Window Hooks**: [`WindowAnimationController.cpp`](https://github.com/hyprwm/Hyprland/blob/main/WindowAnimationController.cpp) and [`WorkspacePlacementController.cpp`](https://github.com/hyprwm/Hyprland/blob/main/WorkspacePlacementController.cpp) consume these animations to drive visual updates during state changes.

The physics solver implements the classic Hooke's law differential equation, guaranteeing deterministic, frame-rate-independent motion across all monitor refresh rates.

## Summary

- **Declare springs** with `hl.curve("<name>", { type = "spring", mass = ..., stiffness = ..., dampening = ... })` before referencing them.
- **Reference springs** in animation blocks via the `spring` key to activate physics-based motion instead of bezier curves.
- **Validate configuration**: Undefined spring names cause startup errors in [`LuaBindingsConfigRules.cpp`](https://github.com/hyprwm/Hyprland/blob/main/LuaBindingsConfigRules.cpp).
- **Tune physics**: Adjust `mass` for inertia, `stiffness` for speed, and `dampening` for overshoot control to match your ergonomic preferences.
- **Scope freely**: Use different springs for windows, workspaces, and UI elements by targeting specific animation leaves.

## Frequently Asked Questions

### What is the difference between bezier and spring curves in Hyprland?

**Bezier curves** are predefined mathematical functions that interpolate between start and end values using control points, producing consistent timing regardless of distance. **Spring curves** simulate physical mass-spring systems, where animation duration varies based on the "distance" to travel and the physics constants, creating natural acceleration and deceleration that responds dynamically to the amount of change.

### How do I fix "spring not found" configuration errors?

This error originates from [`src/config/lua/bindings/LuaBindingsConfigRules.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/lua/bindings/LuaBindingsConfigRules.cpp) when an animation references a spring name not defined in your configuration. Ensure you declare the spring with `hl.curve("yourName", { type = "spring", ... })` **before** the `hl.animation()` block that references it via `spring = "yourName"`. Check for typos in the name string, as the validator performs exact string matching at startup.

### What are the optimal mass, stiffness, and dampening values for smooth animations?

For **general desktop use**, start with `mass = 1.0`, `stiffness = 200`, and `dampening = 20`. For **snappy window management**, use `mass = 0.6`, `stiffness = 300`, `dampening = 25`. For **relaxed, cinematic motion**, try `mass = 2.5`, `stiffness = 120`, `dampening = 15`. Values outside the documented ranges (mass > 5.0 or stiffness > 500) may cause instability or excessive duration according to the animation manager's solver implementation.

### Can I use different springs for windows and workspaces?

Yes. Hyprland's animation tree supports distinct configurations per animation leaf. Define multiple springs—such as `hl.curve("windowSpring", ...)` and `hl.curve("workspaceSpring", ...)`—then reference the appropriate name in each `hl.animation()` block by setting its `leaf` parameter to `"windowsIn"` or `"workspace"` respectively. Each animation type maintains independent curve references in `Config::animationTree()`.