Custom CSS isn't applied to my Discourse

AI-generated summary

User hlissner reported that custom CSS was not being applied on their Discourse instance after an update. pmusaraj confirmed that a recent upgrade to core broke the theme component and implemented a fix. However, hlissner encountered another issue where SCSS color variables did not inherit the theme’s color scheme. pmusaraj advised using CSS custom properties instead, and provided a guide on updating themes and plugins to support automatic dark mode.

hlissner attempted to add custom color variations in a color_definitions.scss file, but encountered issues with importing other stylesheets. pmusaraj fixed the import issue, but hlissner reported that the SCSS color variables still did not inherit the theme’s color scheme.

pmusaraj suggested that hlissner avoid inheriting from the parent theme’s SCSS variables, citing complexity concerns. hlissner agreed to use an alternative approach, but noted that it would require additional boilerplate SCSS code. pmusaraj offered to update an outdated guide on using variables in theme development.

hlissner discussed the limitations of using a single main theme with user-selectable color schemes, citing issues with color calculations and auto-generated variables. pmusaraj offered to explore alternative solutions.

As of yesterday’s update (of my hosted server at https://doomemacs.discourse.group), none of my custom CSS is applied. Changes to my theme(s) or components’ CSS have no effect (though changes their <head> or other HTML sections work fine).

There is one suspect link tag pointing to an empty stylesheet, whose hash changes each time I change my CSS. It appears Discourse is silently failing to compile my stylesheets. There are no mentions of failures in my error logs and discourse_theme uploads my stylesheets without complaint, but to no effect.

Would an admin kindly have a look?

~~I am not certain, but I think you might be hitting this change https://meta.discourse.org/t/restrict-editing-of-remote-themes/170051~~
Looks like this is incorrect :smiley:

Hi @hlissner, I am working on a fix for this, a recent upgrade to core broke the theme component on your instance. I should have a fix shortly.

The fix is now merged in core and your site is deployed @hlissner. Note that I disabled two theme components: the one with custom styles (which you can enable) and discourse-theme-category-homepage, which needs to be updated upstream before you can enable it. More details on that in Enhanced category-box display component - #7 by pmusaraj

Thank you! The stylesheets now correctly load, however, the SCSS color variables don’t appear to inherit my theme’s color scheme. e.g. $secondary yields its default value, #ffffff, instead of #282c34. Is this perhaps another regression from e8b8272?

Yes, it is another regression. It’s a bit of a tricky fix… and for the vast majority of color variables, theme components should be using CSS custom properties. You can look at this guide Update themes and plugins to support automatic dark mode, for an overview and some examples on how to add custom color variations in a special color_definitions.scss file in your theme component.

Let me know how it goes!

I’ve done so where I can, but without access to these variables I cannot transform colors based off my active scheme. e.g.

$primary-low: dark-light-choose(darken($secondary, 12%), lighten($secondary, 10%));

:root {
    --primary-low: #{$primary-low};
}

Is there a better way around this? I could add styles directly to each theme, but I intend to have many, and I’d rather handle some general cases from a central, global component where possible.

Yes, that makes sense, did you try adding that SCSS above to a new file in common/color_definitions.scss? It should just work if you add it there. (There is also a tab in the UI for that special stylesheet.)

Was about to try exactly that, then the discourse went down with a The software powering this discussion forum encountered an unexpected problem, haha.

You can access the site via /safe-mode, that disables themes and components and then you can see what happened.

This is yet another regression though, those SCSS errors should not blow up the whole site, I’ll certainly fix that in the next few days.

That worked! The color variables are properly set in color_definitions.scss’s scope. Only trouble is I can’t import other stylesheets from it. e.g.

// scss/globals.scss
$foo: "#000000";

// color_definitions.scss
@import "globals";
:root { --foo: #{$foo}; }

Yields this in the Discourse error logs:

SCSS compilation error: Error: File to import not found or unreadable: globals.scss.
        on line 129 of color_definitions.scss
>> @import "globals";

I can redesign my stylesheets to avoid the dependency though, so not a big deal, but could this be considered a bug?

Yes, I have a PR up to fix the import issue, should be merged by tomorrow.

https://github.com/discourse/discourse/pull/11963

Thanks for your help! The PR was merged, my instance was updated, and I can import styelsheets into color_definitions.scss, but this issue has resurfaced:

This time, this affects variables in color_definitions.scss as well.

Is it possible to do what you are trying to do without inheriting from the parent theme’s SCSS variables? That’s a very narrow use case and I would rather not add that complexity in core.

It’s certainly possible, only inconvenient, because it’ll require hundreds of lines of boilerplate scss per-theme (and a build system for it to share variables across them all) that weren’t necessary a week ago. That said, it’d probably be best to do this anyway, to avoid issues with future refactors of Discourse’s build process. I’ll do that. Thanks!

Perhaps this guide should be revised/removed if it’s no longer supported.

That guide is a bit outdated, yes, although what is tripping up in your case is not core variables but rather SCSS colors in a component not inheriting the theme’s color scheme. (Nonetheless, I will go through the guide and update it.)

A little bit of context: in August/September 2020 we moved to using CSS custom properties for colors. The main reason for that change was so that we could support automatic dark mode in a way that was light and fast. Themes have CSS and JS, so they cannot be switched quickly, but using CSS custom properties, color schemes can be flipped on the fly, without refreshing the page.

I see in your site that you have 4 themes with a color scheme each and a component shared across the themes for the shared styles. You could achieve essentially the same thing with one main theme (that would contain all the shared styles) and 4 user-selectable color schemes. You would need to move all color calculations in the color_definitions.scss file of the main theme, but it is doable, I’ll try to find some time and give this a shot tomorrow.

That would be ideal, but I arrived at the current setup because multiple color schemes wouldn’t work for me. Some color schemes produce poor colors for auto-generated variables like --primary-low. Simply redefining the variable may work for one color scheme, but not another. A more general solution is possible if we redefine it based off $primary, or conditionally based on color scheme id/name, but without either multiple themes is necessary, so I can have a per-theme color_definitions.scss (the duplication I’d like to avoid). Or is there a better option I’m missing?