How to Use Hyprland Animation Features: A Complete Guide to Workspace and Window Effects

Hyprland animation features are controlled through the animations: configuration section and rule-based overrides, allowing you to enable workspace transitions, window fades, and layer effects using styles like slide, fade, and popin with customizable speeds and bezier curves.

Hyprland provides a flexible, data-driven animation system that drives workspace transitions, window fades, and layer-shell effects. Built on Hyprutils' animation utilities and defined in the hyprwm/Hyprland repository, these features are fully configurable at runtime without recompiling the compositor. This guide covers the architecture behind Hyprland animation features and provides practical configuration examples for customizing motion throughout your desktop environment.

Architecture of the Animation System

The Animation Manager

The core engine lives in src/animation/AnimationManager.cpp, which owns a global singleton CHyprAnimationManager accessed via Animation::mgr(). A high-resolution timer (m_animationTimer) ticks roughly every millisecond, invoking frameTick() → tick() to advance all active animations.

During each tick, the manager iterates over CAnimatedVariable instances (representing floats, vectors, or colors) and updates their values according to their configured curves. The implementation batches damage requests to minimize redraws:

// From AnimationManager.cpp
CHyprAnimationManager::frameTick() {
    onTicked();                     // reset tick-state
    if (!shouldTickForNext()) return;
    tick();                         // advance animated variables
    Event::bus()->m_events.tick.emit(); // inform other subsystems
}

Damage handling occurs through policies like AVARDAMAGE_*, where the manager groups owners (windows, workspaces, layers) and issues minimal damage via damageWindowForPolicies and preDamageWorkspace before and after updates.

The Configuration Tree

Animation styles and properties are stored in a hierarchical tree managed by CAnimationTreeController, defined in src/config/shared/animation/AnimationTree.hpp. Each node contains enabled, speed, bezier, and an optional style string, populated from your animations: section through Config::animationTree()->setConfigForNode(...).

Configuring Workspace Animations

Workspace transitions are implemented in src/animation/WorkspaceAnimationController.cpp. When switching workspaces, the compositor calls Animation::Workspace::startAnimation(PHLWORKSPACE ws, eAnimationType type, bool left, bool instant, std::optional<std::string> style), which looks up animation configurations via Config::animationTree()->getAnimationPropertyConfig(name).

Built-in Animation Styles

The style syntax follows the pattern <base>[<direction>][<percentage>%]:

  • slide – Horizontal movement (left/right)
  • slidevert – Vertical movement (up/down)
  • fade – Opacity transition only
  • slidefade – Simultaneous slide and fade
  • popin – Scale-based pop-in (commonly used for layers)

Example configurations in ~/.config/hypr/hyprland.conf:


# Workspace animation style - slides left covering 75% of monitor width

animations:workspace = slide left 75%

# Special workspace (scratchpad) uses simple fade

animations:specialWorkspace = fade

Global Animation Settings

Master toggles are defined as CConfigValues in src/config/values/ConfigValues.cpp:

MS<Bool>("animations:enabled", "enable animations", true),
MS<Bool>("animations:workspace_wraparound",
         "changes the direction of slide animations between the first and last workspaces", false),

To enable the system globally:

animations:enabled = true
animations:workspace_wraparound = false  # Optional wrap-around behavior

Per-Window and Layer Animation Rules

You can override animations for specific windows or layers using Hyprland's rule system. The parser eventually calls CAnimatedVariable::setConfig() with your custom style string.


# Terminal windows slide in from right, covering 90% of screen

windowrule = animation:slide right 90% , class:^(Alacritty)$

# Notification overlays fade in/out

layerrule = animation:fade , layer:overlay

Customizing Speed and Bezier Curves

Each animation node supports speed multipliers and bezier curve names stored in CAnimationPropertyConfig and applied when CAnimatedVariable creates its internal animation object.

Available built-in curves include linear, with custom curves defined via the bezier config option (initialized in AnimationManager::CHyprAnimationManager).


# Increase workspace animation speed to 1.5x

animations:workspace_speed = 1.5

# Use ease-out curve for smooth deceleration

animations:workspace_bezier = ease-out

Programmatic Animation Control

For developers extending Hyprland, you can trigger workspace switches programmatically:

// Trigger animation to workspace ID 2
PHLWORKSPACE target = g_pHyprMonitor->getWorkspaceByID(2);
if (target) {
    // left=false (slide from right), instant=false (animate)
    Animation::Workspace::startAnimation(target, ANIMATION_TYPE_IN, false, false, std::nullopt);
}

You can also create custom animation nodes at runtime:

// Define custom "myPop" animation
Config::animationTree()->setConfigForNode(
    "myPop",                      // name
    true,                         // enabled
    2.0f,                         // speed multiplier
    "ease-out",                   // bezier curve
    "popin 30%"                   // style string
);

Then reference it in rules:

windowrule = animation:myPop , class:^(Gedit)$

To inspect animated variables during debugging:

auto* alpha = myWindow->alpha(WINDOW_ALPHA);
if (alpha) {
    std::cout << "Current alpha: " << *alpha << "\n";
    std::cout << "Goal alpha:    " << alpha->goal() << "\n";
}

Summary

  • Enable globally with animations:enabled = true in src/config/values/ConfigValues.cpp.
  • Choose styles (slide, slidevert, fade, slidefade, popin) with optional direction and percentage parameters.
  • Configure workspaces via animations:workspace and animations:specialWorkspace using the animation tree in src/config/shared/animation/AnimationTree.hpp.
  • Override per-entity using windowrule or layerrule directives that inject styles into CAnimatedVariable instances.
  • Adjust dynamics with animations:workspace_speed and animations:workspace_bezier for fine-tuned motion.
  • Architecture relies on CHyprAnimationManager in src/animation/AnimationManager.cpp for ticking and WorkspaceAnimationController for workspace-specific implementation.

Frequently Asked Questions

How do I completely disable animations in Hyprland?

Set animations:enabled = false in your hyprland.conf. According to the source in src/config/values/ConfigValues.cpp, this boolean config value acts as the master switch that prevents the CHyprAnimationManager from processing variable updates during its tick cycle, effectively disabling all transitions while maintaining instant state changes.

What animation styles are available for workspace switching?

Hyprland supports slide, slidevert, fade, slidefade, and popin as defined in src/animation/WorkspaceAnimationController.cpp. These can be combined with directional keywords (left, right, top, bottom) and percentage values (e.g., slide left 80%) to control the distance traveled during the transition.

How do I apply different animations to specific applications?

Use the windowrule directive with the animation: prefix. For example, windowrule = animation:fade , class:^(Firefox)$ targets Firefox windows specifically. The rule system parses this syntax and calls CAnimatedVariable::setConfig() to override the default animation tree configuration for that window's properties.

Can I customize the speed of workspace transitions independently?

Yes, use animations:workspace_speed = 1.5 (where 1.0 is default) to adjust timing. This value is retrieved from CAnimationPropertyConfig and applied to the internal Hyprutils::Animation::CAnimation object. You can also define custom bezier curves with animations:workspace_bezier for non-linear acceleration patterns.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →