How to make my shortcode load scripts and styles, from within the plugin?

plugins_url expects the second parameter to be the main plugin file, which is why __FILE__ is used in examples, it’s assuming the code is in that file, but yours is not.

To fix this, you will need to retrieve __FILE__ in your main plugin file, store it, and pass it to your shortcode objects for use in plugins_url

There is also another major problem you’re unaware of

Shortcodes return their content as a string, but you’ve output the content directly. This breaks a lot of things because now the shortcode is output when it’s processed, not when it’s displayed.

This breaks a lot of things:

  • nested shortcodes
  • XMLRPC
  • any code that relies on the rendered content or the_content filter
  • Some REST API endpoints
  • Possibly even RSS feeds and some plugin sitemaps
  • Lots of things plugins and themes do

A classic sign that a plugin/theme is doing this is when shortcodes appear before the content regardless of where they were placed, or shortcodes appearing in the wrong order.

You can fix this though by using an output buffer to catch the output and assign it to a variable.

I would recommend changing your function signature to include the string return type. Doing this means it will create a PHP fatal error if your shortcode is built incorrectly ( and your shortcode is built incorrectly ):

public function layout() : string {