Images in CSS, how to append WordPress path (setPublicPath set)

When I compile, the url points to:

https://[staging host].com/images/the-image.jpg instead of https://[staging host].com/wp-content/themes/the-theme-dir/images/the-image.jpg

I have setPublicPath set in bud.config.js:

/**
 * @typedef {import('@roots/bud').Bud} bud
 *
 * @param {bud} app
 */
module.exports = async (app) => {
  app
    /**
     * Application entrypoints
     *
     * Paths are relative to your resources directory
     */
    .entry({
      app: ['@scripts/app', '@styles/app'],
      editor: ['@scripts/editor', '@styles/editor'],
    })

    /**
     * These files should be processed as part of the build
     * even if they are not explicitly imported in application assets.
     */
    .assets('images')

    /**
     * These files will trigger a full page reload
     * when modified.
     */
    .watch('resources/views/**/*', 'app/**/*')

    /**
     * Target URL to be proxied by the dev server.
     *
     * This should be the URL you use to visit your local development server.
     */
     .proxy('http://example.test')

     /**
      * Development URL to be used in the browser.
      */
     .serve('http://0.0.0.0:3000')
 
     /**
      * Relative path to the public directory.
      */
     .setPublicPath('/wp-content/themes/the-theme-dir/public/');
};

How do I get the compiler to add “/wp-content/themes/the-theme-dir/”?

In the stylesheet(s) you either use stylesheet-relative paths (e.g. url('../../../images/test.png')) (paths are always relative to entrypoint stylesheet, even if imported in SASS by the way), or absolute paths, but then the asset URLs need to be resolved by bud (underlying webpack).

It appears that development for this feature is in progress, but I am not sure whether it is possible yet:

Using stylesheet-relative URLs works nice for me though and doesn’t introduce an extra layer of complexity (resolving asset URLs/modifying URLs), the only exception is when I want to modify inlined SVGs (where CSS limitations force me to do this) and then I use a PostCSS plugin, which would resolve URLs differently anyway.

1 Like

FWIW setting bud.setPublicPath('../'); worked for me (see [bug] Asset paths in CSS break if publicPath isn’t defined in bud.config.mjs when upgrading to Bud 6.1 · Issue #1547 · roots/bud · GitHub).

Unfortunately, that didn’t work for me.

Share your css.

I just tested it with:

package version
roots/acorn ^2.1
@roots/bud 6.3.2
@roots/sage 6.3.2
@roots/bud-tailwindcss 6.3.2

This is my source file (./resources/styles/app.css):

.target {
  background-image: url(@images/roots.svg);
}

With no public path set the emitted css (./public/css/app.css) is:

body {
  background: url(../images/roots.f12b27.svg);
}

And with the public path set the emitted css looks like this:

body {
  background: url(/app/themes/sage/public/images/roots.f12b27.svg);
}

Both of these are fine.

If you don’t want to use @src or @images, then you’ll need to resolve the path on your own.

So, this would be the source file:

body {
  background: url(../images/roots.svg);
}

And the emitted asset paths are exactly the same as above.

setPublicPath() doesn’t seem to do anything. Background images in CSS are compiled to host.com/images/the-image.jpg instead of host.com/wp-content/themes/theme-name/public/images/the-image.jpg regardless of what I put there.

I’m using Sass instead of Tailwind.

For example, the following CSS in source file resources/styles/common/_global.scss (imported to resources/styles/app.scss):

background-image: url(../images/text-accent.svg);

(Note ../)

Gives an error:

webpack built bud e7479ea4e005f3e68ef5 in 4268ms
⠦ 98% emitting

ERROR ./resources/styles/app.scss

Module not found: Error: Can’t resolve ‘./images/text-accent.svg’ in ‘./resources/styles’

ERROR ./resources/styles/app.scss

Module not found: Error: Can’t resolve ‘./images/background-accent.svg’ in ‘./resources/styles’

If I do

background-image: url(../../images/text-accent.svg);

(Note ../../)

It compiles OK, but the path is host.com/images/the-image.jpg which not what I need.

It should be host.com/wp-content/themes/theme-name/public/images/the-image.jpg

This issue still exists only with yarn dev.
When running yarn build public path is resolved.

Tested with:

package version
roots/acorn ^2.1
@roots/bud 6.3.3
@roots/sage 6.3.3
@roots/bud-tailwindcss 6.3.3

I use multidev env, so you also can set a public path from your .env or wp-config.php file, like

define('APP_PUBLIC_PATH', getenv('APP_PUBLIC_PATH') ?: '/app/themes/theme/public/');

Also, try to test with the key for bud bud build --publicPath /your-path/.

Both options work for me.

package version
roots/acorn ^2.1.2
@roots/bud 6.3.2
@roots/sage 6.3.2

I tried your solution but it did not work.
Public set is not working with yarn dev only in css!