Absolute / domain-relative path for asset URLs in CSS

The frontend styles are added as editor styles so Gutenberg can wrap and preview them:

<?php
namespace App;
use function Roots\asset;
add_action('after_setup_theme', function () {
    // Add frontend styles as editor styles
    add_editor_style(asset('app.css')->uri());
});

This works very well, all styles appear correctly in the editor (except some exceptions because of the extra editor DOM, etc).

However, the asset url(...)s inside the CSS are still relative to their stylesheet (e.g. url(images/water-sand.9a11c3.jpg). This is completely valid and works perfectly fine in frontend. But the Gutenberg editor postprocesses those styles, wrapping their selectors (notably the body element selector) in an extra wrapper class selector (.editor-styles-wrapper) and then injects those styles as inline styles.
By having those styles as inline styles, the references relative to the originating stylesheet won’t work anymore.

Now this probably be the job of the Gutenberg style postprocessing, but until this is fixed, would it be possible to let bud output those asset url(...)s relative to the site domain or as absolute URLs?
Then those URLs will still work, even in these inlined styles.

I think the way to do this is modifying the rules handling static assets.

bud doesn’t use url-loader or anything like that; all of the static assets handlers are defined using Rule.generator.

naive implementation:

["image", "font", "svg", "json"].map((key) => {
  app.build.rules[key].setGenerator(() => ({
    publicPath: "http://example.test/app/themes/sage/public/",
  }));
});

You might also need/want to set outputPath if you are doing this:

1 Like

Thanks, this works!

Gutenberg should actually rewrite those editor styles, but it clearly doesn’t happen, the editor styles are wrapped in an extra selector (.editor-styles-wrapper), but the url(...)s are still stylesheet-relative, and fail to load.
Related issue:

Alright, the underlying issue is the fact that currently remotely added editor styles (fetched by URI) don’t get a baseURL field when being used in the Gutenberg Block Editor. The missing baseURL field prevents the Gutenberg editor post-processing from rewriting those stylesheet-relative URLs, resulting in broken styles.

Relevant WordPress trac ticket:
https://core.trac.wordpress.org/ticket/55728#ticket

The editor styles can be added as files by path relative to theme directory, so the styles are not remotely fetched and the baseURL field is added:

<?php
namespace App;
use function Roots\asset;
use Webmozart\PathUtil\Path; // library is used
add_action('after_setup_theme', function () {
    add_theme_support('editor-styles');
    // Add frontend styles as editor styles
    // Must be added by relative path (not remote URI)
    // (@see https://core.trac.wordpress.org/ticket/55728#ticket)
    $absCssPath = asset('app.css')->path();
    $absTemplatePath = get_template_directory();
    // path to editor styles file must be relative to the theme directory
    $relCssPath = Path::makeRelative($absCssPath, $absTemplatePath);
    add_editor_style($relCssPath);
});

1 Like