How—and why—to pimp your CMS with modular content blocks

How—and why—to pimp your CMS with modular content blocks
Image by Tiffany Terry

Most website CMSs handle typical article pages or “general purpose” pages the same way: They provide one big input field for the whole content section of the page. Usually this input field is enhanced with a WYSIWYG editor, which in turn needs plugins and supporting tools like WordPress shortcodes to handle more than just text. Read about the pros and cons of this common solution and learn about an alternative that increases convenience and flexibility by breaking up your content into modular blocks.

What’s so bad about WYSIWYG editors?

Well, basically nothing. WYSIWYG editors like TinyMCE or CKEditor make formatting text a comfortable experience. But what if you want to spice up your big chunk of text with additional elements?

Let’s say you want to embed a YouTube video, add a little image gallery, have a multi-page highlight box with a tab navigation and insert an image way down near the end of your article. (I’ll explain the reason for the “way down“ later.) For all of the mentioned examples—and many more—there are solutions enabling you to stuff even complex pieces of content into the WYSIWYG editor field. Some of these solutions are provided as plugins for the WYSIWYG editor. Others are implemented on the CMS level, pre- or post-processing the field before its content is shown to website visitors.

One of the nice aspects of this approach is the fact that you don’t have to change any code in your templates. You still need just one placeholder to output the complete main content of a page—pre-rendered and including all the required code to display the extras mentioned above. And of course many WordPress themes work—and work together with various plugins extending TinyMCE’s capability—only because they can rely on this default structure.

// WordPress: Display the post content 
<?php the_content(); ?>

// Drupal: Display the node content
// (Hope I got this right since I haven’t used Drupal for years.)
<?php print render($content); ?>

// ProcessWire: Display the field “body”
// which is a textarea field with a CKEditor in this example
<?php echo $page->body; ?>
Examples of how to display a big “main content of the page” field in various CMSs

So everything is in apple-pie order, isn’t it? Yes and no. It depends on your requirements. If you don’t demand specific standards of the delivered code, you will probably be happy with it. But if you want more control over the code, it may become challenging.

Two examples to illustrate the challenge

Let’s continue with two of the examples mentioned above: the embedded YouTube video and the image.

Example 1

The easiest way to embed a YouTube video is using oEmbed. In some CMSs, e. g. in WordPress, this feature is already included by default. Others need a plugin. With oEmbed you can just place the URL of the video’s detail page somewhere in your text and it will be replaced by an embedded video player when a user visits the page. Sounds very easy to use and is actually very easy to use.

One downside of this almost magical replacement is that it’s not exactly WYSIWYG in the editor field anymore. WordPress for example requires the video URL to be on its own line and to be not hyperlinked. So you have to know this when you edit your article. In the editor field itself nothing indicates that this URL is more than just a plain URL, but instead a placeholder for a full-featured video player.

The other downside is that you don’t have any control over the details of the video embed code. What if you want the embeded video to be responsive (using the “maintain aspect ratio” CSS trick like Embed Responsively does it for example), but the code created by the oEmbed implementation doesn’t output the required container elements and classes/styles? What if the laws of your country require you to use YouTube’s “privacy enhanced mode”—which means that the video is served from the domain youtube-nocookie.com instead of youtube.com? What if you want to include additional structured data to provide search engines with detailed information about the video?

You could implement some of these changes and extensions in your templates by using something like PHP’s str_replace function to change parts of the pre-rendered HTML code. Call me overcautious, but I’m always a bit sceptical when having to do a bunch of such replacements in a row, applying them to a large piece of pre-rendered code. Remember: Using a function like str_replace for this purpose means fixing things afterwards instead of creating clean code right away. While this might work in this example, it will be a bit tougher in the next one.

Example 2

You remember the image “way down near the end of the article”? Let’s assume that you want …

  • a responsive image using a picture element, to have fine granular control over its source elements and to provide different image files according to the pixel density of the screen,
     
  • your CMS to create all the required resized images—depending on the chosen layout option (let’s say “full-width”, “half-width floating left” and “half width floating right”) and the pre-configured max. sizes for image width and image height—no matter how small or big the uploaded image is or what aspect ratio it has, while making sure that neither an upscaled version of the image is created nor the image is upscaled via CSS,
     
  • the image to be lazy loading using JavaScript because—being placed “way down near the end of the article”—it will probably not be in sight when the user starts reading the page, especially not on a mobile device,
     
  • a noscript alternative, so that website visitors who turned-off JavaScript can still see the image (although it is not lazy loading in this case),
     
  • a placeholder rectangle of the exact size of the image (and responding to the surrounding container or viewport width just the same way as the image itself does) to prevent jumping content—in case the page area with the lazy loading image comes in sight before the image is loaded,
     
  • to serve the image file(s) from a cookieless subdomain to increase performance a little bit,
     
  • an image caption to be displayed underneath the image.

So when uploading an image with a width of 1200 pixels and a height of 772 pixels, you don’t want to get this output:

<p><img src="/path/to/myimage.jpg" alt="Allons-y!"
        width="1200" height="772"></p>
<p class="caption">This is an image caption.</p>

Instead you want your CMS to create something like this, assuming that you use respimage and lazysizes:

<head>

    [...]

    <style>
        @media only screen and (max-width: 360px) {
            .myimage-jpg {
                width: 19.375rem;
            }
        }
        @media only screen and (max-width: 977px) {
            .myimage-jpg {
                width: 35.875rem;
            }
        }
        @media only screen and (max-width: 1092px) {
            .myimage-jpg {
                width: 54.6875rem;
            }
        }
        @media only screen and (min-width: 1093px) {
            .myimage-jpg {
                width: 54.6875rem;
            }
        }
        @media only screen and (min-width: 1669px) {
            .myimage-jpg {
                width: 1200px;
            }
        }
    </style>

    [...]

</head>

<body>

    [...]

    <figure class="image image--full-width myimage-jpg">
        <picture class="image__picture image__picture--js myimage-jpg"
                 style="padding-bottom: 64.333333333333%">
            <source media="(max-width: 360px)"
                    srcset="https://static.mycoolwebsite.com/path/to/myimage.310px-width.jpg 1x, https://static.mycoolwebsite.com/path/to/myimage.620px-width.jpg 2x, https://static.mycoolwebsite.com/path/to/myimage.930px-width.jpg 3x">
            <source media="(max-width: 977px)"
                    srcset="https://static.mycoolwebsite.com/path/to/myimage.574px-width.jpg 1x, https://static.mycoolwebsite.com/path/to/myimage.1148px-width.jpg 2x, https://static.mycoolwebsite.com/path/to/myimage.jpg 2.0905923344948x">
            <source media="(max-width: 1092px)"
                    srcset="https://static.mycoolwebsite.com/path/to/myimage.875px-width.jpg 1x, https://static.mycoolwebsite.com/path/to/myimage.jpg 1.3714285714286x">
            <source media="(min-width: 1093px)"
                    srcset="https://static.mycoolwebsite.com/path/to/myimage.jpg 1x">
            <img alt="Allons-y!"
                 class="image__img myimage-jpg lazyload">
        </picture>
        <noscript>
            <picture class="image__picture image__picture--no-js myimage-jpg"
                     style="padding-bottom: 64.333333333333%">
                <source media="(max-width: 360px)"
                        srcset="https://static.mycoolwebsite.com/path/to/myimage.310px-width.jpg 1x, https://static.mycoolwebsite.com/path/to/myimage.620px-width.jpg 2x, https://static.mycoolwebsite.com/path/to/myimage.930px-width.jpg 3x">
                <source media="(max-width: 977px)"
                        srcset="https://static.mycoolwebsite.com/path/to/myimage.574px-width.jpg 1x, https://static.mycoolwebsite.com/path/to/myimage.1148px-width.jpg 2x, https://static.mycoolwebsite.com/path/to/myimage.jpg 2.0905923344948x">
                <source media="(max-width: 1092px)"
                        srcset="https://static.mycoolwebsite.com/path/to/myimage.875px-width.jpg 1x, https://static.mycoolwebsite.com/path/to/myimage.jpg 1.3714285714286x">
                <source media="(min-width: 1093px)"
                        srcset="https://static.mycoolwebsite.com/path/to/myimage.jpg 1x">
                <img src="https://static.mycoolwebsite.com/path/to/myimage.310px-width.jpg"
                     alt="Allons-y!" 
                     class="image__img myimage-jpg">
            </picture>
        </noscript>
        <figcaption class="image__caption">This is an image caption.</figcaption>
    </figure>

    [...]

</body>

Pretty unrealistic? Nope! That’s exactly how most images on this website are displayed. I’m going to explain the details of the code example in a separate article. But if you are interested, just open your browser’s developer tools and inspect the HTML and CSS code of the following image. (It’s not identical with the example code above.)

Red electric guitar
Originally uploaded image is linked.  (Image by moerschy)

OK, not every web designer is so crazily obsessed with the details of image display code like I am. But even if you want only half of the features listed above it’s not a trivial task. I don’t know if there is a plugin for one of the common CMS WYSIWYG editors that can do all of these things. But I rather doubt it.

Creating your own solution using something like WordPress shortcodes or Hanna code should be possible. But then you don’t have any visual representation of the image in the article view of your CMS backend.

There is one more aspect: The above code only covers the default HTML output. If you want to have an AMP version of the page, you have to output the amp-img component instead of all the picture and source stuff from above. You also need to use AMP-specific elements for embedded videos, accordions, lightboxes, etc. None of your usual jQuery plugins will work on an AMP page. So there is even more the editor plugin or CMS-side field post-processor has to cover.

Long story short: If you want full flexibility and complete control over your code, there must be a better way than pre- or post-processing a big WYSIWYG editor enhanced input field.

And there is. It’s neither new nor extraordinary. Quite a lot of clever developers already put some thought into this concept and created solutions for various CMSs.

The basic idea of modular content blocks

Some of the different content block types in the CMS backend of this website.
Some of the different content block types in the CMS backend of this website.

The concept is pretty simple:

  1. You build the content of a page using different types of field groups, known as “content blocks”.
     
  2. Each of these content block types represents a section of your content which should receive special treatment, i. e. it requires its own set of input fields in the CMS backend and its own sub-template for the frontend output.
     
  3. Create content block types for all major types of content sections you typically use. Some examples: images (if you want a more complex output than just a simple img element), embedded videos, code examples (using a code highlighter), “Tweet this” boxes (so you don’t need an external service), accordions, tabs, image galleries or plain HTML input (e. g. for embed codes of platforms you don’t use often enough to justify setting up their own content block type).

How to get content blocks going in your favorite CMS

The theoretical concept presented above sounds pretty simple. But how can you implement content blocks in the CMS of your choice?

Fortunately most of the common CMSs out there either provide content block building tools by default or can be extended by appropriate plugins. Of course I cannot provide a list with solutions for every CMS out there. But I can share my experiences with some of the CMSs I currently use or used in the past.

TYPO3

If you have ever used the TYPO3 CMS, you are already familiar with the concept of creating a page out of content blocks anyway. It’s the built-in default for basic pages. So you don’t need any additional extensions.

Unfortunately the content blocks concept is not impemented in the widely used tt_news extension which is the ypical solution to manage blog or news articles in TYPO3. But perhaps there is a way to replace the big article body field with another field allows adding different types of blocks. Since TYPO3 is not exactly my favorite CMS, I haven’t digged deeper yet.

WordPress

As a WordPress user, you might have already come across the Advanced Custom Fields (ACF) plugin. If not, I highly recommend checking it out. It is an extremely powerful extension that lets you break up the rigid structur of WordPress’ default post types without coding. Or you can use ACF to make creating all the fields for your custom post types as easy as pie.

Regarding modular content blocks, have a look at ACF’s Flexible Content field type. This is all you need to pimp your WordPress site with modular content blocks.

MODX

I haven’t monitored the development of MODX after I stopped using the CMS in 2012. But there is a commercial add-on that promises to deliver a very polished and comprehensive implementation of the content blocks idea. Appropriately enough it is called ContentBlocks.

ProcessWire

For my favorite open source CMS ProcessWire there is a commercial add-on module called ProFields. Among other useful field types this module introduces the Repeater Matrix field type. The description says: Repeater Matrix fields enable flexible content types and open the door to all kinds of great content management possibilities. This module offers everything you need to implement modular content blocks.

At this point I’d like to mention that the first time I saw a neat content blocks implementation on a ProcessWire powered website was a setup created by Christoph Lieck and Christoph Thelen. My technical briefing suggested either CKEditor plugins or the Repeater Matrix field type to implement content blocks. Christoph Lieck then convinced me that the Repeater Matix made much more sense in terms of flexibility and maintainability.

If you are a ProcessWire user and have not yet checked out ProFields, I recommend doing so. I’m also going to cover the Repeater Matrix setup (all fields, templates and a slightly tweaked implementation) of this website in a little article series over the next weeks. So stay tuned and subscribe to the blog.

Update: Thomas Aull brought a second free implementation alternative to my attention. So I updated this article accordingly. New parts are highlighted.

If you spare the expenses for the commercial ProFields module, there is aare twofree alternatives: ProcessWire’s built-in field types Repeater and PageTable.

Option 1: Using ProcessWire’s built-in Repeater field type

Well,The Repeater field type is only kind of an alternative, though. I tested it out of interest—and it works, but only if you get by with a very small number of content block types and if you use not more than two or three fields per content block type. The idea is to use ProessWire’s built-in Repeater field type. In contrast to Repeater Matrix, a simple Repeater field enables you to create a group of fields and make it repeatable in any quantity on your page—but without the option to have different groups of fields (= content block types) to choose from. So every content block includes the same set of fields. You can apply a workaround which enables you to have something that looks almost like the different content block types you get when you use Repeater Matrix. But this workaround comes with a serious caveat: a negative impact on performance. I’m going to include a more detailed description in the article series I mentioned above. So again, stay tuned.

Option 2: Using ProcessWire’s built-in PageTable field type

The second alternative is a true alternative. But it might involve a little bit more work if you want a good looking backend interface. Thomas Aull brought this to my attention. You can use ProcessWire’s built-in PageTable field type. It allows you to add content blocks with different templates and sort them via drag and drop. However, I don’t like how the blocks are displayed in the ProcessWire backend: It’s a table—like the name implies. Each row represents one content block and has an edit button which opens the edit mode of that block in a modal popup. But there is a solution to prettify how PageTable content blocks are displayed in the CMS backend. The additional module PageTableExtended allows you to use your own layout as output for a table row. This way you can mimic each content block’s frontend layout to a certain extend. To be honest, this is a visual representation which is much closer to the frontend layout than the Repeater Matrix version of content blocks can ever be—which might be usability enhancement for some website editors. But it comes with the cost of additional work to create the table row backend layouts which mimic the content blocks’ frontend layouts.

Do you use something like content blocks on your website(s)? Or do you think this concept does not make sense for you or your clients? Do you know a convenient solution for one of the CMSs not mentioned here? Then tell me using the social media channels linked below. I’m curious about your opinions and experiences.