WordPress Blocks, Portable Patterns and Pain Points
At 4/19/2024
I like WordPress. I’ve used it for dozens of projects in the past 15 years, and WordCamp was one of my first speaking gigs. I wrote this article in WordPress.
I also like designing and building portable patterns. It’s fun to craft versatile little bundles of HTML, CSS and JavaScript that work in different projects and environments.
But getting portable patterns working in WordPress’s block editor? Unexpectedly challenging!
Let’s review our options…
Block themes support template parts and block patterns, and the block editor lets you define reusable blocks. These seem simple to set up, but they’re mainly intended for combinations of existing blocks, and they don’t allow authors to edit their contents in individual posts and pages without severing their connection to the original (which sort of defeats the purpose).
What we probably need is a new block, one for each pattern we think content authors will benefit from. The tutorial for creating a new block spans seven chapters: It involves creating a plugin, setting up a React environment, and defining a series of functions for display, editing and saving logic. The amount of code necessary will quickly dwarf the HTML, CSS and JavaScript of most front-end patterns.
So maybe we don’t need a whole new block, maybe we can update an existing block to match our pattern. Unfortunately, the process of filtering existing blocks is almost as complicated as creating a new one. Plus, we’d have to worry about core updates breaking our modifications.
Well, okay, maybe we don’t need perfect parity between our patterns and the existing blocks. Can we at least get the markup to match? Sort of: You can filter a block’s output using PHP, but those changes will only apply to the front-end, not the block editor. And since most of a block’s content and options are stored as annotated HTML strings, you’ll probably need to parse its structure using PHP or rely on some really advanced regular expressions for any significant changes.
All right, if consistent markup is that complex, let’s focus on consistent styles. Maybe something like design tokens or Sass mixins can help us apply key styles from each pattern to its corresponding WordPress block, then we can enqueue the result.
Except none of those styles will show up in the editor: That requires a separate function. Or we could add the styles to our theme.json
and they’ll show up in both places, but then we’d have to copy and paste to a single-line string or write a custom build process for generating that file.
Once finished, you may still notice conflicting or broken styles. Sometimes there are styles related to the theme or site settings injected inline that are hard to nail down. There may be many combinations of alignment, typography, color and stylistic variations to account for. Do we update our styles to support all that? De-register everything and start from scratch?
Should we just go back to shortcodes instead?
Going Against the Grain
I definitely get the sense that WordPress wants me to work in the opposite direction:
- We can create a new block theme with only a stylesheet and a configuration file.
- That configuration file may also include our typographic styles, color palette, layout sizes and more.
- We can construct our page templates visually in the Site Editor, exporting the theme files when we’re satisfied. (We can divide those templates into template parts and block patterns if we want to keep them DRY.)
- When we need more functionality, we create new blocks, including their markup, styles and behavior.
- If we want to use these blocks in other environments, we can leverage WordPress’s open source libraries to parse and manipulate blocks using JavaScript. (At least in theory… I couldn’t find many examples of this in the wild.)
For projects that start with WordPress and consider pattern portability a “nice to have,” this workflow makes sense: It’s now possible to design an entire experience in WordPress itself, which is truly impressive. But if you already have a library of web-based patterns or you want to avoid platform lock-in, and assuming you aren’t interested in becoming a full-time bespoke plugin author, the path isn’t clear.
A Partial Third-Party Workaround
The Advanced Custom Fields (ACF) plugin can streamline certain aspects of block creation for existing patterns:
- You can compose the block’s editable fields with the plugin’s visual interface, which is more approachable and faster than importing and composing a JSX template.
- You can register fields via PHP (either from scratch or exported from the interface). This opens the door to storing configuration data alongside other pattern assets like templates and styles.
- The field data you retrieve won’t be embedded in HTML strings. You’re free to compose the markup however you want, pass the data to an existing template, request a response from a hydration service, etc.
The experience isn’t perfect. ACF’s fields aren’t always visually consistent with the rest of the block editor, there can be a small delay when updating server-rendered blocks in the editor, and more ambitious blocks may be tough to pull off within its constraints. It also doesn’t streamline any of the style-related complexities mentioned earlier.
A Wish List
I really wish WordPress had a lighter way of defining custom blocks. Controls could be defined in block.json
(similar to Storybook), or maybe even declared in a template (similar to Perch)?
I also think it’s critical that WordPress adds cascade layers to its default block styles, at least as a feature to opt into. Right now, the only surefire way to prevent style conflicts is to remove block styles, which seems unnecessarily destructive.
But more than anything, I’d love to see an official guide from WordPress on this subject. Pick a public design system (maybe USWDS or GOV.UK?) and show how a theme developer should expose dozens of existing HTML, CSS and/or JavaScript patterns to the block editor.