How to make a title block with a custom background
Tags: drupal
Published: 2018-03-19 15:56:03

---
title: How to make a title block with a custom background
published: true
tags: Drupal
canonical_url: https://arturolinar.es/blog/post/title-block-with-custom-background
---

# How to make a title block with a custom background
A common request I’ve received lately when building sites in Drupal is to make the background of the page title configurable to allow the user upload and change it.


![](https://d2mxuefqeaa7sj.cloudfront.net/s_58B000CCEE244A0B10193C36972405EDDB99EDFC2E3CC8B2EF3D6B543327D95C_1520443205424_image.png)


Of course, this could be solved with a new block type with two fields, one for the image and one for the title. But then we would need to add the block for each page where we want to show the title.

How does Drupal handle page titles? Looking in the block admin page, I found that actually it is a block. Well, we need the same functionality of that block in our new one.

So looking for the class that contains the block machine name *page_title_block* I found `Drupal\Core\Block\Plugin\Block\PageTitleBlock` which implements `TitleBlockPluginInterface`. This is all the interface:

```php

    interface TitleBlockPluginInterface extends BlockPluginInterface {

      /**
       * Sets the title.
       *
       * @param string|array $title
       *   The page title: either a string for plain titles or a render array for
       *   formatted titles.
       */
      public function setTitle($title);

    }

```

Searching what uses that interface, I found that `BlockPageVariant` uses it to assign it a title:

```php
    foreach ($this->blockRepository->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) {
          /** @var $blocks \Drupal\block\BlockInterface[] */
          foreach ($blocks as $key => $block) {
            $block_plugin = $block->getPlugin();
            if ($block_plugin instanceof MainContentBlockPluginInterface) {
              $block_plugin->setMainContent($this->mainContent);
              $main_content_block_displayed = TRUE;
            }
            elseif ($block_plugin instanceof TitleBlockPluginInterface) {
              $block_plugin->setTitle($this->title);
            }
      //...
```
This means that if I create a custom block that implements `TitleBlockPluginInterface` I will get the page title automatically (thanks to `BlockPageVariant`)? Apparently, yes.

Lets start writing the custom block extending `PageTitleBlock` to use the title field implementation:

```php
    /**
     * @Block(
     *   id = "my_image_title_block",
     *   admin_label = "Image title block"
     * )
     */
    class ImageTitleBlock extends PageTitleBlock {

      /**
       * The image field.
       *
       * @var mixed
       */
      protected $image;

      public function defaultConfiguration() {
        return [
          'image' => [
            'value' => '',
          ],
          'label_display' => FALSE,
        ] + parent::defaultConfiguration();
      }

      /**
       * {@inheritdoc}
       */
      public function build() {
        $build = [];

        if (isset($this->configuration['image'])
          && !empty($this->configuration['image'])) {

          $image_field = $this->configuration['image'];
          $image_uri = File::load($image_field[0]);

          $build['image'] = [
            'uri' => ImageStyle::load('title_bar')->buildUrl($image_uri->getFileUri()),
          ];
        } else {
          $build['image']['#markup'] = '[' . t('Picture') . ']';
        }


        return $build + parent::build();
      }

      /**
       * {@inheritdoc}
       */
      public function blockForm($form, FormStateInterface $form_state) {

        $form['image'] = array(
          '#type' => 'managed_file',
          '#upload_location' => 'public://images/',
          '#title' => $this->t('Image'),
          '#description' => $this->t("Background image"),
          '#default_value' => $this->configuration['image'],
          '#upload_validators' => array(
            'file_validate_extensions' => array('gif png jpg jpeg'),
            'file_validate_size' => array(25600000),
          ),
          '#states' => array(
            'visible' => array(
              ':input[name="image_type"]' => array('value' => t('Upload New Image')),
            )
          )
        );

        return $form;
      }

      public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
        if (!$form_state->getValue('image')) {
          $form_state->setError($form['image'], $this->t('Select an image'));
        }
      }

      /**
       * {@inheritdoc}
       */
      public function blockSubmit($form, FormStateInterface $form_state) {
        /* Fetch the array of the file stored temporarily in database */
        $image = $form_state->getValue('image');

        $this->configuration['image'] = $image;

        /* Load the object of the file by it's fid */
        $file = \Drupal\file\Entity\File::load($image[0]);

        /* Set the status flag permanent of the file object */
        $file->setPermanent();

        /* Save the file in database */
        $file->save();
      }
    }
```


After clearing Drupal cache, you will find your new shiny block waiting for you in the *Add block* list. The build method returns the processed image URL (using *title_bar* style) instead of the render array for an image so we can use it later.

Let’s create *title_bar* image style and configure it accordingly (in my case, resize and crop to a predefined size will do).


![](https://d2mxuefqeaa7sj.cloudfront.net/s_58B000CCEE244A0B10193C36972405EDDB99EDFC2E3CC8B2EF3D6B543327D95C_1520464421443_image.png)


Then, update your theme to make sure that image url shows in a `style` attribute, or a `data-*` if you’re using javascript to load the image.

*block—image-title-block.html.twig*
```twig
    <div{{ attributes.setAttribute('style',
        'background: #787c8a url(' ~ content.image.uri ~ ') no-repeat center;') }}>
      {{ title_prefix }}
      {% if label %}
        <h2{{ title_attributes }}>{{ label }}</h2>
      {% endif %}
      {{ title_suffix }}
      {% block content %}
        {{ content }}
      {% endblock %}
    </div>
    ...
```
Lets test it!


![](https://d2mxuefqeaa7sj.cloudfront.net/s_58B000CCEE244A0B10193C36972405EDDB99EDFC2E3CC8B2EF3D6B543327D95C_1520465614212_image.png)
![](https://d2mxuefqeaa7sj.cloudfront.net/s_58B000CCEE244A0B10193C36972405EDDB99EDFC2E3CC8B2EF3D6B543327D95C_1520465649359_image.png)
![](https://d2mxuefqeaa7sj.cloudfront.net/s_58B000CCEE244A0B10193C36972405EDDB99EDFC2E3CC8B2EF3D6B543327D95C_1520465716498_image.png)