Theme Development: Compiling SASS files including paths


In my SCSS files, there are references to external assets like images and fonts. When I compile the styles via the terminal, the paths make sense as the output CSS file is written on /css/skins/default.css. Yet when site editors use the theme customizer, the rendered file is outputted on /application/files/presets/test-1.css, therefore all paths become invalid.

Is there a solution to this problem? maybe a variable that can be added in front of all paths to generate an absolute path?

Hi @shahroq - not off the top of my head, but let me poke around.

So the issue might be that in your compiled css before the customizer the paths are relative - does that ring any bells?

Hi @EvanCooper
Thank you for taking a look at this.

My first approach was using the relative path, and then when the editor uses the core customizer it breaks the path.

Then I switched to the absolute path, which definitely raised fewer complaints, but still, it breaks when the concrete is installed in any place other than the web server root. Check the last msg on this thread for example.

Got it - let me take another look.

I’ve had a chance to look into this. I’ve added a new auto-populated SCSS variable into the core that will be available in 9.2.5. This variable, concrete-theme-path, will automatically be populated with the path to the current theme. You should then be able to use it together with SCSS interpolation to load background images that work whether the theme is being built using the Laravel Mix customizer (to build the default skins) or the built-in Concrete customizer.

You can see this working in the latest commits of GitHub - concretecms/theme_bedrock_documentation: Companion code to the Version 9 theme documentation on, but I will explain it a little here.

First, you’ll want to make sure your webpack.mix.js file does NOT process CSS URLs. This is a webpack/laravel mix helper feature that will automatically rewrite relative URLs to their absolute ones. You don’t want this, because by default we want the URL to be relative. So add this somewhere in webpack.mix.js:

    processCssUrls: false

Next, somewhere in your SCSS files (I added it to the _shared-variables.scss file that the Flintstone demo theme includes from _common.scss) you’ll need to define the default version of the concrete-theme-path variable. This should point in a relative path from the root of the generated SCSS file back to the theme root. (Note: this is NOT computed from the root of wherever your SCSS include file is). In my Flintstone theme documentation (linked above), that path is ../../, so here’s how I define the variable:

$concrete-theme-path: '../../' !default;

Note the !default: you’ll need to include this so this variable can be overwritten by the customizer.

Finally, you use the variable wherever you need to get a path to your theme directory, for whatever reason you need. In the theme demo, we’re defining a background image in the _body.scss file, so here’s how we set the background image of the body tag to a file found in the images/ directory of the theme:

body {
  background: var(--bs-body-bg) url(#{$concrete-theme-path}/images/bg_flintstone.png) repeat fixed;

That should do it. When building the initial skins with npm run production the original value of concrete-theme-path will be used, which will load the image relative to the theme stylesheet, and these two things never change relative to each other. When using the customizer, the absolute path to the theme directory will be injected into this variable, and it will be used instead.

Hope this helps! Again, this will NOT work today, but when we release 9.2.5 in early February it should be available. Nothing is stopping you from coding your themes for use with this variable, however, since the worst that will happen will be that the theme doesn’t work well in the customizer (which is probably the case today)


This looks very cool, nice post

1 Like

Thank you @andrew . Just implemented it with 9.2.6 and it works perfectly.

That’s great news. Thanks for writing back