# How to Set Up Multiple Monitors with Hyprland: A Complete Configuration Guide

> Easily set up multiple monitors with Hyprland. Learn to configure displays in hyprland.lua by defining hl monitor blocks for resolutions positions and scales to create your ideal virtual desktop.

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

---

**Configure multiple displays in Hyprland by defining `hl.monitor` blocks in your `~/.config/hypr/hyprland.lua` file, specifying output names, resolutions, positions, and scales to build your virtual desktop layout.**

Setting up multiple monitors with Hyprland involves a sophisticated configuration pipeline that transforms Lua-based display rules into live Wayland monitor objects. According to the hyprwm/Hyprland source code, the compositor processes your monitor declarations through a dedicated parsing and layout system, allowing precise control over multi-display arrangements ranging from simple laptop-plus-external setups to complex multi-head workstations.

## How Hyprland Processes Monitor Configuration

When Hyprland initializes, it reads your configuration file and processes each `hl.monitor` declaration through a specialized architecture designed to validate rules and compute final display positions.

### Parsing and Rule Validation

The **monitor rule parser** ([`src/config/shared/monitor/Parser.hpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/shared/monitor/Parser.hpp)) handles the initial configuration reading. This component, implemented in `CMonitorRuleParser`, validates fields such as `output`, `mode`, `position`, `scale`, and `transform`. It converts string values like `"1920x1080@60"` into internal `CMode` structures and resolves output identifiers (e.g., `"DP-1"`).

### Rule Collection and Management

After parsing, the **monitor rule manager** ([`src/config/shared/monitor/MonitorRuleManager.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/shared/monitor/MonitorRuleManager.cpp)) collects all `CMonitorRule` objects into a registry. This manager supports advanced features including monitor mirroring and disabling specific outputs, providing lookup utilities that the compositor queries during initialization.

### Runtime State and Layout Calculation

The **monitor state tracker** ([`src/state/MonitorStateTracker.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/state/MonitorStateTracker.cpp)) iterates over the stored rules to instantiate live `CMonitor` objects. Once these objects exist, the **monitor layout controller** ([`src/state/MonitorLayoutController.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/state/MonitorLayoutController.cpp)) calculates final positions using either explicit coordinates or automatic placement keywords, applying scaling and transformations to complete the virtual desktop arrangement.

## Basic Two-Monitor Setup

For a typical laptop with an external display, use automatic placement keywords to position the secondary monitor relative to the primary.

```lua
-- Primary monitor (built-in laptop display)
hl.monitor({
    output   = "eDP-1",
    mode     = "1920x1080@60",
    position = "auto",
    scale    = "1",
})

-- Secondary monitor (external display to the right)
hl.monitor({
    output   = "DP-1",
    mode     = "2560x1440@144",
    position = "auto-right",
    scale    = "1.5",
})

```

The `auto-right` keyword instructs `MonitorLayoutController` to place this display immediately to the right of the previously configured monitor, creating a seamless extended desktop.

## Advanced Layout Strategies

### Explicit Coordinate Positioning

For precise control over complex arrangements, specify exact pixel coordinates (`"x y"`) relative to the origin (0,0):

```lua
-- Left ultrawide monitor
hl.monitor({
    output   = "HDMI-A-1",
    mode     = "3440x1440@100",
    position = "0 0",
    scale    = "auto",
})

-- Center monitor (positioned at the right edge of the left monitor)
hl.monitor({
    output   = "DP-1",
    mode     = "2560x1440@144",
    position = "3440 0",
    scale    = "auto",
})

-- Right monitor (continuing the horizontal span)
hl.monitor({
    output   = "DP-2",
    mode     = "1920x1080@60",
    position = "6000 0",
    scale    = "auto",
})

```

This configuration creates a 10,960-pixel wide workspace where `MonitorLayoutController` respects your exact positioning without automatic adjustments.

### Automatic Placement Keywords

Hyprland supports several placement directives for dynamic layouts:

- **`auto`** – Places the monitor at the first available space (typically used for the primary display)
- **`auto-left`** – Positions to the left of the previously placed monitor
- **`auto-right`** – Positions to the right (ideal for standard dual-monitor setups)
- **`auto-up`** – Places above the previous monitor
- **`auto-down`** – Places below the previous monitor

### Disabling Unused Outputs

To ignore a specific output (useful for handling disconnected docks or disabling broken panels), set the `disabled` flag:

```lua
hl.monitor({
    output   = "DP-3",
    disabled = true,
})

```

This rule is processed by `CMonitorRuleParser::setDisabled()`, which excludes the monitor from the active list during state creation.

### Mirroring Displays

Clone one monitor's output to another device using the `mirror` field:

```lua
-- Primary display
hl.monitor({
    output   = "DP-1",
    mode     = "1920x1080@60",
    position = "auto",
})

-- Mirrored display (shows identical content to DP-1)
hl.monitor({
    output   = "HDMI-A-1",
    mirror   = "DP-1",
})

```

The `CMonitorRuleParser::setMirror()` function links the secondary framebuffer to the primary output, implemented in [`src/config/shared/monitor/MonitorRule.hpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/shared/monitor/MonitorRule.hpp).

## Organizing Your Configuration

For maintainability, split monitor definitions into separate Lua files and require them in your main configuration:

```lua
-- In ~/.config/hypr/monitors.lua
hl.monitor({ output = "eDP-1", mode = "preferred", position = "auto", scale = "auto" })
hl.monitor({ output = "DP-1", mode = "2560x1440@144", position = "auto-right", scale = "1.25" })

-- In ~/.config/hypr/hyprland.lua
require("monitors")

```

Because `MonitorRuleManager` processes `hl.monitor` calls in the order they appear, loading external files preserves your intended placement sequence while keeping your main configuration file clean.

## Summary

- **Configuration Location**: Define monitors in `~/.config/hypr/hyprland.lua` using the `hl.monitor` Lua API.
- **Core Components**: The system uses `CMonitorRuleParser` (validation), `MonitorRuleManager` (storage), and `MonitorLayoutController` (position calculation).
- **Positioning Options**: Use `"x y"` for explicit coordinates or `auto-*` keywords for relative placement.
- **Advanced Features**: Disable outputs with `disabled = true` or clone displays using the `mirror` field referencing another output name.
- **Scaling**: Set `scale` to `"auto"` for DPI detection or specific values like `"1.5"` for high-DPI displays.

## Frequently Asked Questions

### How do I find the correct output name for my monitor?

Hyprland uses the names reported by the underlying Wayland backend (typically matching `wlr-randr` or `xrandr` output). Common prefixes include `eDP-1` for internal laptop panels, `DP-` for DisplayPort connections, and `HDMI-A-` for HDMI ports. Run `hyprctl monitors` from a terminal to list currently detected outputs and their names.

### Can I use automatic scaling instead of fixed values?

Yes. Set `scale = "auto"` in your `hl.monitor` block to let Hyprland automatically detect and apply the appropriate DPI scaling based on the monitor's physical dimensions and resolution. This is handled during the layout calculation phase in `MonitorLayoutController`.

### What happens if I disconnect a monitor configured with explicit coordinates?

If a monitor defined with explicit `position` coordinates becomes unavailable, Hyprland removes it from the active layout but preserves the virtual desktop space. Windows previously on that display may need redistribution. The `MonitorStateTracker` monitors connection events and updates the compositor state accordingly.

### How do I rotate a monitor 90 degrees?

Use the `transform` field with a rotation value: `transform = "90"` for 90 degrees clockwise, `"180"` for upside-down, or `"270"` for 90 degrees counter-clockwise. The layout controller applies this transformation after positioning, affecting both the display orientation and how input coordinates are mapped.