The Untapped Potential of the Drupal 8 Core Block Content Entity

As Drupal Developers, we know that blocks are a great way to display content. From eye catching calls to action to custom, editor curated content, Drupal developers can use blocks for a wide variety of use cases. Less understood is the potential value of the block’s corresponding entity type, known simply as Block Content.

Block Content types are customizable, fieldable content entities that are part of Drupal 8 core. Instances of Block Content can be placed throughout the site using the block’s configuration, or via the popular Context module. Although Drupal makes it easy to place Block Content throughout a site, trying to leverage them in more sophisticated ways quickly becomes challenging.

Through my work at U.Group, I contributed to Block Content Template, a new module that allows developers to unlock the hidden potential of the Block Content entity. Read on to learn more about my experience contributing to the module, and how you can use it to make the block system more flexible for your own sites.

The Challenge with Drupal Block Content

Since blocks are content entities, they can be used in views, referenced in fields, and embedded into a WYSIWYG text editor, just like other content entities. The problem is that Block Content does not provide its own template, so when they are referenced in these ways, they lack the basic wrapping markup that front-end developers rely on to style the content.

As a result, developers avoid using Block Content in these ways, turning instead to contributed modules such as Paragraphs or ECK. While these modules are certainly powerful, their use can contribute to the overhead and technical debt of a site. If Block Content provided a template, we could solve many of the same problems with a solution native to Drupal core.

Our Solution: The Block Content Template Module

While researching this topic, I came across the Block Content Template module. The module had only been added to Drupal.org a few weeks prior and reported having less than 10 sites using it, but the description made clear that it was intended to address the very same problems I was trying to solve.

The module as I discovered it had already taken care of most of my work for me. Specifically, it provided a block-content.html.twig template file. The one thing that it was missing was standard classes and markup in the template. The solution put forth in the source code looked promising, so I decided I’d be better off contributing to this project rather than creating my own module from scratch.

After a few hours of development and testing, I was able to iterate on the module’s template_preprocess function and ultimately surface the block’s id, bundle name, and view mode as classes in the template. After that, I submitted the changes as a patch on the module. I was thrilled when the module’s maintainer rolled my changes into a major release just a few hours later!

The Module Explained

To give you a closer look at how the module works, let’s take a look at the twig template, then see how enabling the module changes the markup:

{#
/**
 * @file
 * Default theme implementation to display a block content.
 *
 * @see template_preprocess_block_content_template()
 *
 * @ingroup themeable
 */
#}
{%
  set classes = [
    'block-content',
    'block-content--type-' ~ bundle|clean_class,
    'block-content--' ~ id,
    'block-content--view-mode-' ~ view_mode|clean_class
  ]
%}
<div{{ attributes.addClass(classes) }}>
  {{ title_prefix }}
  {{ title_suffix }}
  <div class="block-content__content">
    {{ content }}
  </div>
</div>

In the following example, I’ve created a View that displays the default bundle basic block. Here’s the markup without the Block Content Template module enabled:

<div class="view-content">
    <div class="views-row">
        <div class="field field--name-field-media field--type-entity-reference field--label-hidden">
            <div class="field__items">
                <div class="field__item">
                    <img src="/path/to/image.jpg" alt="image description" typeof="foaf:Image" />
                </div>
            </div>
        </div>
    </div>
</div>

Here’s the markup with the module enabled:

<div class="view-content">
    <div class="views-row">
        <div class="contextual-region block-content block-content--type-basic block-content--9 block-content--view-mode-default">
            <div data-contextual-id="block_content:block_content=9:changed=1591843824&amp;langcode=en" data-contextual-token="YloFh6OXxJRFd0N7WFbLdpW_IvbaTfZEcmX6tE7UNFE"></div>
            <div class="block-content__content">
                <div class="field field--name-field-media field--type-entity-reference field--label-hidden">
                    <div class="field__items">
                        <div class="field__item">
                            <img src="/path/to/image.jpg" alt="image description" typeof="foaf:Image" />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

With the module enabled, you’ll see the addition of the following wrapper div:

<div class="contextual-region block-content block-content--type-basic block-content--9 block-content--view-mode-default">

This markup greatly improves the front-end developer’s ability to effectively target the block for styling. While this example demonstrates the module’s effect on Block Content entities in a view, you can also use it to achieve the same results when they are rendered in a reference field or embedded into a WYSIWYG. This is a massive improvement over the out-of-the-box experience, with the potential to radically change the way that developers imagine and implement their data model.

The Future of Block Content

Since the Experience Team started using this module on our projects, we have been able to reimagine how we can use Block Content entities during our development process. We think this module has a bright future in the Drupal community—possibly even a future core candidate.

Try it out on your next project and let us know what you think via Twitter or LinkedIn!

Get alerted to new job postings, events, and insights by registering for our monthly newsletter.