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 = trueinsrc/config/values/ConfigValues.cpp. - Choose styles (
slide,slidevert,fade,slidefade,popin) with optional direction and percentage parameters. - Configure workspaces via
animations:workspaceandanimations:specialWorkspaceusing the animation tree insrc/config/shared/animation/AnimationTree.hpp. - Override per-entity using
windowruleorlayerruledirectives that inject styles intoCAnimatedVariableinstances. - Adjust dynamics with
animations:workspace_speedandanimations:workspace_bezierfor fine-tuned motion. - Architecture relies on
CHyprAnimationManagerinsrc/animation/AnimationManager.cppfor ticking andWorkspaceAnimationControllerfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →