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.
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.
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);
});
namespace App;
use function Roots\asset;
add_action('after_setup_theme', function () {
// Add frontend styles as editor styles
// Must be added by relative path (not remote URI)
// (@see https://core.trac.wordpress.org/ticket/55728#ticket)
$relCssPath = asset('app.css')->relativePath(get_theme_file_path());
add_editor_style($relCssPath);
});
FWIW I solved this issue by adding my styles like this:
/**
* Add custom admin styles
*/
add_action('admin_enqueue_scripts', function($hook) {
// Only add custom admin styles on certain views to prevent
// conflicts with 3rd-party plugin styles (e.g. WS Form)
// https://wordpress.stackexchange.com/a/22954/185703
if ($hook == 'post-new.php' || $hook == 'post.php' || $hook == 'edit.php') {
// Note: enqueueCss() only works of thereâs also a JS file in the entry point
// https://github.com/roots/acorn/issues/229
// https://github.com/roots/bud/issues/1416
// https://github.com/roots/acorn/blob/2bf3d1c8c79a23b34f5c10c52df7926c83ab9e46/src/Roots/Acorn/Assets/Concerns/Enqueuable.php
bundle('admin')->enqueueCss();
}
});
@tedw: Though this would not enqueue the frontend styles as editor styles, but the separate admin styles.
This is also a fine approach, though I prefer using the frontend styles also as editor styles.
@strarsis Apologies, I accidentally copied the wrong snippet!
This is the code I meant to copy:
/**
* Add custom Gutenberg editor CSS and JS assets
* https://developer.wordpress.org/block-editor/tutorials/javascript/extending-the-block-editor/
* https://soderlind.no/hide-block-styles-in-gutenberg/
*/
add_action('enqueue_block_editor_assets', function() {
// NOTE: This wonât apply CSS to block pattern preview iframes
// when âbud devâ is running since the CSS is injected,
// but it will work in production or after running âbud buildâ
bundle('app')->enqueue();
}, 100);
Hm, but this would not add the styles as editor styles. The style isolation must be realized using .editor-styles-wrapper or a PostCSS plugin.
In contrast, when adding the styles as editor styles, the editor (Gutenberg) has to do the isolation by itself (wrapping the selectors with a styles wrapper selector).
Chiming in on this â the add_editor_style() function doesnât work unless you add theme support for editor-styles. Wasted a few hours figuring that out .
@ElvarP: Well, do you have editor-styles theme support enabled (add_theme_support( âeditor-stylesâ );) as @AlexHay pointed out?
Instead of using Sage specific asset functions, you would handle the path yourself, as:
add_action('after_setup_theme', function () {
add_editor_style('relative/path/to/styles.css');
});
Where relatives paths are resolved relative to the theme root directory.
Note: While specifying an URL instead of a path is possible, it currently causes issues with relative paths inside styles being post-processed by Gutenberg.
Adding the frontend-styles as-is, the Gutenberg editor will handle the style isolation automatically by post-processing the styles, but in the near future an iframe will be used instead.
Oh thanks for explaining, that was my problem. I was including the editor styles with specifying an URL so the style paths were wrong. Thanks for the fix!
Hey!
I have a problem that might be related to this, but not quite the same i think.
I have a multisitesetup and when iâm building bud for production i get a cors-error since assets (images/fonts) are pointing to base domain.
For example:
multisite base: multisite.com
subdomainsite: site1.multisite.com
when resolving fonts on site1.multisite.com i get an CORS error since it tries to resolve the asset on multisite.com. Iâm not really sure if this is an error in bud, wp or server setup but in wp_enqueue_scipts this function: bundle('app')->enqueue() calls
public function enqueueCss(string $media = 'all', array $dependencies = [])
{
$this->css(function ($handle, $src) use (&$dependencies, $media) {
wp_enqueue_style($handle, $src, $dependencies, null, $media);
$this->mergeDependencies($dependencies, [$handle]);
});
return $this;
}
and $src there is https://multisite.com, but i want it to be https://site1.multisite.com any suggestions?
Any suggestions for this issue?
Iâm thinking that one way to solve this might be to do a replace in $src from https:// to https://{siteurl} but in that case i think i would need do a proper wp_enqueue_style instead of bundle('app')->enqueue() but how do i access the handle from bundle?
dont like that switch_to_blog thing though, so might add âmainHomeâ to new site upon site creation or something so i can fetch $mainHome by doing get_option(âmainHomeâ) on current site or something.