Drupal 8 Theming: How to Set Custom HTML Classes in a Block Region

Drupal 8 theming awesomeness

Now that I'm digging into Drupal 8 theming and its awesomeness, I'm discovering some really useful methods and functions. At the same time, I'm learning a lot and having fun.

In this post I'll show you how you can set a custom HTML class within a block region. I'll be doing this in a sub-theme that uses Drupal 8's Classy as a base-theme.

Our use case is that there are three "preface" block regions defined in a Classy sub-theme, "First", "Second", and "Third." When these regions render as HTML, Classy gives them one common class called region. We'd like to have something more specific such as region--preface that can be used as a class for theming any of these preface regions.

Getting started, examine the array

The first thing to do is enable Devel Kint to examine the block region array. Kint is part of the Devel module and you can either download it from drupal.org or use Drush. Right now, Devel for Drupal 8 is available as a dev release; using drush we can download and enable it using these commands.


drush dl devel-8.x-1.x-dev -y
drush en kint -y

Next, I'll add a template_preprocess_region in my sub-theme's .theme file and kint() the vars to see what's going on. In some cases, using kint right in a Twig template works well but in this case, you'll get much more info by using it as we do below in our .theme file.


function mysubtheme_preprocess_region(&$vars) {
 kint($vars);
}

Once I do this, I run a drush cr and reload the page that has one of my preface regions on it. Here I see the array path to the region name and it's elements > #region.

Devel kint() printing out array paths

So now in our preprocess region I can define that array path.


function mysubtheme_preprocess_region(&$vars) {
  $region = $vars['elements']['#region'];
}

Note, you can also look in core's theme.inc file to see how the region variables are defined and when I do that, I see something pretty similar to the above:


  $variables['region'] = $variables['elements']['#region'];

The next thing I am going to do is create an array of my three preface regions that have already been defined in the theme:


 $region_preface = array (
    'preface_first',
    'preface_second',
    'preface_third',
  );

Now that I define the array, I will set a common class for these three regions:


  if (in_array($region, $region_preface)) {
    $vars['attributes']['class'][] = 'region--preface';
  }
  

Putting it all together


function mysubtheme_preprocess_region(&$vars) {
  $region = $vars['elements']['#region'];
  
   $region_preface = array (
    'preface_first',
    'preface_second',
    'preface_third',
  );
  
   if (in_array($region, $region_preface)) {
     $vars['attributes']['class'][] = 'region--preface';
  }
}

Alternate Method using Twig set classes = []

One other way to set a custom class is to use the new set classes = [] method in a Twig template. So instead of setting the class in the .theme file, we'll create a variable for use in Twig.


  if (in_array($region, $region_preface)) {
   $vars['region_preface'] = 'region--preface';
  }

To make use of this variable, I've already gone ahead and copied Classy's region.html.twig into my sub-theme's template folder. I generally keep the same template folder structure in my sub-theme that classy gives you which looks something like this:


|____templates
| |____block
| |____content
| |____content-edit
| |____dataset
| |____field
| |____form
| |____layout
| |____misc
| |____navigation
| |____user
| |____views

Now in my region.html.twig, I look for this existing code:


{%
  set classes = [
    'region',
    'region-' ~ region|clean_class,
  ]
%}

Now we add the variable, region_preface, that we created in our preprocess function.


{%
  set classes = [
    'region',
    'region-' ~ region|clean_class,
     region_preface|clean_class,
  ]
%}

Of note above is clean_class which "prepares a string for use as a valid HTML class name." In other words, it removes invalid characters from our HTML classes so they render in a nice manner. We don't really need it here but it's nice to have and get used to using.

With either method above, be sure to run a drush cr and reload your page. The HTML output should look something like this.


<div class="region region-preface-first region--preface">

Now we can utilize the new common class region--preface for theming all preface regions with common attributes.

Summary

The above tutorial starts to give us a little insight into Drupal 8 theming. As with all things Drupal, there are often several ways to do the same task so by no means are the methods above definitive. In a future post, I'll expand on this a bit and add a class based on a variable value.

Tags 

  • Drupal 8
  • Twig
  • Theming
  • Drupal Planet

Resources 

Comments or questions about this post?

Feel free to @reply me on Twitter!

Share