How Can I Fix a False Error When Defining Colors in Style.css

I’ve hit this exact snag twice while theming Waybar and Wofi: I define a color, my editor screams in red, and yet the bar renders perfectly. Other times, I try “proper” (browser) CSS variables and the apps crash with parser errors. Here’s what’s going on, how I fixed it, and a full, practical theme you can use right now.

The “First Code” That Looks Wrong

This is the exact snippet I started with:

@define-color background #24283b;

window {
    background-color: @background;
}

What’s “Wrong” With This

I’m theming Waybar/Wofi. Both use GTK’s CSS dialect, not the same CSS engine you’d find in a web browser. GTK adds its own features:

  • @define-color <name> <value>;
  • Referencing colors with @color_name (e.g., @background)

Most editors and CSS linters don’t know GTK’s dialect, so they throw false errors like:

  • Unknown at rule @define-color
  • property values expected
  • at-rule or selector expected

Those are editor/linter false positives. GTK’s CSS parser (the one Waybar/Wofi actually use) understands @define-color and @background just fine. So the code is OK your editor is the one confused.

Why The “no error” Version Actually Fail

I tried switching to browser-style CSS variables so my editor would calm down:

:root {
    --background: #24283b;
}

window {
    background-color: var(--background);
}

It looked clean in my editor and then Waybar/Wofi crashed with:

  • Invalid name of pseudo-class :root
  • 'var' is not a valid color name

That’s because GTK CSS does not support :root, --custom-properties, or var(). So this version will fail at runtime even if your editor says it’s fine.

Conclusion: Keep GTK’s @define-color and ignore the false editor errors or teach your editor to ignore them.

Make The Editor Stop Complaining

If you use VS Code, you can relax its CSS validation just for this workspace:

// .vscode/settings.json (workspace settings)
{
  "css.lint.unknownAtRules": "ignore",
  "css.validate": false
}

In Neovim or other editors using a CSS language server, you can either disable validation for your Waybar/Wofi config folders, or switch the filetype / syntax to something like gtkcss if your setup supports it.

Project Setup Where Files Live and How I Eeload

  • Waybar CSS: ~/.config/waybar/style.css
  • Wofi CSS: ~/.config/wofi/style.css

Reload steps I use:

# Waybar: kill and restart
pkill waybar && waybar &

# Wofi: just close and reopen Wofi
wofi --show drun

My Practical Theme (Waybar + Wofi)

I built a small but complete theme with a palette, hover/active states, and a few quality of life tweaks. Paste one or both snippets into the paths above.

Waybar richer style.css (GTK CSS)

/* ---------- Color palette (GTK CSS variables) ---------- */
@define-color bg            #24283b;
@define-color bg-alt        #1f2233;
@define-color fg            #c0caf5;
@define-color muted         #a9b1d6;
@define-color accent        #7aa2f7;
@define-color warning       #e0af68;
@define-color error         #f7768e;
@define-color ok            #9ece6a;
@define-color border        #414868;
@define-color shadow        rgba(0, 0, 0, 0.35);

/* ---------- Global defaults ---------- */
* {
  color: @fg;
  border: 0;
  font-family: JetBrainsMono Nerd Font, monospace;
  font-size: 12pt;
}

/* Waybar’s top-level window */
window#waybar {
  background-color: @bg;
  border-bottom: 1px solid @border;
  box-shadow: 0 2px 8px @shadow;
}

/* Module containers share the same capsule look */
#workspaces,
#clock,
#pulseaudio,
#cpu,
#memory,
#network,
#battery,
#tray,
#backlight,
#temperature {
  background: @bg-alt;
  margin: 4px 6px;
  padding: 6px 10px;
  border-radius: 10px;
}

/* Workspaces: active/urgent/hover */
#workspaces button {
  color: @muted;
  margin: 0 2px;
  padding: 4px 8px;
  border-radius: 8px;
  background: transparent;
}

#workspaces button:hover {
  background: rgba(122, 162, 247, 0.08); /* accent tint */
  color: @fg;
}

#workspaces button.active {
  background: @accent;
  color: @bg;
  font-weight: 600;
}

#workspaces button.urgent {
  background: @error;
  color: @bg;
}

/* Status accents for other modules */
#battery.charging,
#network.connected {
  color: @ok;
}

#battery.warning,
#temperature.critical,
#network.disconnected {
  color: @warning;
}

/* Volume hover/active feedback */
#pulseaudio:hover {
  background: rgba(122, 162, 247, 0.12);
}

/* Tooltip styling (GTK) */
tooltip {
  background: @bg-alt;
  color: @fg;
  border: 1px solid @border;
  border-radius: 8px;
}

Wofi Clean Theme With Focused/Selected States

/* ---------- Colors ---------- */
@define-color bg        #24283b;
@define-color bg-alt    #1f2233;
@define-color fg        #c0caf5;
@define-color muted     #a9b1d6;
@define-color accent    #7aa2f7;
@define-color border    #414868;

/* ---------- Window ---------- */
window {
  background: @bg;
  color: @fg;
  border: 1px solid @border;
  border-radius: 12px;
  padding: 8px;
}

/* ---------- Input ---------- */
#input {
  background: @bg-alt;
  color: @fg;
  border: 1px solid @border;
  border-radius: 10px;
  padding: 8px 10px;
  margin: 6px;
}

#input:focus {
  border-color: @accent;
  box-shadow: 0 0 0 2px rgba(122,162,247,0.25);
}

/* ---------- Entries ---------- */
#entry {
  padding: 6px 10px;
  margin: 2px 6px;
  border-radius: 8px;
  color: @muted;
}

#entry:hover {
  background: rgba(122,162,247,0.10);
  color: @fg;
}

#entry:selected,
#entry:focus {
  background: @accent;
  color: @bg;
  font-weight: 600;
}

/* ---------- Scroll ---------- */
#scroll {
  padding: 6px 0;
}

Reusable Palettes, Quick Swapping and Translucency

Here are a few extra tricks I now keep in my setup.

Maintain multiple palettes (dark/light) inside one file

You can keep two palettes and toggle comments:

/* ===== DARK PALETTE ===== */
@define-color bg            #24283b;
@define-color bg-alt        #1f2233;
@define-color fg            #c0caf5;
@define-color accent        #7aa2f7;

/* ===== LIGHT PALETTE ===== */
/* @define-color bg         #f7f7fb; */
/* @define-color bg-alt     #ececf3; */
/* @define-color fg         #1e2230; */
/* @define-color accent     #3d5afe; */

Uncomment the palette you want, then reload Waybar/Wofi.

Add translucency only where it looks good

GTK accepts rgba(), so I selectively apply a tint:

#pulseaudio,
#clock {
  background: rgba(31, 34, 51, 0.7); /* @bg-alt with ~70% opacity */
}

Tip: Avoid translucency on the entire bar unless your wallpaper is calm; otherwise text contrast suffers.

Hot reload helpers (tiny script)

I keep a small script to swap themes and reload Waybar:

#!/usr/bin/env bash
set -euo pipefail

THEME_DIR="$HOME/.config/waybar"
STYLE="$THEME_DIR/style.css"
DARK="$THEME_DIR/style.dark.css"
LIGHT="$THEME_DIR/style.light.css"

case "${1:-dark}" in
  dark)  cp "$DARK" "$STYLE" ;;
  light) cp "$LIGHT" "$STYLE" ;;
  *) echo "Usage: $0 [dark|light]"; exit 1 ;;
esac

pkill waybar || true
nohup waybar >/dev/null 2>&1 &

I keep style.dark.css and style.light.css next to the main file and run switchbar light or switchbar dark.

Troubleshooting Checklist

  • Red squiggles only in editor? It’s probably just the linter. Try it in Waybar/Wofi anyway.
  • Using :root, --foo, or var()? That’s browser CSS. Replace with @define-color + @foo.
  • Correct paths?
    • Waybar: ~/.config/waybar/style.css
    • Wofi: ~/.config/wofi/style.css
  • Reloaded the app? Restart Waybar; re-open Wofi.
  • Typos in color names? @background must match @define-color background.
  • Opacity values are rgba(r,g,b,a); hex + alpha (like #RRGGBBAA) is not always supported the way you expect in every GTK version.

Final Thought

Once I understood that Waybar and Wofi speak GTK CSS, everything clicked. The “errors” were never in my theme they were in my editor’s assumptions. By sticking with @define-color and @color_name, I get reliable, readable configs, and when I want extra polish, I layer in hover states, capsule modules, and small translucency touches.

Related blog posts