A simple way to add responsive (breakpoint-specific) blocks in Gutenberg

The new WordPress Block Editor (a.k.a. Gutenberg) has improved immensely over the years, to the point where I am now willingly (although occasionally grudgingly) using it as my main development platform for client sites.

One area where it really falls down though is in smartly handling responsive breakpoints. There is some effort to make it responsive-friendly (though it’s definitely not “mobile first”), but there are really weird holes, like the fact that there’s no built-in way to apply consistent left and right margins on text content at smaller screen sizes; once you’re below the defined content width, if you don’t manually configure your theme to add padding/margins to headings, paragraphs, etc., and they don’t have a defined background color, the text will bump right up against the edges of the screen.

That’s not the problem I’m here to solve at the moment, however. Instead, I want to focus on a handy little tool I’ve been using in my WordPress development for over a decade: specialized CSS classes to designate blocks of content as only appearing on phones, or not appearing on phones.

By “phone” here I just mean the smallest standard breakpoint. I’m using the WordPress convention (at least it used to be the WordPress convention; I don’t feel like I can trust anything anymore) of setting that at the slightly odd (although even) value of 782 pixels.

What can you do with this? Once you have CSS classes that designate a block as only appearing on phones or not appearing on phones, then you can easily tailor your output to certain screens. Obviously (at least, I hope it’s obvious) this is not the ideal solution; it means you’re delivering HTML content — potentially redundant HTML content — that will not be seen by some users. But nothing in web development is perfect, and this can be a convenient way to get out of a pinch when, for example, you have a very complex desktop layout element that simply cannot be adapted in a usable way on phones. You can just hide that element on the phone breakpoint and, if desired, present the same content in a more simplified way to only phones. (Again… only if you can’t achieve a usable phone experience on the same HTML block via media query-specific CSS.)

OK, let’s get down to it. The first thing you need to do is register a couple of block styles. I am only making these styles applicable to the Group block, because that seems like a logical way to rein it in. Any block can easily be wrapped in a group, so if you need this feature, just do it.

register_block_style('core/group', array(
  'name' => 'no-phone',
  'label' => 'No phone'
));

register_block_style('core/group', array(
  'name' => 'phone-only',
  'label' => 'Phone only'
));

That should go into your functions.php file or wherever in your theme you are defining block characteristics. Ideally it should be in a function that is executed on the init action. Next, you need to make sure you’ve got a custom block style .css file enqueued for the Group block. You can place this wherever is appropriate within your theme; I happen to have a nested assets/css/blocks folder where I put mine. Here’s that bit of code, also for your function that runs on init.

wp_enqueue_block_style('core/group', array(
  'handle' => 'my-theme-core-group',
  'path' => get_theme_file_path('assets/css/blocks/core-group.css'),
  'src' => get_theme_file_uri('assets/css/blocks/core-group.css'),
));

And then in the referenced core-group.css file, you’ll need this:

@media screen and (max-width: 782px) {	
  .wp-block-group.is-style-no-phone {
    display: none !important;
  }
}

@media screen and (min-width: 783px) {
  .wp-block-group.is-style-phone-only {
    display: none !important;
  }
}

Now in the Block Editor, when you switch to the Styles tab when focused on a Group block, you’ll see your new style options:

The “house of cards” approach to development is a “fatal error” in itself

This morning my work of putting out a fire for one client was interrupted by the need to put out a blazing inferno for another client. Specifically, they’re running a big sale on their WooCommerce store, and the site was returning a fatal error.

Turning on debugging, I saw this message:

PHP Fatal error: Declaration of Dhii\\Container\\ProxyContainer::has($key) must be compatible with Psr\\Container\\ContainerInterface::has(string $id): bool

Ugh.

There is so much about this that I hate. Mainly, what is any of it for? I have to question whether any of the developers of PayPal Zettle POS for WooCommerce, the affected plugin, really know either. This plugin suffers from what I call the “house of cards” approach to development. Why write your own code if you can just slap together dozens of packages that already do the things you want? On the surface, that’s great. But the problem is, then you don’t really know what your own software does.

I recognize that this is a necessity in many cases. It’s just not practical to reinvent every wheel. But when your application is structured like this, you may have 6 different kinds of wheels, or wheels made out of other wheels, or wheels that also contain a kitchen sink. As usual, xkcd nails it:


Fortunately, WP_DEBUG let me see exactly where the errors were occurring, and although my 20 years of idiosyncratic PHP development experience didn’t help me to understand what the error meant, this StackExchange post did. I just had to change this:

public function has($key)

…to this:

public function has($key): bool

And then I had to do that about a dozen more times in various other files deeply nested in the plugin’s vendor folder, until the PHP fatal errors stopped appearing.

In the WordPress support forums, I discovered near the top of the list a post from someone else experiencing this same error, and the devs suggested it was probably a plugin conflict. They didn’t seem interested in pursuing the possibility that their own code was broken.

But, then again, it really isn’t their code. And that’s the problem.

I’m not above reproach here. I’m a WordPress developer. I use other people’s code all the time! I even sell a product that is substantially constructed out of other people’s code. But I am very judicious about what does or does not get placed in my vendor folder. And I realize that if something goes wrong with it, it’s up to me to fix it, even if it’s not my code.

Speaking of which… I have some updates to make. Gotta go!

Some perspective on Gutenberg

Today I had to do some work on a client’s site that I didn’t build but have ended up maintaining, which is built from an amalgam of multiple “page builder” plugins, but most prominently, WP Bakery.

I was just explaining to my wife (who is not a developer but who uses WordPress, both Classic Editor and Gutenberg/Block Editor, extensively) what it’s like to use WP Bakery:

“Imagine the most annoying aspects of Gutenberg that you find the most annoying*, then imagine something ten times clunkier, a hundred times uglier, and a thousand times less intuitive. That’s WP Bakery.”

—Me

*Yes I really did, deliberately, say it that redundantly.

Vindication!

I already mentioned this in an addendum to my last blog post, but it seems to warrant its own dedicated post.

I’m a self-employed, solo developer, not very actively engaged in the WordPress “community” even though my work is 95% WordPress. So I have apparently missed the memo that shortcodes were (prior to yesterday’s release of WordPress 6.2.1, anyway) the way people were injecting PHP into their HTML-based Block Theme templates. (Silly me… I was just misusing Block Patterns to the same effect.)

Well… as it turns out, allowing shortcodes in Block Theme templates apparently was a security issue, which the WordPress core team summarily “fixed” by just outright removing shortcode support in templates in this update.

This change did break a pair of sites for me (which are still just in final testing, not live, and which I need to go fix as soon as I finish writing this), but the problem was relatively minor. It sounds like a lot of people are using shortcodes extensively as a backdoor hack for adding PHP functionality to templates, and they are… um… not happy.

At what point does the Gutenberg team collectively take a step back and realize that maybe they’ve been the ones Doing It Wrong™ all this time? I feel like that reckoning is approaching.

A Gutenberg/Block Editor revelation… just stop trying

This is not as defeatist as it seems by the title. I’ve actually had a huge breakthrough in my ongoing battle journey with the WordPress Block Editor (a.k.a. Gutenberg).

My biggest problem throughout the process of trying to build a Block Theme has been finding myself hamstrung by the lack of PHP in a Block Theme’s all-HTML template structure. I’ve ended up brute forcing my way into having access to PHP with a combination of ACF Blocks and Block Patterns. But it should have been obvious to me that both approaches were wrong, because I found myself creating ACF Blocks that didn’t have any custom fields and Block Patterns that didn’t have inserters.

The fact that I was using both of these tools in ways that they are patently not intended to be used should have been my first clue, but the problem has always been that documentation of all of this new technology is so scarce, inconsistent, poorly organized and out-of-date by the time it’s written, that it’s hard to really know in advance how they work, and whether or not you’re using them properly. And as my recent series of blog posts have indicated, I am the proud king of Doing It Wrong™.

But as I said at the beginning, I’ve had a revelation, which is this:

The only reason to create a pure “Block Theme” is if you intend to use the new Site Editor (a.k.a. Full Site Editing).

I emphatically do not intend, now or ever, to use the Site Editor, because I have always coded themes from scratch, and the people I am building sites for do not want to modify the overall design themselves, nor should they be given access to the tools to do so.

I am completely locking down access to the Site Editor on the sites I build, so why should I design my themes to work with it? Well… until now, I kind of just thought that was The Way Forward. Maybe it is, but it’s a way that does not, at all, align with how I do business or what my clients want/expect from me.

Luckily, core WordPress team member Carolina Nymark has written an excellent introduction to using PHP templates in block themes. It’s as simple as this. Just… use the old PHP-style of templates. There are a few tricks to be aware of, most of which are addressed by Carolina’s article, but some more I discovered along the way.

I’ve spent the last year and a half of building my block theme constantly butting up against this frustrating limitation. Now after about 4 hours of work, I’ve managed to convert my nascent Block Theme to using PHP templates.

I’ve eliminated my custom field-less ACF Blocks.

I’ve eliminated my un-insertable Block Patterns.

Things are working like they should. Well, mostly. This is an ongoing process. But the key test of the change has been that everything that was working in the theme before is working now, and I have the full capabilities of PHP and the long history of PHP-based WordPress development back at my disposal for future work.

I’ll write more about this in the coming weeks as I refine my process, including an overview of my general setup for a Block-friendly but PHP-rich base theme.

Update: Well, it seems rather fortuitous that I chose this undertaking when I did, because it coincides perfectly with the release of WordPress 6.2.1 which breaks shortcodes in Block Theme templates (which is even more of a shitshow for some people than it is for me, since it hadn’t occurred to me that shortcodes could be used as a workaround to the absense of PHP in Block Theme templates), including a pair of sites I’m currently developing using this theme. Switching those sites to the new PHP-based version of my theme should fix this issue automatically.