Making Bootstrap work with the WordPress Block Editor

tl;dr: You need to load Bootstrap’s CSS in the 'wp_enqueue_scripts' hook with a priority lower than 10.

Where do I begin with this one? First, some foundational details: I’m old school. I’ve been a professional web developer/designer since 1996. I’ve embraced new technologies as they come along, but I tend to bristle at things that are either a) not an open standard or b) need to be compiled.

I refused to use Flash. In the end I was proved right, as open web technologies supplanted it. Flash is dead, and the open web is not. I still refuse to use CSS preprocessors for a similar reason. They’re a non-standard workaround to limitations in the current standard. They fragment the landscape instead of pushing the standard forward. And as CSS variables have gained wide browser support, preprocessors are beginning to look as pointless as Flash.

Now the thing I hate is npm — or any similar tech that requires me to run shell scripts and compile anything. I’ve long since embraced server-side scripting, using open source libraries like jQuery, and even using a pre-built CMS (or CMS-ish system) like WordPress. (Yes, for many years I rolled my own CMSes.) The bottom line for me is, if it’s code I can download simply and treat as a “black box,” fine. But if it’s something I need to get my hands dirty in, I shouldn’t need anything to work with it but a text editor.

All of that to say, I am having a bit of a time with where things are going these days with Gutenberg, a.k.a. the WordPress Block Editor. And I haven’t exactly been quiet about it here.

This week I needed to extend the Block Editor by creating a carousel/slideshow block. Yep, I’ve rolled my own with these for many years as well, but this time around I decided I wanted to work with something pre-built, so I settled on the one in Bootstrap. I don’t really need all of Bootstrap (although I suspect over time I will need more of it), but customizing it requires using npm, so I decided to go ahead and include the entire pre-compiled package in my theme.

That’s when the problems began.

Oh, the carousel works great! But I spent a bunch of time yesterday trying to figure out why the custom background color and fonts defined in my theme.json file were being ignored… especially since they’re right there in the inline CSS inside the <head> of every page.

Don’t even get me started on inline CSS, or the way so many people in the industry seem to worship PageSpeed Insights. Once again we’re skating to where the puck is, instead of where it’s going, and to stretch the analogy to the limit, we’re melting all of the ice in front of it too. This is not the way to move web development forward intelligently.

Ah-hem.

Eventually I worked out what’s happening. WordPress, historically, was designed to allow you to define dependencies, so you could load CSS and JavaScript in a logical manner. Gutenberg/Block Editor throws all of this out the window with this inline CSS. Certain “critical” inline CSS for the Block Editor gets loaded immediately regardless of the dependencies you put into wp_enqueue_style(). The result being, styles defined (indirectly, in a way more convoluted way than vanilla CSS) in my theme.json file were appearing before the Bootstrap CSS file was loaded. And since I’m using the compiled Bootstrap instead of a custom npm build, there’s a bunch of “general” CSS it’s throwing in, including color and font definitions on the <body> tag that override Gutenberg’s earlier inline CSS.

Fortunately, someone else had the same problem and figured out a solution. But since, in 2022, spammers overrun any forum thread that’s left open too long, the thread was already locked and I couldn’t express my appreciation to the poster who shared it. So I’m writing this blog post instead.

The trick is to load any third-party CSS that you might need to override using a separate function called on the 'wp_enqueue_scripts' hook, with a low priority number (less than 10, since that’s the magic default).

Here’s a generalized version of the code I’m using:

function my_enqueue_scripts_early() {

    $ver = '1.0.0'; // Your theme version; could also be a class property, constant, global variable, etc.

    wp_enqueue_style('bootstrap-style', get_theme_file_uri('vendors/bootstrap/bootstrap.min.css'), array(), $ver);
    wp_enqueue_script('bootstrap', get_theme_file_uri('vendors/bootstrap/bootstrap.bundle.min.js'), array('jquery'), $ver);

}
add_action('wp_enqueue_scripts', 'my_enqueue_scripts_early', 8);

Apple vs. Adobe: This is fargin’ war!

I’m sure I’m not the only child of the ’80s who watched Johnny Dangerously several (hundred) times as a kid. One of my favorite characters was Roman Moronie, whose command of the English language — well, more specifically, English profanities — was tenuous at best. I’m sure he would be highly offensive to a particular nationality or ethnic group, if it were possible to tell where he was actually from. (That mystery itself being a joke in the movie; at one point a newspaper headline reads: “Roman Moronie deported to Sweden — claims he’s not from there.”) Yes, I was a big fan of ’80s Michael Keaton movies that, in retrospect, are somewhat problematic. Johnny Dangerously, Mr. Mom. I think I partly liked him because I thought maybe he was related to the characters on Family Ties. OK, I was old enough to know better than that.

What does this have to do with Apple vs. Adobe, or anything for that matter? I’m not sure, but I do know that their battle has escalated to fargin’ war!

Steve Jobs fired the first metaphorical salvo last month with his Thoughts on Flash. I thought he nailed it, as expected. Of course Adobe can’t let him win, so yesterday Adobe retaliated with their “We [heart] Apple” / “We [heart] Choice” ad campaign and an open letter of their own.

The idea that Flash is somehow open — or that Apple is somehow trying to “close” the web — is both disingenuous and misguided. My natural inclination is to blather on ad nauseum about such things, but as I’m home with a sick kid today (which is to say, there’s enough nauseum in this house already), I’ll let some more pithy writers say it for me.

First, an excellent and concise response from Jim Whimpey in Brisbane, Australia (by way of John Gruber in Philadelphia):

Adobe: not open, claim to be.
Apple: not open, don’t claim to be, contribute heavily to that which is truly open.

If that’s not pithy enough for you, a picture is worth a thousand words. Via Jeffrey Zeldman in NYC:

Update: Over on the Macworld website, the Macalope has some choice words on this topic. It’s worth reading in its entirety, but here’s my favorite bit, dissecting excerpts from the Adobe open letter:

If the web fragments into closed systems, if companies put content and applications behind walls…

You mean like the wall of a lousy runtime environment that would just as soon crash the Macalope’s browser as play back a Daily Show clip? The wall of a development environment controlled by one company that makes some pretty good coin off the deal?

Oh, no. That’s not the wall you were talking about. Sorry. Go on.

…some indeed may thrive — but their success will come at the expense of the very creativity and innovation that has made the Internet a revolutionary force.

The Internet is an open range where anyone can compete in any way they like. But Adobe didn’t make the Internet. In fact, they tried to wall off a section of it. Apple, on the other hand, made its own walled garden with a scenic view of the Internet.