9

GTK3 applications can be styled and themed with CSS. How can I force GTK to use solely the CSS shipped with my application, instead of combining / cascading it with the theme installed on the user's system?

Why would one want to do that? In theory, CSS would be a great rules-based styling system, where you just add one screen full judiciously chosen rules to define the looks of your application consistently. Unfortunately, in practice, people tend to add hundreds of brain-dead, repetitious definitions into their stylesheets, thereby counterfeiting the very nature of cascading.

The actual problem is that my application shall get the typical, subdued dark-grey look of a media handling application, irrespective of the global theme installed on the user's system. From reading the GTK documentation and the GTKmm tutorial, I came up with the following code to read my own CSS stylesheet:

auto screen = Gdk::Screen::get_default();
auto css_provider = Gtk::CssProvider::create();
try {
    css_provider->load_from_path(lib::resolveModulePath (stylesheetName, resourceSerachPath));

} catch(Glib::Error const& failure) {
    WARN(gui, "Failure while loading stylesheet '%s': %s", cStr(stylesheetName), cStr(failure.what()));
}

Gtk::StyleContext::add_provider_for_screen(screen, css_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

Technically this works perfect. However -- now I am forced to work "against" the CSS rules present on the user's system. If I start with setting a suitable border colour in the default rule and a dark grey background and suitable text colour in a rule for GtkWindow, plus some rule for text entry fields, I get the desired look on some parts, but whenever the user's system theme adds a specific definition for some specific widget or widget combination, thereby repeating explicitly the colours instead of inheriting them from a generic rule, I need to add yet another specific rule into my application style sheet to fix that specific case. That is, the possibly ill-guided structure of the installed system theme forces my application stylesheet into the same ill-guided bad practice and have hundreds of single-case definitions repeating the same values over and over.

Questions

  • How can I tell GTK to use only my stylesheet for my application?
  • Is there any viable alternative, which is not so radical, yet still allows me to use CSS the way it was intended to be used (minimal set of rules + cascading)?
knittl
  • 246,190
  • 53
  • 318
  • 364
Ichthyo
  • 8,038
  • 2
  • 26
  • 32

2 Answers2

7

You can use the reset.css file from the GTK demos to unset all existing rules.

A less radical alternative might be to just ignore user themes other than the default. Presumably if a user has a theme built with bad CSS practices, they nonetheless like that theme. So why shouldn't they be able to view your application with their preferred theme?

ptomato
  • 56,175
  • 13
  • 112
  • 165
  • thanks for the pointer. Didn't konw 'reset.css', but it points in the same direction I am exploring for a less-radical solution. I'll post that in a minute. – Ichthyo Oct 05 '18 at 15:45
  • "why shouldn't they be able to view your application with their preferred theme?". Important point, *yes they should!* -- However, the actual problem is they will then report "bugs" in my application, like "widget Blah" shows black text on dark grey background. The bad structure of user's themes will thus infect the structure of my own CSS – Ichthyo Oct 05 '18 at 15:48
  • In that case you can easily deflect their bug reports from your application to their theme... Nuking their entire theme seems a bit overkill to me. – ptomato Oct 21 '18 at 09:52
  • 2
    Strongly disagree. Whenever something goes wrong, by default finger-point at the user and blame her for "non-standard" setup, theming, configuration, etc. How am I even going to know beforehand, if some reported problem is maybe due to a quirk in the user's theme? – Ichthyo Oct 21 '18 at 14:48
  • I said redirect the bug report, not blame the user! – ptomato Oct 21 '18 at 20:20
  • 1
    you clearly lack experience in user support. Users perceive my application as broken. They don't care a damn how the styling of a toolkit set works. They install random shit from the net and forget about it. So in the end, I have to spend the time to find out what is broken. Or better yet, I write my application in a way that it copes automatically with the problematic area. Which is what my question was all about. – Ichthyo Oct 22 '18 at 01:15
  • Okay, I clearly lack experience — I'd better stop commenting then. Good luck. – ptomato Oct 22 '18 at 10:58
  • To make this answer clearer, why not say `*{ all: unset;}` ? – Cheetaiean Jul 05 '23 at 19:56
4

as pointed out by @ptomato, you can install a CSS to effectively override any pre-existing other rules on the system. However, this also shows a way towards a less radical solution: just cancel out the problematic parts of the pre-installed theme.

How does it work?

We add catch-all rules to the CSS, i.e. rules which somehow select any possible element, or at least a complete subtree. This is achieved by using a wildcard * in the selector. And since we install our stylesheet with a higher priority (typically GTK_STYLE_PROVIDER_PRIORITY_APPLICATION), these rules will "stamp over" every specific rule which happens to be present with lower priority.

  • we can use the value unset to clear out a setting
  • we can use the value inherit to force the property to be derived from the parent widget's setting of this property.

Especially for the given problem to get "grey-subdued media application" look within a environment with a "light" theme, we can use

* {
    color: inherit;
    background-color: inherit;
}

...to cancel out only the problematic part of the pre-existing "light" theme, which is the background and colour setting. We can then set our own values once at a central point, and they will be inherited as expected.

We can even expand on that idea and treat further problematic settings within a given scope, by using the wildcard below a CSS contextual selector. And a key trick to get that right is to use the GTK+ inspector on your running application and investigate the actual settings to find the lowest possible point still to "grab" the problematic setting. (To activate the GTK+ inspector run your application with GTK_DEBUG=interactive path/to/my/app )

Ichthyo
  • 8,038
  • 2
  • 26
  • 32