# Waybar
Waybar is a highly customizable status bar for Wayland compositors, specifically designed for Sway and other wlroots-based window managers like Hyprland, River, Niri, DWL, and Wayfire. It provides a modular architecture where each component (clock, battery, network, etc.) is a separate module that can be independently configured and styled using JSON configuration and CSS styling.
The bar supports multiple outputs, custom scripts, system tray integration, and extensive theming capabilities through GTK CSS. Waybar is written in C++20 and uses GTK3 for rendering, making it lightweight and highly performant while offering deep customization through its configuration files located in `~/.config/waybar/`.
## Configuration File Structure
The configuration uses JSONC format (JSON with comments) and defines bar position, modules, and their settings. The config file should be named `config` or `config.jsonc` and placed in `~/.config/waybar/`.
```jsonc
// ~/.config/waybar/config
{
"layer": "top",
"position": "top",
"height": 30,
"spacing": 4,
"modules-left": ["sway/workspaces", "sway/mode", "sway/window"],
"modules-center": ["clock"],
"modules-right": ["pulseaudio", "network", "cpu", "memory", "battery", "tray"],
"sway/workspaces": {
"disable-scroll": true,
"all-outputs": true,
"format": "{name}: {icon}",
"format-icons": {
"1": "",
"2": "",
"3": "",
"urgent": "",
"focused": "",
"default": ""
}
},
"clock": {
"timezone": "America/New_York",
"tooltip-format": "{:%Y %B}\n{calendar}",
"format": "{:%H:%M}",
"format-alt": "{:%Y-%m-%d}"
},
"battery": {
"bat": "BAT0",
"states": {
"warning": 30,
"critical": 15
},
"format": "{capacity}% {icon}",
"format-charging": "{capacity}% ",
"format-plugged": "{capacity}% ",
"format-icons": ["", "", "", "", ""]
},
"network": {
"format-wifi": "{essid} ({signalStrength}%) ",
"format-ethernet": "{ipaddr}/{cidr} ",
"format-disconnected": "Disconnected ⚠",
"tooltip-format": "{ifname} via {gwaddr}"
},
"pulseaudio": {
"format": "{volume}% {icon}",
"format-muted": "",
"format-icons": {
"default": ["", "", ""]
},
"on-click": "pavucontrol"
},
"cpu": {
"format": "{usage}% ",
"tooltip": false
},
"memory": {
"format": "{}% "
},
"tray": {
"spacing": 10
}
}
```
## CSS Styling
Waybar uses GTK CSS for styling. Create a `style.css` file in `~/.config/waybar/` to customize the appearance of modules and the bar itself.
```css
/* ~/.config/waybar/style.css */
* {
font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif;
font-size: 13px;
border: none;
border-radius: 0;
min-height: 0;
}
window#waybar {
background-color: rgba(43, 48, 59, 0.8);
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff;
transition-property: background-color;
transition-duration: 0.5s;
}
window#waybar.hidden {
opacity: 0.2;
}
#workspaces button {
padding: 0 5px;
background-color: transparent;
color: #ffffff;
}
#workspaces button:hover {
background: rgba(0, 0, 0, 0.2);
}
#workspaces button.focused,
#workspaces button.active {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button.urgent {
background-color: #eb4d4b;
}
#clock, #battery, #cpu, #memory, #network, #pulseaudio, #tray {
padding: 0 10px;
color: #ffffff;
}
#clock {
background-color: #64727D;
}
#battery {
background-color: #ffffff;
color: #000000;
}
#battery.charging, #battery.plugged {
color: #ffffff;
background-color: #26A65B;
}
#battery.critical:not(.charging) {
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: steps(12);
animation-iteration-count: infinite;
animation-direction: alternate;
}
@keyframes blink {
to {
background-color: #ffffff;
color: #000000;
}
}
#cpu {
background-color: #2ecc71;
color: #000000;
}
#memory {
background-color: #9b59b6;
}
#network {
background-color: #2980b9;
}
#network.disconnected {
background-color: #f53c3c;
}
#pulseaudio {
background-color: #f1c40f;
color: #000000;
}
#pulseaudio.muted {
background-color: #90b1b1;
color: #2a5c45;
}
#tray {
background-color: #2980b9;
}
tooltip {
background: rgba(43, 48, 59, 0.5);
border: 1px solid rgba(100, 114, 125, 0.5);
}
tooltip label {
color: white;
}
```
## Multiple Instances of a Module
You can create multiple instances of the same module by adding a `#` suffix with a custom identifier.
```jsonc
{
"modules-right": ["battery", "battery#bat2"],
"battery": {
"bat": "BAT0",
"format": "{capacity}% {icon}",
"format-icons": ["", "", "", "", ""]
},
"battery#bat2": {
"bat": "BAT1",
"format": "{capacity}% {icon}",
"format-icons": ["", "", "", "", ""]
}
}
```
```css
/* Style the second battery instance */
#battery.bat2 {
background-color: #66cc99;
}
```
## Custom Module with Scripts
The custom module allows running external scripts and displaying their output. It supports JSON return format for dynamic styling and tooltips.
```jsonc
{
"modules-left": ["custom/weather", "custom/media"],
"custom/weather": {
"exec": "curl -s 'wttr.in/?format=1'",
"interval": 3600,
"format": "{}",
"tooltip": true
},
"custom/media": {
"format": "{icon} {}",
"return-type": "json",
"max-length": 40,
"format-icons": {
"spotify": "",
"default": ""
},
"escape": true,
"exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null"
},
"custom/power": {
"format": " ",
"tooltip": false,
"menu": "on-click",
"menu-file": "$HOME/.config/waybar/power_menu.xml",
"menu-actions": {
"shutdown": "shutdown now",
"reboot": "reboot",
"suspend": "systemctl suspend",
"hibernate": "systemctl hibernate"
}
}
}
```
## Multi-Output Configuration
Configure different bars for different monitors using the `output` property or create multiple bar configurations in an array.
```jsonc
[
{
"layer": "top",
"output": "eDP-1",
"position": "top",
"modules-left": ["sway/workspaces", "sway/mode"],
"modules-center": ["sway/window"],
"modules-right": ["battery", "clock", "tray"]
},
{
"layer": "top",
"output": ["DP-1", "HDMI-A-1"],
"position": "bottom",
"modules-left": ["sway/workspaces"],
"modules-right": ["clock"]
},
{
"layer": "top",
"output": "!eDP-1",
"position": "top",
"modules-right": ["cpu", "memory", "clock"]
}
]
```
## States for Conditional Styling
Many modules support states that trigger CSS classes based on percentage values. States allow dynamic styling based on module values.
```jsonc
{
"battery": {
"bat": "BAT0",
"states": {
"good": 95,
"warning": 30,
"critical": 15
},
"format": "{capacity}% {icon}",
"format-good": "{capacity}% ",
"format-warning": "{capacity}% ",
"format-critical": "{capacity}% ",
"format-charging": "{capacity}% ",
"format-icons": ["", "", "", "", ""]
},
"cpu": {
"format": "{usage}% ",
"states": {
"warning": 70,
"critical": 90
}
},
"memory": {
"format": "{percentage}% ",
"states": {
"warning": 70,
"critical": 90
}
}
}
```
```css
#battery.good {
background-color: #26A65B;
}
#battery.warning {
background-color: #f39c12;
}
#battery.critical {
background-color: #e74c3c;
animation: blink 0.5s steps(12) infinite alternate;
}
#cpu.warning {
background-color: #f39c12;
}
#cpu.critical {
background-color: #e74c3c;
}
#memory.warning {
background-color: #f39c12;
}
#memory.critical {
background-color: #e74c3c;
}
```
## Module Actions and Click Events
Modules support click, scroll, and other mouse events to execute commands or trigger built-in actions.
```jsonc
{
"clock": {
"format": "{:%H:%M}",
"format-alt": "{:%Y-%m-%d}",
"on-click": "gnome-calendar",
"on-click-right": "gnome-clocks",
"actions": {
"on-click-right": "mode",
"on-scroll-up": "shift_up",
"on-scroll-down": "shift_down"
}
},
"pulseaudio": {
"format": "{volume}% {icon}",
"format-muted": "",
"on-click": "pavucontrol",
"on-click-right": "pactl set-sink-mute @DEFAULT_SINK@ toggle",
"on-scroll-up": "pactl set-sink-volume @DEFAULT_SINK@ +5%",
"on-scroll-down": "pactl set-sink-volume @DEFAULT_SINK@ -5%"
},
"network": {
"format-wifi": "{essid} ({signalStrength}%) ",
"format-disconnected": "Disconnected",
"on-click": "nm-connection-editor",
"on-click-right": "nmcli radio wifi off",
"on-click-middle": "nmcli radio wifi on"
},
"idle_inhibitor": {
"format": "{icon}",
"format-icons": {
"activated": "",
"deactivated": ""
},
"on-click-right": "swaylock"
}
}
```
## Temperature Module
Monitor system temperature with customizable critical thresholds and thermal zone selection.
```jsonc
{
"temperature": {
"thermal-zone": 2,
"hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
"critical-threshold": 80,
"format-critical": "{temperatureC}°C ",
"format": "{temperatureC}°C {icon}",
"format-icons": ["", "", ""],
"tooltip-format": "Temperature: {temperatureC}°C / {temperatureF}°F"
}
}
```
## MPD Music Module
Display and control Music Player Daemon status with playback information and controls.
```jsonc
{
"mpd": {
"format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ",
"format-disconnected": "Disconnected ",
"format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
"unknown-tag": "N/A",
"interval": 2,
"consume-icons": {
"on": " "
},
"random-icons": {
"off": " ",
"on": " "
},
"repeat-icons": {
"on": " "
},
"single-icons": {
"on": "1 "
},
"state-icons": {
"paused": "",
"playing": ""
},
"on-click": "mpc toggle",
"on-click-right": "mpc stop",
"on-scroll-up": "mpc next",
"on-scroll-down": "mpc prev"
}
}
```
## Sway Workspaces Configuration
Configure workspace display for Sway window manager with custom icons and formatting.
```jsonc
{
"sway/workspaces": {
"disable-scroll": true,
"all-outputs": true,
"warp-on-scroll": false,
"format": "{name}: {icon}",
"format-icons": {
"1": "",
"2": "",
"3": "",
"4": "",
"5": "",
"6": "",
"7": "",
"8": "",
"9": "",
"10": "",
"urgent": "",
"focused": "",
"default": ""
},
"persistent-workspaces": {
"1": [],
"2": [],
"3": [],
"4": [],
"5": []
}
},
"sway/mode": {
"format": "{}"
},
"sway/window": {
"max-length": 50,
"format": "{}",
"rewrite": {
"(.*) - Mozilla Firefox": " $1",
"(.*) - Visual Studio Code": " $1"
}
},
"sway/scratchpad": {
"format": "{icon} {count}",
"show-empty": false,
"format-icons": ["", ""],
"tooltip": true,
"tooltip-format": "{app}: {title}"
}
}
```
## Hyprland Configuration
Configure Waybar for Hyprland compositor with workspaces and window information.
```jsonc
{
"modules-left": ["hyprland/workspaces", "hyprland/submap", "hyprland/window"],
"hyprland/workspaces": {
"format": "{name}: {icon}",
"format-icons": {
"1": "",
"2": "",
"3": "",
"active": "",
"default": ""
},
"on-scroll-up": "hyprctl dispatch workspace e+1",
"on-scroll-down": "hyprctl dispatch workspace e-1",
"all-outputs": true,
"active-only": false
},
"hyprland/window": {
"max-length": 50,
"separate-outputs": true,
"rewrite": {
"(.*) - Mozilla Firefox": " $1",
"(.*) - Chromium": " $1"
}
},
"hyprland/submap": {
"format": "{}",
"max-length": 8,
"tooltip": false
},
"hyprland/language": {
"format": "{}",
"format-en": "EN",
"format-de": "DE"
}
}
```
## Backlight Module with Slider
Control screen backlight with a visual slider widget.
```jsonc
{
"modules-right": ["backlight", "backlight/slider"],
"backlight": {
"device": "intel_backlight",
"format": "{percent}% {icon}",
"format-icons": ["", "", "", "", "", "", "", "", ""],
"on-scroll-up": "brightnessctl set +5%",
"on-scroll-down": "brightnessctl set 5%-"
},
"backlight/slider": {
"min": 0,
"max": 100,
"orientation": "horizontal",
"device": "intel_backlight"
}
}
```
```css
#backlight-slider slider {
min-height: 0px;
min-width: 0px;
opacity: 0;
background-image: none;
border: none;
box-shadow: none;
}
#backlight-slider trough {
min-height: 10px;
min-width: 80px;
border-radius: 5px;
background-color: #2d3436;
}
#backlight-slider highlight {
min-width: 10px;
border-radius: 5px;
background-color: #f1c40f;
}
```
## PulseAudio Slider Module
Volume control with a visual slider for audio management.
```jsonc
{
"modules-right": ["pulseaudio", "pulseaudio/slider"],
"pulseaudio": {
"format": "{volume}% {icon} {format_source}",
"format-bluetooth": "{volume}% {icon} {format_source}",
"format-bluetooth-muted": " {icon} {format_source}",
"format-muted": " {format_source}",
"format-source": "{volume}% ",
"format-source-muted": "",
"format-icons": {
"headphone": "",
"hands-free": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": ["", "", ""]
},
"on-click": "pavucontrol"
},
"pulseaudio/slider": {
"min": 0,
"max": 100,
"orientation": "horizontal"
}
}
```
```css
#pulseaudio-slider slider {
min-height: 0px;
min-width: 0px;
opacity: 0;
background-image: none;
border: none;
box-shadow: none;
}
#pulseaudio-slider trough {
min-height: 10px;
min-width: 80px;
border-radius: 5px;
background-color: #2d3436;
}
#pulseaudio-slider highlight {
min-width: 10px;
border-radius: 5px;
background-color: #3498db;
}
```
## Disk Usage Module
Monitor disk space usage for specified mount points.
```jsonc
{
"disk": {
"interval": 30,
"format": "{percentage_used}% ",
"path": "/",
"tooltip-format": "Used: {used} / {total}\nFree: {free} ({percentage_free}%)"
},
"disk#home": {
"interval": 30,
"format": "{percentage_used}% ",
"path": "/home",
"tooltip-format": "Home: {used} / {total}"
}
}
```
## Keyboard State Module
Display keyboard lock states (Caps Lock, Num Lock, Scroll Lock).
```jsonc
{
"keyboard-state": {
"numlock": true,
"capslock": true,
"scrolllock": false,
"format": {
"numlock": "N {icon}",
"capslock": "C {icon}",
"scrolllock": "S {icon}"
},
"format-icons": {
"locked": "",
"unlocked": ""
}
}
}
```
## Privacy Module
Monitor applications using microphone, camera, or screen sharing through PipeWire.
```jsonc
{
"privacy": {
"icon-spacing": 4,
"icon-size": 18,
"transition-duration": 250,
"modules": [
{
"type": "screenshare",
"tooltip": true,
"tooltip-icon-size": 24
},
{
"type": "audio-out",
"tooltip": true,
"tooltip-icon-size": 24
},
{
"type": "audio-in",
"tooltip": true,
"tooltip-icon-size": 24
}
]
}
}
```
```css
#privacy {
padding: 0;
}
#privacy-item {
padding: 0 5px;
color: white;
}
#privacy-item.screenshare {
background-color: #cf5700;
}
#privacy-item.audio-in {
background-color: #1ca000;
}
#privacy-item.audio-out {
background-color: #0069d4;
}
```
## Include Configuration Files
Share common module configurations across multiple bars using the include directive.
```jsonc
// ~/.config/waybar/config
[
{
"layer": "top",
"position": "top",
"output": "eDP-1",
"include": [
"~/.config/waybar/modules.json"
],
"modules-left": ["sway/workspaces"],
"modules-right": ["battery", "clock"]
},
{
"layer": "top",
"position": "top",
"output": "HDMI-A-1",
"include": [
"~/.config/waybar/modules.json"
],
"modules-left": ["sway/workspaces"],
"modules-right": ["cpu", "memory", "clock"]
}
]
```
```jsonc
// ~/.config/waybar/modules.json
{
"clock": {
"tooltip-format": "{:%Y %B}\n{calendar}",
"format": "{:%H:%M}",
"format-alt": "{:%Y-%m-%d}"
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "{capacity}% {icon}",
"format-icons": ["", "", "", "", ""]
},
"cpu": {
"format": "{usage}% "
},
"memory": {
"format": "{}% "
}
}
```
## Bar Control with Signals
Control Waybar visibility and reload configuration using Unix signals.
```bash
# Toggle bar visibility
killall -SIGUSR1 waybar
# Reload configuration (waybar v0.9.5+)
killall -SIGUSR2 waybar
# Configure signal actions in config
```
```jsonc
{
"on-sigusr1": "toggle",
"on-sigusr2": "reload"
}
```
## Building from Source
Install and build Waybar from the official repository.
```bash
# Clone the repository
git clone https://github.com/Alexays/Waybar
cd Waybar
# Build with meson
meson setup build
ninja -C build
# Run without installing
./build/waybar
# Install system-wide
sudo ninja -C build install
# Run installed waybar
waybar
# Launch with specific config
waybar -c ~/.config/waybar/config -s ~/.config/waybar/style.css
# Debug mode with widget tree output
waybar -l debug
```
## Integration with Sway
Configure Sway to use Waybar as its status bar.
```bash
# Option 1: In ~/.config/sway/config
bar {
swaybar_command waybar
}
# Option 2: Exec at end of sway config
exec waybar
# Option 3: Run waybar with IPC support
bar {
id bar0
swaybar_command waybar -b bar0
}
```
```jsonc
// Enable Sway IPC integration
{
"ipc": true,
"id": "bar0"
}
```
## Summary
Waybar serves as a versatile, highly customizable status bar for Wayland compositors, particularly excelling with Sway, Hyprland, River, and other wlroots-based window managers. Its modular architecture supports system monitoring (CPU, memory, temperature, disk), hardware status (battery, backlight, network, bluetooth), media controls (MPD, MPRIS), window management (workspaces, taskbar, tray), and custom scripts. The combination of JSON configuration and GTK CSS styling provides extensive flexibility for creating unique, functional desktop environments.
Common integration patterns include multi-monitor setups with different bar configurations per output, shared module configurations via includes, state-based conditional styling for alerts and warnings, and custom modules executing external scripts for specialized functionality. The bar integrates seamlessly with compositor IPC for dynamic workspace management and supports both click/scroll interactions and menu-based interfaces for user interaction with modules.