Building a WordPress block theme is shortening my life expectancy

Throughout my (now quite long) career as a web developer, I have had many ups and downs. But I have never had as many stomach aches as I have in the last year, trying to wrap my brain around a steady stream of confusing, convoluted, counterintuitive and just downright inexplicable elements of building a theme from the ground up to work with Gutenberg, a.k.a. the WordPress Block Editor.

I’ve made some major progress over the course of the year, and my theme (in various stages of completion) is now powering multiple live client sites, with development ongoing for a few more. For the most part, now, I am finally at a stage where I feel like this is the right way to use WordPress going forward, rather than just reluctantly accepting that I have no choice in the matter.

But I still feel like Gutenberg does a lot of things the wrong way — most notably in its fundamental lack of separation between content and presentation. Yes, I am going to Old Man Yells At Cloud this. I know React is the new hotness and now everything needs to be done in ES6 (which I will forever call JavaScript), but the WordPress core team is throwing away some of the platform’s greatest strengths by abandoning this core component of how it (like pretty much any 2000s-era CMS) is built.

It may seem that I’m just an old curmudgeon who doesn’t want to learn React (I don’t), but it’s not just that. It’s that every aspect of this interface that has been designed to make it easier for average users to interact with — which, I think, it finally is, 5 years after it was unceremoniously forced on us — makes the process of developing for it harder, and more abstract.

There are two unrelated but connected problems with how things are going down here.

First, modern developers just love dependencies.

I get it. To an extent. Reusing tried-and-true code libraries instead of rolling your own all the time is smart. But that means you’re using code you probably haven’t looked at closely. You don’t really know how it works. It may have bugs, or it may have opaque features you don’t realize are there, or it may just have too much stuff bloating it, slowing down performance and making applications more brittle. Pile dozens of these dependencies together, and you’ve got a lumbering behemoth of code that no one in the world completely understands. And I truly do believe we are at a point where no one, at all, knows entirely how the current version of WordPress works. On top of that, any time you’ve got external dependencies, weird things can happen.

Second, Gutenberg is evolving so quickly that the documentation hasn’t kept up.

Gutenberg’s documentation is occasionally out-of-date, always incomplete, and it’s only getting worse.

I know writing documentation is tedious, and the web has never had good documentation. When I was in college in the mid-’90s and I wanted to learn HTML, I went to the campus computing department and asked them how I could go about learning HTML. They, seriously, just told me to download BBEdit. Which I did. And which didn’t help me learn HTML at all. (Although it is still the text editor I write all my code in, 29 years later.) So how did I learn HTML? View source. Because back then, you could do that.

I don’t expect to be able to just “view source” and learn how Gutenberg works. But since WordPress is open source software, and I have the files right here on my computer, I do think that when the documentation fails me, I should be able to poke around in the source code and find what I’m looking for.

Let’s get specific. As it happens, in my theme I’m addressing one of my earlier complaints above by using ACF Blocks. It’s been a rough road, but I’m starting to make really good progress. The only problem is, my styles aren’t getting applied. My CSS for the block isn’t loading in the Block Editor, and the Block Editor styles I’ve configured my block to support (colors, spacing, typography) via its block.json file are not showing up on the front end.

Well, what do I do about that?

Focusing on the front end first, I know that Gutenberg’s styles get applied courtesy of pithy CSS class names like .has-primary-background-color as well as HTML style attributes using CSS variables, like var(--wp--preset--spacing--80).

But if I look at the block attributes in the Block Editor’s comment tag, or the JSON or PHP array of style properties for the block, I see the same is formatted as such: var:preset|spacing|80

The quarter century of development experience in my old fart brain tells me that there must be a function or method, somewhere, that converts var:preset|spacing|80 into var(--wp--preset--spacing--80), and that I would be better off trying to find that function than writing my own.

Uhhh… OK. So how do I go about that?

ACF’s documentation for this feature is abysmal, which is kind of understandable, since the whole thing is a moving target that is changing rapidly (not to mention the organizational challenges that happen when the company that bought you out gets bought out itself), and the core WordPress documentation isn’t much better. So I’m left resorting to a scavenger hunt through the WordPress code. But it’s layer upon layer of 5-line functions referencing each other through a series of add_filter() callbacks.

As usual with my Gutenberg rants, I don’t have any solid conclusions to end on here. This whole post was mostly an exercise in working out that knot that was gnawing at my insides. At least I’ve done that. But I’m no closer to solving my problem. That’s probably because the real problem isn’t what I think it is. And it’s not going away.

All I know is, building a block theme — at least, for me, right now — takes way longer than building a classic theme. And I think that’s because my approach, one developer just cranking away, is not the model anyone in the core WordPress development community cares about, or possibly even comprehends existing. These days I’m not extremely confident about its continued viability myself.

Post script: I think I actually managed to find it, by using BBEdit’s multi-file search on this string: '|'

The method is: WP_Theme_JSON::get_property_value()

Of course, that doesn’t get called directly. It’s called in WP_Theme_JSON::compute_style_properties() which is in turn called by WP_Theme_JSON::get_block_classes() which itself is in turn called by WP_Theme_JSON::get_stylesheet() and then we’re getting too far afield, because that’s used to turn the theme.json file into inline CSS.

So I am guessing at this point that I probably should not use any of these methods. (Actually, I can’t because they’re all protected.) It really seems like this should be happening automatically, and either ACF Blocks are missing some key functionality, or I’m missing something about how ACF Blocks work (which I would blame on the lack of documentation).

Update (April 11, 2023): After I wrote this blog post, I also started a thread on the ACF forum, and there I was finally given an answer. Yes, there is a WordPress function for getting block wrapper attributes. It is even, um, named exactly what it should be. But as the fellow ACF user who responded with that enlightening bit of information even noted, it is incredibly difficult to find. The WordPress documentation does, to its credit, include most if not all (I mean, how would I actually know?) functions and methods, but the search tool is a joke.