#5317·Waybar

custom module: font-family CSS no longer applies after feat(custom): add image — ligature icons render as literal text

Author: condaatjeCreated Sep 9, 2026Updated Sep 9, 2026
Labelscustom

Custom module font-family CSS no longer applies after feat(custom): add image — ligature icons render as literal text

Waybar version: 0.15.0 works; master @ 6d60c8e (2026-08-27) broken Compositor: Hyprland 0.56.2 (Lua config) — unlikely relevant, included for completeness Module: custom/* (specifically ML4W's custom/notification)

Summary

On master, a custom module whose format-icons value is a ligature name in a PUA/ligature font (e.g. Material Icons notifications_active) renders the icon's literal name instead of the glyph, because the per-module CSS rule that sets font-family no longer reaches the label.

Real-world symptom on an ML4W/Hyprland setup: the notification-module bell shows the word notifications_active instead of a bell. Same config on 0.15.0 renders the glyph correctly.

Root cause (traced)

822071f3 feat(custom): add image changed Custom's base class:

  • 0.15.0: class Custom : public ALabel → the label widget carries the widget name custom-notification, so this CSS hits the label:

    css
    #custom-notification {
        font-family: "Material Icons";
        font-size: 24px;
    }

    → Pango shapes the ligature → glyph renders.

  • master: class Custom : public AIconLabel, and AIconLabel's constructor (src/AIconLabel.cpp) does:

    c
    label_.unset_name();
    label_.get_style_context()->remove_class(MODULE_CLASS);
    box_.set_name(name);                        // name ("custom-notification") moves to box_
    box_.get_style_context()->add_class(id);

    The #custom-notification name and id class now live on the box, not the label. The label — the widget that renders the text — has its GTK name unset, so the font-family: "Material Icons" rule no longer applies to it. The ligature string falls back to the bar's generic font stack and renders as literal text.

Manual check that confirms the mechanism: running the exact same config/CSS against 0.15.0 vs master on this machine gives a bell glyph vs notifications_active text.

Minimal repro

css
#custom-notification {
    font-family: "Material Icons";
    font-size: 24px;
}
jsonc
{
  "layer": "top",
  "output": [],
  "modules-left": ["custom/notification"],
  "custom/notification": {
    "exec-if": "true",
    "exec": "while true; do printf '{\"text\":\"1\",\"alt\":\"notification\",\"tooltip\":\"1\",\"class\":\"notification\"}'; sleep 3; done",
    "return-type": "json",
    "format": "{icon}",
    "format-icons": {
      "notification": "notifications_active",
      "none": "notifications",
      "default": "none"
    }
  }
}

Expected vs actual

  • Expected: a Material Icons bell glyph.
  • Actual (master): the literal text notifications_active.

(Any material/nerd-font ligature-name icon in a custom module's format-icons is affected, not just this one — the trigger is label_.unset_name() in the AIconLabel path.)

Possible fix directions

  • In AIconLabel, keep #custom-<name> on the label (don't unset_name()), and move only the classes (MODULE_CLASS, dynamic script classes) onto the box. The widget name is what the common #custom-notification { font-family } pattern targets.
  • Or set the box name while also keeping the label name, whichever the project prefers — the current code moves the name off the text widget entirely.

Happy to open a PR if a maintainer confirms which direction is preferred.