The blog you’re reading right now is running on a new WordPress based offering. It’s called “Wrigley,” and it’s beautiful. Even better, it’s strong—it’s resistant to much of the accidental breakage that occurs in all web projects. That’s because in building Wrigley, we introduced two technologies to the LexBlog tech stack:
- The WordPress block editor, AKA Gutenberg.
- Tailwind, for managing CSS.
While they’re both wildly popular, it’s actually quite rare to use them together. There are some unique challenges, and most projects would not surface the advantages of doing so. I’m so happy we did.
What We Normally Do
A long-standing best-practice in CSS is to strive for what’s called semantic class names. Here’s “good” and “bad” in that school of thought:
- Good: A class like .header-blog_title would carry the CSS for making the blog title, in the header, large and bold. The design might change at some point, but the class name will never need to change, because it’s semantic: It always applies to the blog title that is in the header. Nice.
- Bad: Classes like .text-lg and .font-bold would be frowned upon as non-semantic. If the design were to change, you’d have to chase down all the relevant classes in your markup in order to match the new design. Boo.
This concept is absolutely central to many of the foundational texts for our craft. Zeldman’s Designing with Web Standards is a classic example. The CSS Zen Garden illustrates the idea beautifully. But guess what? We’re not doing any of it in Wrigley.
What Wrigley Does
Wrigley makes use of a new school of thought that flies directly in the face of the semantic class name approach: Utility-first CSS. The first notable framework to do this was Bootstrap, the original front end for Twitter. Bootstrap is excellent, but Tailwind, which Wrigley uses, takes the most important parts of Bootstrap to the extreme, and omits the rest. The result is something completely disruptive and provocative, and I mean that in a good way. In Utility-first CSS:
- Good: Classes like .text-lg and .font-bold are helpful in order to immediately understand what the page will look like, merely by reading (or writing!) the markup.
- Bad: A class like .header-blog_title is vulnerable to collateral damage if you intend to apply a change to the home page, not remembering that this perhaps affects the layout differently on interior pages.
This is an uncomfortable change in perspective for those who are accustomed to semantic class names. Smart people are using profanity in public forums to express their disdain for it. You have to respect the passion. But what I respect more, is the well-stated perspective of Tailwind’s founder, Adam Wathan:
I’ve written a few thousand words on why traditional “semantic class names” are the reason CSS is hard to maintain, but the truth is you’re never going to believe me until you actually try it. If you can suppress the urge to retch long enough to give it a chance, I really think you’ll wonder how you ever worked with CSS any other way.
Adam Wathan, founder of Tailwind CSS
I couldn’t have said it any better myself.
The Challenge
So what’s so hard about using utility-first CSS? In sites that are entirely template-driven, nothing. You just type the utility classes when making your template files. In sites that are mostly content-driven, lots. You’re not the one typing your content, your users (bloggers) are. LexBlog sites are almost entirely content-driven, with very little markup in the template files.
Take the simple example of bottom whitespace after a paragraph in a post. Under traditional semantic class names, we’d simply have a rule in our stylesheet like, p { margin-bottom: 20px; }. But with utility-first CSS, we need to hit every paragraph tag in the post content with .mb-5. Obviously we don’t expect our bloggers to add .mb-5 to each paragraph in order to put a margin-bottom under them, so what do we do?
The Solution
The solution actually is WordPress’s block editor, Gutenberg. It hands us the post content not in one long string of text, but as an array of “blocks”. A paragraph is a block. A list is a block. So is an image. A social media embed. A blockquote. Lots more. And while the developer experience is still fairly rough, it gives us a way to hook into each block, and morph it in various ways. For example, here’s me adding margin-bottom to paragraph blocks:
This function hooks into each paragraph block, and hits it with a css class of .mb-5, using php’s DomDoc.
Paragraph margins are a simple example but don’t be fooled, this approach can be used for any module, no matter how complex. Here’s how a blockquote gets built:
That’s the code that makes quotes look like this:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
The Advantages
So what’s the point of all this? It’s not faster to write. It’s not better for readers. It’s not simpler. It’s just trading one form of complexity for another. But that’s the rub! It’s about choosing which kind of complexity you want to live with, and the choice is obvious:
CSS has some unique qualities that make it more annoying to deal with than any other web language. The best example is the “append-only CSS” problem. This is a crippling issue that can make projects completely unmaintainable. But with utility-first CSS, we never even have to write CSS, let alone append any.
What’s Next
We have not yet applied much effort to making the block editor resemble the front end, and many premium themes do this. We’ll get some feedback from our writers and likely work to bridge the gap between how the post appears when writing, as opposed to when reading.
Wrigley can pull even more value out of the block editor if we start supporting more blocks. For example, there’s a lot we could do with the audio block to provide value for podcasts. Our long-form bloggers could make interesting use of the cover block. The gallery block would be helpful for posts that use a lot of images.
Finally, a cool side-effect of learning the heck out of the block editor, is that we’re in much better shape to use it elsewhere. We’ll be looking to improve our support for it in Apple Fritter, the options-driven theme framework that powers most of our sites.